From bc8c8c12da9514d7085c87bbe14b290a6556ef44 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Fri, 30 Aug 2024 20:36:10 +0200 Subject: [PATCH 001/107] generate new server client --- .../external/backend-api/src/services.gen.ts | 66 +++++++++-- .../src/external/backend-api/src/types.gen.ts | 106 +++++++++++++++++- 2 files changed, 161 insertions(+), 11 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/external/backend-api/src/services.gen.ts b/src/Umbraco.Web.UI.Client/src/external/backend-api/src/services.gen.ts index c6edaee403..63fb202bed 100644 --- a/src/Umbraco.Web.UI.Client/src/external/backend-api/src/services.gen.ts +++ b/src/Umbraco.Web.UI.Client/src/external/backend-api/src/services.gen.ts @@ -3,7 +3,7 @@ import type { CancelablePromise } from './core/CancelablePromise'; import { OpenAPI } from './core/OpenAPI'; import { request as __request } from './core/request'; -import type { GetCultureData, GetCultureResponse, PostDataTypeData, PostDataTypeResponse, GetDataTypeByIdData, GetDataTypeByIdResponse, DeleteDataTypeByIdData, DeleteDataTypeByIdResponse, PutDataTypeByIdData, PutDataTypeByIdResponse, PostDataTypeByIdCopyData, PostDataTypeByIdCopyResponse, GetDataTypeByIdIsUsedData, GetDataTypeByIdIsUsedResponse, PutDataTypeByIdMoveData, PutDataTypeByIdMoveResponse, GetDataTypeByIdReferencesData, GetDataTypeByIdReferencesResponse, GetDataTypeConfigurationResponse, PostDataTypeFolderData, PostDataTypeFolderResponse, GetDataTypeFolderByIdData, GetDataTypeFolderByIdResponse, DeleteDataTypeFolderByIdData, DeleteDataTypeFolderByIdResponse, PutDataTypeFolderByIdData, PutDataTypeFolderByIdResponse, GetFilterDataTypeData, GetFilterDataTypeResponse, GetItemDataTypeData, GetItemDataTypeResponse, GetItemDataTypeSearchData, GetItemDataTypeSearchResponse, GetTreeDataTypeAncestorsData, GetTreeDataTypeAncestorsResponse, GetTreeDataTypeChildrenData, GetTreeDataTypeChildrenResponse, GetTreeDataTypeRootData, GetTreeDataTypeRootResponse, GetDictionaryData, GetDictionaryResponse, PostDictionaryData, PostDictionaryResponse, GetDictionaryByIdData, GetDictionaryByIdResponse, DeleteDictionaryByIdData, DeleteDictionaryByIdResponse, PutDictionaryByIdData, PutDictionaryByIdResponse, GetDictionaryByIdExportData, GetDictionaryByIdExportResponse, PutDictionaryByIdMoveData, PutDictionaryByIdMoveResponse, PostDictionaryImportData, PostDictionaryImportResponse, GetItemDictionaryData, GetItemDictionaryResponse, GetTreeDictionaryAncestorsData, GetTreeDictionaryAncestorsResponse, GetTreeDictionaryChildrenData, GetTreeDictionaryChildrenResponse, GetTreeDictionaryRootData, GetTreeDictionaryRootResponse, PostDocumentBlueprintData, PostDocumentBlueprintResponse, GetDocumentBlueprintByIdData, GetDocumentBlueprintByIdResponse, DeleteDocumentBlueprintByIdData, DeleteDocumentBlueprintByIdResponse, PutDocumentBlueprintByIdData, PutDocumentBlueprintByIdResponse, PutDocumentBlueprintByIdMoveData, PutDocumentBlueprintByIdMoveResponse, PostDocumentBlueprintFolderData, PostDocumentBlueprintFolderResponse, GetDocumentBlueprintFolderByIdData, GetDocumentBlueprintFolderByIdResponse, DeleteDocumentBlueprintFolderByIdData, DeleteDocumentBlueprintFolderByIdResponse, PutDocumentBlueprintFolderByIdData, PutDocumentBlueprintFolderByIdResponse, PostDocumentBlueprintFromDocumentData, PostDocumentBlueprintFromDocumentResponse, GetItemDocumentBlueprintData, GetItemDocumentBlueprintResponse, GetTreeDocumentBlueprintAncestorsData, GetTreeDocumentBlueprintAncestorsResponse, GetTreeDocumentBlueprintChildrenData, GetTreeDocumentBlueprintChildrenResponse, GetTreeDocumentBlueprintRootData, GetTreeDocumentBlueprintRootResponse, PostDocumentTypeData, PostDocumentTypeResponse, GetDocumentTypeByIdData, GetDocumentTypeByIdResponse, DeleteDocumentTypeByIdData, DeleteDocumentTypeByIdResponse, PutDocumentTypeByIdData, PutDocumentTypeByIdResponse, GetDocumentTypeByIdAllowedChildrenData, GetDocumentTypeByIdAllowedChildrenResponse, GetDocumentTypeByIdBlueprintData, GetDocumentTypeByIdBlueprintResponse, GetDocumentTypeByIdCompositionReferencesData, GetDocumentTypeByIdCompositionReferencesResponse, PostDocumentTypeByIdCopyData, PostDocumentTypeByIdCopyResponse, GetDocumentTypeByIdExportData, GetDocumentTypeByIdExportResponse, PutDocumentTypeByIdImportData, PutDocumentTypeByIdImportResponse, PutDocumentTypeByIdMoveData, PutDocumentTypeByIdMoveResponse, GetDocumentTypeAllowedAtRootData, GetDocumentTypeAllowedAtRootResponse, PostDocumentTypeAvailableCompositionsData, PostDocumentTypeAvailableCompositionsResponse, GetDocumentTypeConfigurationResponse, PostDocumentTypeFolderData, PostDocumentTypeFolderResponse, GetDocumentTypeFolderByIdData, GetDocumentTypeFolderByIdResponse, DeleteDocumentTypeFolderByIdData, DeleteDocumentTypeFolderByIdResponse, PutDocumentTypeFolderByIdData, PutDocumentTypeFolderByIdResponse, PostDocumentTypeImportData, PostDocumentTypeImportResponse, GetItemDocumentTypeData, GetItemDocumentTypeResponse, GetItemDocumentTypeSearchData, GetItemDocumentTypeSearchResponse, GetTreeDocumentTypeAncestorsData, GetTreeDocumentTypeAncestorsResponse, GetTreeDocumentTypeChildrenData, GetTreeDocumentTypeChildrenResponse, GetTreeDocumentTypeRootData, GetTreeDocumentTypeRootResponse, GetDocumentVersionData, GetDocumentVersionResponse, GetDocumentVersionByIdData, GetDocumentVersionByIdResponse, PutDocumentVersionByIdPreventCleanupData, PutDocumentVersionByIdPreventCleanupResponse, PostDocumentVersionByIdRollbackData, PostDocumentVersionByIdRollbackResponse, GetCollectionDocumentByIdData, GetCollectionDocumentByIdResponse, PostDocumentData, PostDocumentResponse, GetDocumentByIdData, GetDocumentByIdResponse, DeleteDocumentByIdData, DeleteDocumentByIdResponse, PutDocumentByIdData, PutDocumentByIdResponse, GetDocumentByIdAuditLogData, GetDocumentByIdAuditLogResponse, PostDocumentByIdCopyData, PostDocumentByIdCopyResponse, GetDocumentByIdDomainsData, GetDocumentByIdDomainsResponse, PutDocumentByIdDomainsData, PutDocumentByIdDomainsResponse, PutDocumentByIdMoveData, PutDocumentByIdMoveResponse, PutDocumentByIdMoveToRecycleBinData, PutDocumentByIdMoveToRecycleBinResponse, GetDocumentByIdNotificationsData, GetDocumentByIdNotificationsResponse, PutDocumentByIdNotificationsData, PutDocumentByIdNotificationsResponse, PostDocumentByIdPublicAccessData, PostDocumentByIdPublicAccessResponse, DeleteDocumentByIdPublicAccessData, DeleteDocumentByIdPublicAccessResponse, GetDocumentByIdPublicAccessData, GetDocumentByIdPublicAccessResponse, PutDocumentByIdPublicAccessData, PutDocumentByIdPublicAccessResponse, PutDocumentByIdPublishData, PutDocumentByIdPublishResponse, PutDocumentByIdPublishWithDescendantsData, PutDocumentByIdPublishWithDescendantsResponse, GetDocumentByIdReferencedByData, GetDocumentByIdReferencedByResponse, GetDocumentByIdReferencedDescendantsData, GetDocumentByIdReferencedDescendantsResponse, PutDocumentByIdUnpublishData, PutDocumentByIdUnpublishResponse, PutDocumentByIdValidateData, PutDocumentByIdValidateResponse, GetDocumentAreReferencedData, GetDocumentAreReferencedResponse, GetDocumentConfigurationResponse, PutDocumentSortData, PutDocumentSortResponse, GetDocumentUrlsData, GetDocumentUrlsResponse, PostDocumentValidateData, PostDocumentValidateResponse, GetItemDocumentData, GetItemDocumentResponse, GetItemDocumentSearchData, GetItemDocumentSearchResponse, DeleteRecycleBinDocumentResponse, DeleteRecycleBinDocumentByIdData, DeleteRecycleBinDocumentByIdResponse, GetRecycleBinDocumentByIdOriginalParentData, GetRecycleBinDocumentByIdOriginalParentResponse, PutRecycleBinDocumentByIdRestoreData, PutRecycleBinDocumentByIdRestoreResponse, GetRecycleBinDocumentChildrenData, GetRecycleBinDocumentChildrenResponse, GetRecycleBinDocumentRootData, GetRecycleBinDocumentRootResponse, GetTreeDocumentAncestorsData, GetTreeDocumentAncestorsResponse, GetTreeDocumentChildrenData, GetTreeDocumentChildrenResponse, GetTreeDocumentRootData, GetTreeDocumentRootResponse, PostDynamicRootQueryData, PostDynamicRootQueryResponse, GetDynamicRootStepsResponse, GetHealthCheckGroupData, GetHealthCheckGroupResponse, GetHealthCheckGroupByNameData, GetHealthCheckGroupByNameResponse, PostHealthCheckGroupByNameCheckData, PostHealthCheckGroupByNameCheckResponse, PostHealthCheckExecuteActionData, PostHealthCheckExecuteActionResponse, GetHelpData, GetHelpResponse, GetImagingResizeUrlsData, GetImagingResizeUrlsResponse, GetImportAnalyzeData, GetImportAnalyzeResponse, GetIndexerData, GetIndexerResponse, GetIndexerByIndexNameData, GetIndexerByIndexNameResponse, PostIndexerByIndexNameRebuildData, PostIndexerByIndexNameRebuildResponse, GetInstallSettingsResponse, PostInstallSetupData, PostInstallSetupResponse, PostInstallValidateDatabaseData, PostInstallValidateDatabaseResponse, GetItemLanguageData, GetItemLanguageResponse, GetItemLanguageDefaultResponse, GetLanguageData, GetLanguageResponse, PostLanguageData, PostLanguageResponse, GetLanguageByIsoCodeData, GetLanguageByIsoCodeResponse, DeleteLanguageByIsoCodeData, DeleteLanguageByIsoCodeResponse, PutLanguageByIsoCodeData, PutLanguageByIsoCodeResponse, GetLogViewerLevelData, GetLogViewerLevelResponse, GetLogViewerLevelCountData, GetLogViewerLevelCountResponse, GetLogViewerLogData, GetLogViewerLogResponse, GetLogViewerMessageTemplateData, GetLogViewerMessageTemplateResponse, GetLogViewerSavedSearchData, GetLogViewerSavedSearchResponse, PostLogViewerSavedSearchData, PostLogViewerSavedSearchResponse, GetLogViewerSavedSearchByNameData, GetLogViewerSavedSearchByNameResponse, DeleteLogViewerSavedSearchByNameData, DeleteLogViewerSavedSearchByNameResponse, GetLogViewerValidateLogsSizeData, GetLogViewerValidateLogsSizeResponse, GetManifestManifestResponse, GetManifestManifestPrivateResponse, GetManifestManifestPublicResponse, GetItemMediaTypeData, GetItemMediaTypeResponse, GetItemMediaTypeAllowedData, GetItemMediaTypeAllowedResponse, GetItemMediaTypeFoldersData, GetItemMediaTypeFoldersResponse, GetItemMediaTypeSearchData, GetItemMediaTypeSearchResponse, PostMediaTypeData, PostMediaTypeResponse, GetMediaTypeByIdData, GetMediaTypeByIdResponse, DeleteMediaTypeByIdData, DeleteMediaTypeByIdResponse, PutMediaTypeByIdData, PutMediaTypeByIdResponse, GetMediaTypeByIdAllowedChildrenData, GetMediaTypeByIdAllowedChildrenResponse, GetMediaTypeByIdCompositionReferencesData, GetMediaTypeByIdCompositionReferencesResponse, PostMediaTypeByIdCopyData, PostMediaTypeByIdCopyResponse, GetMediaTypeByIdExportData, GetMediaTypeByIdExportResponse, PutMediaTypeByIdImportData, PutMediaTypeByIdImportResponse, PutMediaTypeByIdMoveData, PutMediaTypeByIdMoveResponse, GetMediaTypeAllowedAtRootData, GetMediaTypeAllowedAtRootResponse, PostMediaTypeAvailableCompositionsData, PostMediaTypeAvailableCompositionsResponse, GetMediaTypeConfigurationResponse, PostMediaTypeFolderData, PostMediaTypeFolderResponse, GetMediaTypeFolderByIdData, GetMediaTypeFolderByIdResponse, DeleteMediaTypeFolderByIdData, DeleteMediaTypeFolderByIdResponse, PutMediaTypeFolderByIdData, PutMediaTypeFolderByIdResponse, PostMediaTypeImportData, PostMediaTypeImportResponse, GetTreeMediaTypeAncestorsData, GetTreeMediaTypeAncestorsResponse, GetTreeMediaTypeChildrenData, GetTreeMediaTypeChildrenResponse, GetTreeMediaTypeRootData, GetTreeMediaTypeRootResponse, GetCollectionMediaData, GetCollectionMediaResponse, GetItemMediaData, GetItemMediaResponse, GetItemMediaSearchData, GetItemMediaSearchResponse, PostMediaData, PostMediaResponse, GetMediaByIdData, GetMediaByIdResponse, DeleteMediaByIdData, DeleteMediaByIdResponse, PutMediaByIdData, PutMediaByIdResponse, GetMediaByIdAuditLogData, GetMediaByIdAuditLogResponse, PutMediaByIdMoveData, PutMediaByIdMoveResponse, PutMediaByIdMoveToRecycleBinData, PutMediaByIdMoveToRecycleBinResponse, GetMediaByIdReferencedByData, GetMediaByIdReferencedByResponse, GetMediaByIdReferencedDescendantsData, GetMediaByIdReferencedDescendantsResponse, PutMediaByIdValidateData, PutMediaByIdValidateResponse, GetMediaAreReferencedData, GetMediaAreReferencedResponse, GetMediaConfigurationResponse, PutMediaSortData, PutMediaSortResponse, GetMediaUrlsData, GetMediaUrlsResponse, PostMediaValidateData, PostMediaValidateResponse, DeleteRecycleBinMediaResponse, DeleteRecycleBinMediaByIdData, DeleteRecycleBinMediaByIdResponse, GetRecycleBinMediaByIdOriginalParentData, GetRecycleBinMediaByIdOriginalParentResponse, PutRecycleBinMediaByIdRestoreData, PutRecycleBinMediaByIdRestoreResponse, GetRecycleBinMediaChildrenData, GetRecycleBinMediaChildrenResponse, GetRecycleBinMediaRootData, GetRecycleBinMediaRootResponse, GetTreeMediaAncestorsData, GetTreeMediaAncestorsResponse, GetTreeMediaChildrenData, GetTreeMediaChildrenResponse, GetTreeMediaRootData, GetTreeMediaRootResponse, GetItemMemberGroupData, GetItemMemberGroupResponse, GetMemberGroupData, GetMemberGroupResponse, PostMemberGroupData, PostMemberGroupResponse, GetMemberGroupByIdData, GetMemberGroupByIdResponse, DeleteMemberGroupByIdData, DeleteMemberGroupByIdResponse, PutMemberGroupByIdData, PutMemberGroupByIdResponse, GetTreeMemberGroupRootData, GetTreeMemberGroupRootResponse, GetItemMemberTypeData, GetItemMemberTypeResponse, GetItemMemberTypeSearchData, GetItemMemberTypeSearchResponse, PostMemberTypeData, PostMemberTypeResponse, GetMemberTypeByIdData, GetMemberTypeByIdResponse, DeleteMemberTypeByIdData, DeleteMemberTypeByIdResponse, PutMemberTypeByIdData, PutMemberTypeByIdResponse, GetMemberTypeByIdCompositionReferencesData, GetMemberTypeByIdCompositionReferencesResponse, PostMemberTypeByIdCopyData, PostMemberTypeByIdCopyResponse, PostMemberTypeAvailableCompositionsData, PostMemberTypeAvailableCompositionsResponse, GetMemberTypeConfigurationResponse, GetTreeMemberTypeRootData, GetTreeMemberTypeRootResponse, GetFilterMemberData, GetFilterMemberResponse, GetItemMemberData, GetItemMemberResponse, GetItemMemberSearchData, GetItemMemberSearchResponse, PostMemberData, PostMemberResponse, GetMemberByIdData, GetMemberByIdResponse, DeleteMemberByIdData, DeleteMemberByIdResponse, PutMemberByIdData, PutMemberByIdResponse, PutMemberByIdValidateData, PutMemberByIdValidateResponse, GetMemberConfigurationResponse, PostMemberValidateData, PostMemberValidateResponse, PostModelsBuilderBuildResponse, GetModelsBuilderDashboardResponse, GetModelsBuilderStatusResponse, GetObjectTypesData, GetObjectTypesResponse, GetOembedQueryData, GetOembedQueryResponse, PostPackageByNameRunMigrationData, PostPackageByNameRunMigrationResponse, GetPackageConfigurationResponse, GetPackageCreatedData, GetPackageCreatedResponse, PostPackageCreatedData, PostPackageCreatedResponse, GetPackageCreatedByIdData, GetPackageCreatedByIdResponse, DeletePackageCreatedByIdData, DeletePackageCreatedByIdResponse, PutPackageCreatedByIdData, PutPackageCreatedByIdResponse, GetPackageCreatedByIdDownloadData, GetPackageCreatedByIdDownloadResponse, GetPackageMigrationStatusData, GetPackageMigrationStatusResponse, GetItemPartialViewData, GetItemPartialViewResponse, PostPartialViewData, PostPartialViewResponse, GetPartialViewByPathData, GetPartialViewByPathResponse, DeletePartialViewByPathData, DeletePartialViewByPathResponse, PutPartialViewByPathData, PutPartialViewByPathResponse, PutPartialViewByPathRenameData, PutPartialViewByPathRenameResponse, PostPartialViewFolderData, PostPartialViewFolderResponse, GetPartialViewFolderByPathData, GetPartialViewFolderByPathResponse, DeletePartialViewFolderByPathData, DeletePartialViewFolderByPathResponse, GetPartialViewSnippetData, GetPartialViewSnippetResponse, GetPartialViewSnippetByIdData, GetPartialViewSnippetByIdResponse, GetTreePartialViewAncestorsData, GetTreePartialViewAncestorsResponse, GetTreePartialViewChildrenData, GetTreePartialViewChildrenResponse, GetTreePartialViewRootData, GetTreePartialViewRootResponse, DeletePreviewResponse, PostPreviewResponse, GetProfilingStatusResponse, PutProfilingStatusData, PutProfilingStatusResponse, GetPropertyTypeIsUsedData, GetPropertyTypeIsUsedResponse, PostPublishedCacheCollectResponse, PostPublishedCacheRebuildResponse, PostPublishedCacheReloadResponse, GetPublishedCacheStatusResponse, GetRedirectManagementData, GetRedirectManagementResponse, GetRedirectManagementByIdData, GetRedirectManagementByIdResponse, DeleteRedirectManagementByIdData, DeleteRedirectManagementByIdResponse, GetRedirectManagementStatusResponse, PostRedirectManagementStatusData, PostRedirectManagementStatusResponse, GetItemRelationTypeData, GetItemRelationTypeResponse, GetRelationTypeData, GetRelationTypeResponse, GetRelationTypeByIdData, GetRelationTypeByIdResponse, GetRelationByRelationTypeIdData, GetRelationByRelationTypeIdResponse, GetItemScriptData, GetItemScriptResponse, PostScriptData, PostScriptResponse, GetScriptByPathData, GetScriptByPathResponse, DeleteScriptByPathData, DeleteScriptByPathResponse, PutScriptByPathData, PutScriptByPathResponse, PutScriptByPathRenameData, PutScriptByPathRenameResponse, PostScriptFolderData, PostScriptFolderResponse, GetScriptFolderByPathData, GetScriptFolderByPathResponse, DeleteScriptFolderByPathData, DeleteScriptFolderByPathResponse, GetTreeScriptAncestorsData, GetTreeScriptAncestorsResponse, GetTreeScriptChildrenData, GetTreeScriptChildrenResponse, GetTreeScriptRootData, GetTreeScriptRootResponse, GetSearcherData, GetSearcherResponse, GetSearcherBySearcherNameQueryData, GetSearcherBySearcherNameQueryResponse, GetSecurityConfigurationResponse, PostSecurityForgotPasswordData, PostSecurityForgotPasswordResponse, PostSecurityForgotPasswordResetData, PostSecurityForgotPasswordResetResponse, PostSecurityForgotPasswordVerifyData, PostSecurityForgotPasswordVerifyResponse, GetSegmentData, GetSegmentResponse, GetServerConfigurationResponse, GetServerInformationResponse, GetServerStatusResponse, GetServerTroubleshootingResponse, GetItemStaticFileData, GetItemStaticFileResponse, GetTreeStaticFileAncestorsData, GetTreeStaticFileAncestorsResponse, GetTreeStaticFileChildrenData, GetTreeStaticFileChildrenResponse, GetTreeStaticFileRootData, GetTreeStaticFileRootResponse, GetItemStylesheetData, GetItemStylesheetResponse, PostStylesheetData, PostStylesheetResponse, GetStylesheetByPathData, GetStylesheetByPathResponse, DeleteStylesheetByPathData, DeleteStylesheetByPathResponse, PutStylesheetByPathData, PutStylesheetByPathResponse, PutStylesheetByPathRenameData, PutStylesheetByPathRenameResponse, PostStylesheetFolderData, PostStylesheetFolderResponse, GetStylesheetFolderByPathData, GetStylesheetFolderByPathResponse, DeleteStylesheetFolderByPathData, DeleteStylesheetFolderByPathResponse, GetTreeStylesheetAncestorsData, GetTreeStylesheetAncestorsResponse, GetTreeStylesheetChildrenData, GetTreeStylesheetChildrenResponse, GetTreeStylesheetRootData, GetTreeStylesheetRootResponse, GetTagData, GetTagResponse, GetTelemetryData, GetTelemetryResponse, GetTelemetryLevelResponse, PostTelemetryLevelData, PostTelemetryLevelResponse, GetItemTemplateData, GetItemTemplateResponse, GetItemTemplateSearchData, GetItemTemplateSearchResponse, PostTemplateData, PostTemplateResponse, GetTemplateByIdData, GetTemplateByIdResponse, DeleteTemplateByIdData, DeleteTemplateByIdResponse, PutTemplateByIdData, PutTemplateByIdResponse, GetTemplateConfigurationResponse, PostTemplateQueryExecuteData, PostTemplateQueryExecuteResponse, GetTemplateQuerySettingsResponse, GetTreeTemplateAncestorsData, GetTreeTemplateAncestorsResponse, GetTreeTemplateChildrenData, GetTreeTemplateChildrenResponse, GetTreeTemplateRootData, GetTreeTemplateRootResponse, PostTemporaryFileData, PostTemporaryFileResponse, GetTemporaryFileByIdData, GetTemporaryFileByIdResponse, DeleteTemporaryFileByIdData, DeleteTemporaryFileByIdResponse, GetTemporaryFileConfigurationResponse, PostUpgradeAuthorizeResponse, GetUpgradeSettingsResponse, PostUserDataData, PostUserDataResponse, GetUserDataData, GetUserDataResponse, PutUserDataData, PutUserDataResponse, GetUserDataByIdData, GetUserDataByIdResponse, GetFilterUserGroupData, GetFilterUserGroupResponse, GetItemUserGroupData, GetItemUserGroupResponse, DeleteUserGroupData, DeleteUserGroupResponse, PostUserGroupData, PostUserGroupResponse, GetUserGroupData, GetUserGroupResponse, GetUserGroupByIdData, GetUserGroupByIdResponse, DeleteUserGroupByIdData, DeleteUserGroupByIdResponse, PutUserGroupByIdData, PutUserGroupByIdResponse, DeleteUserGroupByIdUsersData, DeleteUserGroupByIdUsersResponse, PostUserGroupByIdUsersData, PostUserGroupByIdUsersResponse, GetFilterUserData, GetFilterUserResponse, GetItemUserData, GetItemUserResponse, PostUserData, PostUserResponse, DeleteUserData, DeleteUserResponse, GetUserData, GetUserResponse, GetUserByIdData, GetUserByIdResponse, DeleteUserByIdData, DeleteUserByIdResponse, PutUserByIdData, PutUserByIdResponse, GetUserById2FaData, GetUserById2FaResponse, DeleteUserById2FaByProviderNameData, DeleteUserById2FaByProviderNameResponse, GetUserByIdCalculateStartNodesData, GetUserByIdCalculateStartNodesResponse, PostUserByIdChangePasswordData, PostUserByIdChangePasswordResponse, PostUserByIdResetPasswordData, PostUserByIdResetPasswordResponse, DeleteUserAvatarByIdData, DeleteUserAvatarByIdResponse, PostUserAvatarByIdData, PostUserAvatarByIdResponse, GetUserConfigurationResponse, GetUserCurrentResponse, GetUserCurrent2FaResponse, DeleteUserCurrent2FaByProviderNameData, DeleteUserCurrent2FaByProviderNameResponse, PostUserCurrent2FaByProviderNameData, PostUserCurrent2FaByProviderNameResponse, GetUserCurrent2FaByProviderNameData, GetUserCurrent2FaByProviderNameResponse, PostUserCurrentAvatarData, PostUserCurrentAvatarResponse, PostUserCurrentChangePasswordData, PostUserCurrentChangePasswordResponse, GetUserCurrentConfigurationResponse, GetUserCurrentLoginProvidersResponse, GetUserCurrentPermissionsData, GetUserCurrentPermissionsResponse, GetUserCurrentPermissionsDocumentData, GetUserCurrentPermissionsDocumentResponse, GetUserCurrentPermissionsMediaData, GetUserCurrentPermissionsMediaResponse, PostUserDisableData, PostUserDisableResponse, PostUserEnableData, PostUserEnableResponse, PostUserInviteData, PostUserInviteResponse, PostUserInviteCreatePasswordData, PostUserInviteCreatePasswordResponse, PostUserInviteResendData, PostUserInviteResendResponse, PostUserInviteVerifyData, PostUserInviteVerifyResponse, PostUserSetUserGroupsData, PostUserSetUserGroupsResponse, PostUserUnlockData, PostUserUnlockResponse, GetItemWebhookData, GetItemWebhookResponse, GetWebhookData, GetWebhookResponse, PostWebhookData, PostWebhookResponse, GetWebhookByIdData, GetWebhookByIdResponse, DeleteWebhookByIdData, DeleteWebhookByIdResponse, PutWebhookByIdData, PutWebhookByIdResponse, GetWebhookEventsData, GetWebhookEventsResponse, PostCurrentUserChangePasswordData, PostCurrentUserChangePasswordResponse } from './types.gen'; +import type { GetCultureData, GetCultureResponse, PostDataTypeData, PostDataTypeResponse, GetDataTypeByIdData, GetDataTypeByIdResponse, DeleteDataTypeByIdData, DeleteDataTypeByIdResponse, PutDataTypeByIdData, PutDataTypeByIdResponse, PostDataTypeByIdCopyData, PostDataTypeByIdCopyResponse, GetDataTypeByIdIsUsedData, GetDataTypeByIdIsUsedResponse, PutDataTypeByIdMoveData, PutDataTypeByIdMoveResponse, GetDataTypeByIdReferencesData, GetDataTypeByIdReferencesResponse, GetDataTypeConfigurationResponse, PostDataTypeFolderData, PostDataTypeFolderResponse, GetDataTypeFolderByIdData, GetDataTypeFolderByIdResponse, DeleteDataTypeFolderByIdData, DeleteDataTypeFolderByIdResponse, PutDataTypeFolderByIdData, PutDataTypeFolderByIdResponse, GetFilterDataTypeData, GetFilterDataTypeResponse, GetItemDataTypeData, GetItemDataTypeResponse, GetItemDataTypeSearchData, GetItemDataTypeSearchResponse, GetTreeDataTypeAncestorsData, GetTreeDataTypeAncestorsResponse, GetTreeDataTypeChildrenData, GetTreeDataTypeChildrenResponse, GetTreeDataTypeRootData, GetTreeDataTypeRootResponse, GetDictionaryData, GetDictionaryResponse, PostDictionaryData, PostDictionaryResponse, GetDictionaryByIdData, GetDictionaryByIdResponse, DeleteDictionaryByIdData, DeleteDictionaryByIdResponse, PutDictionaryByIdData, PutDictionaryByIdResponse, GetDictionaryByIdExportData, GetDictionaryByIdExportResponse, PutDictionaryByIdMoveData, PutDictionaryByIdMoveResponse, PostDictionaryImportData, PostDictionaryImportResponse, GetItemDictionaryData, GetItemDictionaryResponse, GetTreeDictionaryAncestorsData, GetTreeDictionaryAncestorsResponse, GetTreeDictionaryChildrenData, GetTreeDictionaryChildrenResponse, GetTreeDictionaryRootData, GetTreeDictionaryRootResponse, PostDocumentBlueprintData, PostDocumentBlueprintResponse, GetDocumentBlueprintByIdData, GetDocumentBlueprintByIdResponse, DeleteDocumentBlueprintByIdData, DeleteDocumentBlueprintByIdResponse, PutDocumentBlueprintByIdData, PutDocumentBlueprintByIdResponse, PutDocumentBlueprintByIdMoveData, PutDocumentBlueprintByIdMoveResponse, PostDocumentBlueprintFolderData, PostDocumentBlueprintFolderResponse, GetDocumentBlueprintFolderByIdData, GetDocumentBlueprintFolderByIdResponse, DeleteDocumentBlueprintFolderByIdData, DeleteDocumentBlueprintFolderByIdResponse, PutDocumentBlueprintFolderByIdData, PutDocumentBlueprintFolderByIdResponse, PostDocumentBlueprintFromDocumentData, PostDocumentBlueprintFromDocumentResponse, GetItemDocumentBlueprintData, GetItemDocumentBlueprintResponse, GetTreeDocumentBlueprintAncestorsData, GetTreeDocumentBlueprintAncestorsResponse, GetTreeDocumentBlueprintChildrenData, GetTreeDocumentBlueprintChildrenResponse, GetTreeDocumentBlueprintRootData, GetTreeDocumentBlueprintRootResponse, PostDocumentTypeData, PostDocumentTypeResponse, GetDocumentTypeByIdData, GetDocumentTypeByIdResponse, DeleteDocumentTypeByIdData, DeleteDocumentTypeByIdResponse, PutDocumentTypeByIdData, PutDocumentTypeByIdResponse, GetDocumentTypeByIdAllowedChildrenData, GetDocumentTypeByIdAllowedChildrenResponse, GetDocumentTypeByIdBlueprintData, GetDocumentTypeByIdBlueprintResponse, GetDocumentTypeByIdCompositionReferencesData, GetDocumentTypeByIdCompositionReferencesResponse, PostDocumentTypeByIdCopyData, PostDocumentTypeByIdCopyResponse, GetDocumentTypeByIdExportData, GetDocumentTypeByIdExportResponse, PutDocumentTypeByIdImportData, PutDocumentTypeByIdImportResponse, PutDocumentTypeByIdMoveData, PutDocumentTypeByIdMoveResponse, GetDocumentTypeAllowedAtRootData, GetDocumentTypeAllowedAtRootResponse, PostDocumentTypeAvailableCompositionsData, PostDocumentTypeAvailableCompositionsResponse, GetDocumentTypeConfigurationResponse, PostDocumentTypeFolderData, PostDocumentTypeFolderResponse, GetDocumentTypeFolderByIdData, GetDocumentTypeFolderByIdResponse, DeleteDocumentTypeFolderByIdData, DeleteDocumentTypeFolderByIdResponse, PutDocumentTypeFolderByIdData, PutDocumentTypeFolderByIdResponse, PostDocumentTypeImportData, PostDocumentTypeImportResponse, GetItemDocumentTypeData, GetItemDocumentTypeResponse, GetItemDocumentTypeSearchData, GetItemDocumentTypeSearchResponse, GetTreeDocumentTypeAncestorsData, GetTreeDocumentTypeAncestorsResponse, GetTreeDocumentTypeChildrenData, GetTreeDocumentTypeChildrenResponse, GetTreeDocumentTypeRootData, GetTreeDocumentTypeRootResponse, GetDocumentVersionData, GetDocumentVersionResponse, GetDocumentVersionByIdData, GetDocumentVersionByIdResponse, PutDocumentVersionByIdPreventCleanupData, PutDocumentVersionByIdPreventCleanupResponse, PostDocumentVersionByIdRollbackData, PostDocumentVersionByIdRollbackResponse, GetCollectionDocumentByIdData, GetCollectionDocumentByIdResponse, PostDocumentData, PostDocumentResponse, GetDocumentByIdData, GetDocumentByIdResponse, DeleteDocumentByIdData, DeleteDocumentByIdResponse, PutDocumentByIdData, PutDocumentByIdResponse, GetDocumentByIdAuditLogData, GetDocumentByIdAuditLogResponse, PostDocumentByIdCopyData, PostDocumentByIdCopyResponse, GetDocumentByIdDomainsData, GetDocumentByIdDomainsResponse, PutDocumentByIdDomainsData, PutDocumentByIdDomainsResponse, PutDocumentByIdMoveData, PutDocumentByIdMoveResponse, PutDocumentByIdMoveToRecycleBinData, PutDocumentByIdMoveToRecycleBinResponse, GetDocumentByIdNotificationsData, GetDocumentByIdNotificationsResponse, PutDocumentByIdNotificationsData, PutDocumentByIdNotificationsResponse, PostDocumentByIdPublicAccessData, PostDocumentByIdPublicAccessResponse, DeleteDocumentByIdPublicAccessData, DeleteDocumentByIdPublicAccessResponse, GetDocumentByIdPublicAccessData, GetDocumentByIdPublicAccessResponse, PutDocumentByIdPublicAccessData, PutDocumentByIdPublicAccessResponse, PutDocumentByIdPublishData, PutDocumentByIdPublishResponse, PutDocumentByIdPublishWithDescendantsData, PutDocumentByIdPublishWithDescendantsResponse, GetDocumentByIdReferencedByData, GetDocumentByIdReferencedByResponse, GetDocumentByIdReferencedDescendantsData, GetDocumentByIdReferencedDescendantsResponse, PutDocumentByIdUnpublishData, PutDocumentByIdUnpublishResponse, PutDocumentByIdValidateData, PutDocumentByIdValidateResponse, GetDocumentAreReferencedData, GetDocumentAreReferencedResponse, GetDocumentConfigurationResponse, PutDocumentSortData, PutDocumentSortResponse, GetDocumentUrlsData, GetDocumentUrlsResponse, PostDocumentValidateData, PostDocumentValidateResponse, GetItemDocumentData, GetItemDocumentResponse, GetItemDocumentSearchData, GetItemDocumentSearchResponse, DeleteRecycleBinDocumentResponse, DeleteRecycleBinDocumentByIdData, DeleteRecycleBinDocumentByIdResponse, GetRecycleBinDocumentByIdOriginalParentData, GetRecycleBinDocumentByIdOriginalParentResponse, PutRecycleBinDocumentByIdRestoreData, PutRecycleBinDocumentByIdRestoreResponse, GetRecycleBinDocumentChildrenData, GetRecycleBinDocumentChildrenResponse, GetRecycleBinDocumentRootData, GetRecycleBinDocumentRootResponse, GetTreeDocumentAncestorsData, GetTreeDocumentAncestorsResponse, GetTreeDocumentChildrenData, GetTreeDocumentChildrenResponse, GetTreeDocumentRootData, GetTreeDocumentRootResponse, PostDynamicRootQueryData, PostDynamicRootQueryResponse, GetDynamicRootStepsResponse, GetHealthCheckGroupData, GetHealthCheckGroupResponse, GetHealthCheckGroupByNameData, GetHealthCheckGroupByNameResponse, PostHealthCheckGroupByNameCheckData, PostHealthCheckGroupByNameCheckResponse, PostHealthCheckExecuteActionData, PostHealthCheckExecuteActionResponse, GetHelpData, GetHelpResponse, GetImagingResizeUrlsData, GetImagingResizeUrlsResponse, GetImportAnalyzeData, GetImportAnalyzeResponse, GetIndexerData, GetIndexerResponse, GetIndexerByIndexNameData, GetIndexerByIndexNameResponse, PostIndexerByIndexNameRebuildData, PostIndexerByIndexNameRebuildResponse, GetInstallSettingsResponse, PostInstallSetupData, PostInstallSetupResponse, PostInstallValidateDatabaseData, PostInstallValidateDatabaseResponse, GetItemLanguageData, GetItemLanguageResponse, GetItemLanguageDefaultResponse, GetLanguageData, GetLanguageResponse, PostLanguageData, PostLanguageResponse, GetLanguageByIsoCodeData, GetLanguageByIsoCodeResponse, DeleteLanguageByIsoCodeData, DeleteLanguageByIsoCodeResponse, PutLanguageByIsoCodeData, PutLanguageByIsoCodeResponse, GetLogViewerLevelData, GetLogViewerLevelResponse, GetLogViewerLevelCountData, GetLogViewerLevelCountResponse, GetLogViewerLogData, GetLogViewerLogResponse, GetLogViewerMessageTemplateData, GetLogViewerMessageTemplateResponse, GetLogViewerSavedSearchData, GetLogViewerSavedSearchResponse, PostLogViewerSavedSearchData, PostLogViewerSavedSearchResponse, GetLogViewerSavedSearchByNameData, GetLogViewerSavedSearchByNameResponse, DeleteLogViewerSavedSearchByNameData, DeleteLogViewerSavedSearchByNameResponse, GetLogViewerValidateLogsSizeData, GetLogViewerValidateLogsSizeResponse, GetManifestManifestResponse, GetManifestManifestPrivateResponse, GetManifestManifestPublicResponse, GetItemMediaTypeData, GetItemMediaTypeResponse, GetItemMediaTypeAllowedData, GetItemMediaTypeAllowedResponse, GetItemMediaTypeFoldersData, GetItemMediaTypeFoldersResponse, GetItemMediaTypeSearchData, GetItemMediaTypeSearchResponse, PostMediaTypeData, PostMediaTypeResponse, GetMediaTypeByIdData, GetMediaTypeByIdResponse, DeleteMediaTypeByIdData, DeleteMediaTypeByIdResponse, PutMediaTypeByIdData, PutMediaTypeByIdResponse, GetMediaTypeByIdAllowedChildrenData, GetMediaTypeByIdAllowedChildrenResponse, GetMediaTypeByIdCompositionReferencesData, GetMediaTypeByIdCompositionReferencesResponse, PostMediaTypeByIdCopyData, PostMediaTypeByIdCopyResponse, GetMediaTypeByIdExportData, GetMediaTypeByIdExportResponse, PutMediaTypeByIdImportData, PutMediaTypeByIdImportResponse, PutMediaTypeByIdMoveData, PutMediaTypeByIdMoveResponse, GetMediaTypeAllowedAtRootData, GetMediaTypeAllowedAtRootResponse, PostMediaTypeAvailableCompositionsData, PostMediaTypeAvailableCompositionsResponse, GetMediaTypeConfigurationResponse, PostMediaTypeFolderData, PostMediaTypeFolderResponse, GetMediaTypeFolderByIdData, GetMediaTypeFolderByIdResponse, DeleteMediaTypeFolderByIdData, DeleteMediaTypeFolderByIdResponse, PutMediaTypeFolderByIdData, PutMediaTypeFolderByIdResponse, PostMediaTypeImportData, PostMediaTypeImportResponse, GetTreeMediaTypeAncestorsData, GetTreeMediaTypeAncestorsResponse, GetTreeMediaTypeChildrenData, GetTreeMediaTypeChildrenResponse, GetTreeMediaTypeRootData, GetTreeMediaTypeRootResponse, GetCollectionMediaData, GetCollectionMediaResponse, GetItemMediaData, GetItemMediaResponse, GetItemMediaSearchData, GetItemMediaSearchResponse, PostMediaData, PostMediaResponse, GetMediaByIdData, GetMediaByIdResponse, DeleteMediaByIdData, DeleteMediaByIdResponse, PutMediaByIdData, PutMediaByIdResponse, GetMediaByIdAuditLogData, GetMediaByIdAuditLogResponse, PutMediaByIdMoveData, PutMediaByIdMoveResponse, PutMediaByIdMoveToRecycleBinData, PutMediaByIdMoveToRecycleBinResponse, GetMediaByIdReferencedByData, GetMediaByIdReferencedByResponse, GetMediaByIdReferencedDescendantsData, GetMediaByIdReferencedDescendantsResponse, PutMediaByIdValidateData, PutMediaByIdValidateResponse, GetMediaAreReferencedData, GetMediaAreReferencedResponse, GetMediaConfigurationResponse, PutMediaSortData, PutMediaSortResponse, GetMediaUrlsData, GetMediaUrlsResponse, PostMediaValidateData, PostMediaValidateResponse, DeleteRecycleBinMediaResponse, DeleteRecycleBinMediaByIdData, DeleteRecycleBinMediaByIdResponse, GetRecycleBinMediaByIdOriginalParentData, GetRecycleBinMediaByIdOriginalParentResponse, PutRecycleBinMediaByIdRestoreData, PutRecycleBinMediaByIdRestoreResponse, GetRecycleBinMediaChildrenData, GetRecycleBinMediaChildrenResponse, GetRecycleBinMediaRootData, GetRecycleBinMediaRootResponse, GetTreeMediaAncestorsData, GetTreeMediaAncestorsResponse, GetTreeMediaChildrenData, GetTreeMediaChildrenResponse, GetTreeMediaRootData, GetTreeMediaRootResponse, GetItemMemberGroupData, GetItemMemberGroupResponse, GetMemberGroupData, GetMemberGroupResponse, PostMemberGroupData, PostMemberGroupResponse, GetMemberGroupByIdData, GetMemberGroupByIdResponse, DeleteMemberGroupByIdData, DeleteMemberGroupByIdResponse, PutMemberGroupByIdData, PutMemberGroupByIdResponse, GetTreeMemberGroupRootData, GetTreeMemberGroupRootResponse, GetItemMemberTypeData, GetItemMemberTypeResponse, GetItemMemberTypeSearchData, GetItemMemberTypeSearchResponse, PostMemberTypeData, PostMemberTypeResponse, GetMemberTypeByIdData, GetMemberTypeByIdResponse, DeleteMemberTypeByIdData, DeleteMemberTypeByIdResponse, PutMemberTypeByIdData, PutMemberTypeByIdResponse, GetMemberTypeByIdCompositionReferencesData, GetMemberTypeByIdCompositionReferencesResponse, PostMemberTypeByIdCopyData, PostMemberTypeByIdCopyResponse, PostMemberTypeAvailableCompositionsData, PostMemberTypeAvailableCompositionsResponse, GetMemberTypeConfigurationResponse, GetTreeMemberTypeRootData, GetTreeMemberTypeRootResponse, GetFilterMemberData, GetFilterMemberResponse, GetItemMemberData, GetItemMemberResponse, GetItemMemberSearchData, GetItemMemberSearchResponse, PostMemberData, PostMemberResponse, GetMemberByIdData, GetMemberByIdResponse, DeleteMemberByIdData, DeleteMemberByIdResponse, PutMemberByIdData, PutMemberByIdResponse, PutMemberByIdValidateData, PutMemberByIdValidateResponse, GetMemberConfigurationResponse, PostMemberValidateData, PostMemberValidateResponse, PostModelsBuilderBuildResponse, GetModelsBuilderDashboardResponse, GetModelsBuilderStatusResponse, GetObjectTypesData, GetObjectTypesResponse, GetOembedQueryData, GetOembedQueryResponse, PostPackageByNameRunMigrationData, PostPackageByNameRunMigrationResponse, GetPackageConfigurationResponse, GetPackageCreatedData, GetPackageCreatedResponse, PostPackageCreatedData, PostPackageCreatedResponse, GetPackageCreatedByIdData, GetPackageCreatedByIdResponse, DeletePackageCreatedByIdData, DeletePackageCreatedByIdResponse, PutPackageCreatedByIdData, PutPackageCreatedByIdResponse, GetPackageCreatedByIdDownloadData, GetPackageCreatedByIdDownloadResponse, GetPackageMigrationStatusData, GetPackageMigrationStatusResponse, GetItemPartialViewData, GetItemPartialViewResponse, PostPartialViewData, PostPartialViewResponse, GetPartialViewByPathData, GetPartialViewByPathResponse, DeletePartialViewByPathData, DeletePartialViewByPathResponse, PutPartialViewByPathData, PutPartialViewByPathResponse, PutPartialViewByPathRenameData, PutPartialViewByPathRenameResponse, PostPartialViewFolderData, PostPartialViewFolderResponse, GetPartialViewFolderByPathData, GetPartialViewFolderByPathResponse, DeletePartialViewFolderByPathData, DeletePartialViewFolderByPathResponse, GetPartialViewSnippetData, GetPartialViewSnippetResponse, GetPartialViewSnippetByIdData, GetPartialViewSnippetByIdResponse, GetTreePartialViewAncestorsData, GetTreePartialViewAncestorsResponse, GetTreePartialViewChildrenData, GetTreePartialViewChildrenResponse, GetTreePartialViewRootData, GetTreePartialViewRootResponse, DeletePreviewResponse, PostPreviewResponse, GetProfilingStatusResponse, PutProfilingStatusData, PutProfilingStatusResponse, GetPropertyTypeIsUsedData, GetPropertyTypeIsUsedResponse, PostPublishedCacheCollectResponse, PostPublishedCacheRebuildResponse, PostPublishedCacheReloadResponse, GetPublishedCacheStatusResponse, GetRedirectManagementData, GetRedirectManagementResponse, GetRedirectManagementByIdData, GetRedirectManagementByIdResponse, DeleteRedirectManagementByIdData, DeleteRedirectManagementByIdResponse, GetRedirectManagementStatusResponse, PostRedirectManagementStatusData, PostRedirectManagementStatusResponse, GetItemRelationTypeData, GetItemRelationTypeResponse, GetRelationTypeData, GetRelationTypeResponse, GetRelationTypeByIdData, GetRelationTypeByIdResponse, GetRelationByRelationTypeIdData, GetRelationByRelationTypeIdResponse, GetItemScriptData, GetItemScriptResponse, PostScriptData, PostScriptResponse, GetScriptByPathData, GetScriptByPathResponse, DeleteScriptByPathData, DeleteScriptByPathResponse, PutScriptByPathData, PutScriptByPathResponse, PutScriptByPathRenameData, PutScriptByPathRenameResponse, PostScriptFolderData, PostScriptFolderResponse, GetScriptFolderByPathData, GetScriptFolderByPathResponse, DeleteScriptFolderByPathData, DeleteScriptFolderByPathResponse, GetTreeScriptAncestorsData, GetTreeScriptAncestorsResponse, GetTreeScriptChildrenData, GetTreeScriptChildrenResponse, GetTreeScriptRootData, GetTreeScriptRootResponse, GetSearcherData, GetSearcherResponse, GetSearcherBySearcherNameQueryData, GetSearcherBySearcherNameQueryResponse, GetSecurityConfigurationResponse, PostSecurityForgotPasswordData, PostSecurityForgotPasswordResponse, PostSecurityForgotPasswordResetData, PostSecurityForgotPasswordResetResponse, PostSecurityForgotPasswordVerifyData, PostSecurityForgotPasswordVerifyResponse, GetSegmentData, GetSegmentResponse, GetServerConfigurationResponse, GetServerInformationResponse, GetServerStatusResponse, GetServerTroubleshootingResponse, GetItemStaticFileData, GetItemStaticFileResponse, GetTreeStaticFileAncestorsData, GetTreeStaticFileAncestorsResponse, GetTreeStaticFileChildrenData, GetTreeStaticFileChildrenResponse, GetTreeStaticFileRootData, GetTreeStaticFileRootResponse, GetItemStylesheetData, GetItemStylesheetResponse, PostStylesheetData, PostStylesheetResponse, GetStylesheetByPathData, GetStylesheetByPathResponse, DeleteStylesheetByPathData, DeleteStylesheetByPathResponse, PutStylesheetByPathData, PutStylesheetByPathResponse, PutStylesheetByPathRenameData, PutStylesheetByPathRenameResponse, PostStylesheetFolderData, PostStylesheetFolderResponse, GetStylesheetFolderByPathData, GetStylesheetFolderByPathResponse, DeleteStylesheetFolderByPathData, DeleteStylesheetFolderByPathResponse, GetTreeStylesheetAncestorsData, GetTreeStylesheetAncestorsResponse, GetTreeStylesheetChildrenData, GetTreeStylesheetChildrenResponse, GetTreeStylesheetRootData, GetTreeStylesheetRootResponse, GetTagData, GetTagResponse, GetTelemetryData, GetTelemetryResponse, GetTelemetryLevelResponse, PostTelemetryLevelData, PostTelemetryLevelResponse, GetItemTemplateData, GetItemTemplateResponse, GetItemTemplateSearchData, GetItemTemplateSearchResponse, PostTemplateData, PostTemplateResponse, GetTemplateByIdData, GetTemplateByIdResponse, DeleteTemplateByIdData, DeleteTemplateByIdResponse, PutTemplateByIdData, PutTemplateByIdResponse, GetTemplateConfigurationResponse, PostTemplateQueryExecuteData, PostTemplateQueryExecuteResponse, GetTemplateQuerySettingsResponse, GetTreeTemplateAncestorsData, GetTreeTemplateAncestorsResponse, GetTreeTemplateChildrenData, GetTreeTemplateChildrenResponse, GetTreeTemplateRootData, GetTreeTemplateRootResponse, PostTemporaryFileData, PostTemporaryFileResponse, GetTemporaryFileByIdData, GetTemporaryFileByIdResponse, DeleteTemporaryFileByIdData, DeleteTemporaryFileByIdResponse, GetTemporaryFileConfigurationResponse, PostUpgradeAuthorizeResponse, GetUpgradeSettingsResponse, PostUserDataData, PostUserDataResponse, GetUserDataData, GetUserDataResponse, PutUserDataData, PutUserDataResponse, GetUserDataByIdData, GetUserDataByIdResponse, GetFilterUserGroupData, GetFilterUserGroupResponse, GetItemUserGroupData, GetItemUserGroupResponse, DeleteUserGroupData, DeleteUserGroupResponse, PostUserGroupData, PostUserGroupResponse, GetUserGroupData, GetUserGroupResponse, GetUserGroupByIdData, GetUserGroupByIdResponse, DeleteUserGroupByIdData, DeleteUserGroupByIdResponse, PutUserGroupByIdData, PutUserGroupByIdResponse, DeleteUserGroupByIdUsersData, DeleteUserGroupByIdUsersResponse, PostUserGroupByIdUsersData, PostUserGroupByIdUsersResponse, GetFilterUserData, GetFilterUserResponse, GetItemUserData, GetItemUserResponse, PostUserData, PostUserResponse, DeleteUserData, DeleteUserResponse, GetUserData, GetUserResponse, GetUserByIdData, GetUserByIdResponse, DeleteUserByIdData, DeleteUserByIdResponse, PutUserByIdData, PutUserByIdResponse, GetUserById2FaData, GetUserById2FaResponse, DeleteUserById2FaByProviderNameData, DeleteUserById2FaByProviderNameResponse, GetUserByIdCalculateStartNodesData, GetUserByIdCalculateStartNodesResponse, PostUserByIdChangePasswordData, PostUserByIdChangePasswordResponse, PostUserByIdClientCredentialsData, PostUserByIdClientCredentialsResponse, GetUserByIdClientCredentialsData, GetUserByIdClientCredentialsResponse, DeleteUserByIdClientCredentialsByClientIdData, DeleteUserByIdClientCredentialsByClientIdResponse, PostUserByIdResetPasswordData, PostUserByIdResetPasswordResponse, DeleteUserAvatarByIdData, DeleteUserAvatarByIdResponse, PostUserAvatarByIdData, PostUserAvatarByIdResponse, GetUserConfigurationResponse, GetUserCurrentResponse, GetUserCurrent2FaResponse, DeleteUserCurrent2FaByProviderNameData, DeleteUserCurrent2FaByProviderNameResponse, PostUserCurrent2FaByProviderNameData, PostUserCurrent2FaByProviderNameResponse, GetUserCurrent2FaByProviderNameData, GetUserCurrent2FaByProviderNameResponse, PostUserCurrentAvatarData, PostUserCurrentAvatarResponse, PostUserCurrentChangePasswordData, PostUserCurrentChangePasswordResponse, GetUserCurrentConfigurationResponse, GetUserCurrentLoginProvidersResponse, GetUserCurrentPermissionsData, GetUserCurrentPermissionsResponse, GetUserCurrentPermissionsDocumentData, GetUserCurrentPermissionsDocumentResponse, GetUserCurrentPermissionsMediaData, GetUserCurrentPermissionsMediaResponse, PostUserDisableData, PostUserDisableResponse, PostUserEnableData, PostUserEnableResponse, PostUserInviteData, PostUserInviteResponse, PostUserInviteCreatePasswordData, PostUserInviteCreatePasswordResponse, PostUserInviteResendData, PostUserInviteResendResponse, PostUserInviteVerifyData, PostUserInviteVerifyResponse, PostUserSetUserGroupsData, PostUserSetUserGroupsResponse, PostUserUnlockData, PostUserUnlockResponse, GetItemWebhookData, GetItemWebhookResponse, GetWebhookData, GetWebhookResponse, PostWebhookData, PostWebhookResponse, GetWebhookByIdData, GetWebhookByIdResponse, DeleteWebhookByIdData, DeleteWebhookByIdResponse, PutWebhookByIdData, PutWebhookByIdResponse, GetWebhookEventsData, GetWebhookEventsResponse } from './types.gen'; export class CultureService { /** @@ -2425,6 +2425,7 @@ export class DocumentService { * @param data.query * @param data.skip * @param data.take + * @param data.parentId * @returns unknown OK * @throws ApiError */ @@ -2435,7 +2436,8 @@ export class DocumentService { query: { query: data.query, skip: data.skip, - take: data.take + take: data.take, + parentId: data.parentId }, errors: { 401: 'The resource is protected and requires an authentication token' @@ -4014,6 +4016,7 @@ export class MediaService { * @param data.query * @param data.skip * @param data.take + * @param data.parentId * @returns unknown OK * @throws ApiError */ @@ -4024,7 +4027,8 @@ export class MediaService { query: { query: data.query, skip: data.skip, - take: data.take + take: data.take, + parentId: data.parentId }, errors: { 401: 'The resource is protected and requires an authentication token' @@ -8102,7 +8106,7 @@ export class UserService { } }); } - + /** * @param data The data for the request. * @param data.id @@ -8110,18 +8114,64 @@ export class UserService { * @returns string OK * @throws ApiError */ - public static postCurrentUserByIdChangePassword(data: PostCurrentUserChangePasswordData): CancelablePromise { + public static postUserByIdClientCredentials(data: PostUserByIdClientCredentialsData): CancelablePromise { return __request(OpenAPI, { method: 'POST', - url: '/umbraco/management/api/v1/user/current/change-password', + url: '/umbraco/management/api/v1/user/{id}/client-credentials', + path: { + id: data.id + }, body: data.requestBody, mediaType: 'application/json', responseHeader: 'Umb-Notifications', errors: { 400: 'Bad Request', 401: 'The resource is protected and requires an authentication token', - 403: 'The authenticated user do not have access to this resource', - 404: 'Not Found' + 403: 'The authenticated user do not have access to this resource' + } + }); + } + + /** + * @param data The data for the request. + * @param data.id + * @returns string OK + * @throws ApiError + */ + public static getUserByIdClientCredentials(data: GetUserByIdClientCredentialsData): CancelablePromise { + return __request(OpenAPI, { + method: 'GET', + url: '/umbraco/management/api/v1/user/{id}/client-credentials', + path: { + id: data.id + }, + errors: { + 401: 'The resource is protected and requires an authentication token', + 403: 'The authenticated user do not have access to this resource' + } + }); + } + + /** + * @param data The data for the request. + * @param data.id + * @param data.clientId + * @returns string OK + * @throws ApiError + */ + public static deleteUserByIdClientCredentialsByClientId(data: DeleteUserByIdClientCredentialsByClientIdData): CancelablePromise { + return __request(OpenAPI, { + method: 'DELETE', + url: '/umbraco/management/api/v1/user/{id}/client-credentials/{clientId}', + path: { + id: data.id, + clientId: data.clientId + }, + responseHeader: 'Umb-Notifications', + errors: { + 400: 'Bad Request', + 401: 'The resource is protected and requires an authentication token', + 403: 'The authenticated user do not have access to this resource' } }); } diff --git a/src/Umbraco.Web.UI.Client/src/external/backend-api/src/types.gen.ts b/src/Umbraco.Web.UI.Client/src/external/backend-api/src/types.gen.ts index ffc97171b1..224bc0862b 100644 --- a/src/Umbraco.Web.UI.Client/src/external/backend-api/src/types.gen.ts +++ b/src/Umbraco.Web.UI.Client/src/external/backend-api/src/types.gen.ts @@ -384,6 +384,11 @@ export type CreateTemplateRequestModel = { id?: string | null; }; +export type CreateUserClientCredentialsRequestModel = { + clientId: string; + clientSecret: string; +}; + export type CreateUserDataRequestModel = { group: string; identifier: string; @@ -413,6 +418,7 @@ export type CreateUserRequestModel = { name: string; userGroupIds: Array<(ReferenceByIdModel)>; id?: string | null; + kind: UserKindModel; }; export type CreateWebhookRequestModel = { @@ -1075,6 +1081,7 @@ export type InviteUserRequestModel = { name: string; userGroupIds: Array<(ReferenceByIdModel)>; id?: string | null; + kind: UserKindModel; message?: string | null; }; @@ -1353,8 +1360,14 @@ export type MemberItemResponseModel = { id: string; memberType: MemberTypeReferenceResponseModel; variants: Array<(VariantItemResponseModel)>; + kind: MemberKindModel; }; +export enum MemberKindModel { + DEFAULT = 'Default', + API = 'Api' +} + export type MemberResponseModel = { values: Array<(MemberValueModel)>; variants: Array<(MemberVariantResponseModel)>; @@ -1370,6 +1383,7 @@ export type MemberResponseModel = { lastLockoutDate?: string | null; lastPasswordChangeDate?: string | null; groups: Array<(string)>; + kind: MemberKindModel; }; export type MemberTypeCompositionModel = { @@ -2685,8 +2699,14 @@ export type UserItemResponseModel = { id: string; name: string; avatarUrls: Array<(string)>; + kind: UserKindModel; }; +export enum UserKindModel { + DEFAULT = 'Default', + API = 'Api' +} + export enum UserOrderModel { USER_NAME = 'UserName', LANGUAGE = 'Language', @@ -2729,6 +2749,7 @@ export type UserResponseModel = { lastLockoutDate?: string | null; lastPasswordChangeDate?: string | null; isAdmin: boolean; + kind: UserKindModel; }; export type UserSettingsPresentationModel = { @@ -3494,6 +3515,7 @@ export type GetItemDocumentData = { export type GetItemDocumentResponse = Array<(DocumentItemResponseModel)>; export type GetItemDocumentSearchData = { + parentId?: string; query?: string; skip?: number; take?: number; @@ -3947,6 +3969,7 @@ export type GetItemMediaData = { export type GetItemMediaResponse = Array<(MediaItemResponseModel)>; export type GetItemMediaSearchData = { + parentId?: string; query?: string; skip?: number; take?: number; @@ -5068,11 +5091,25 @@ export type PostUserByIdChangePasswordData = { export type PostUserByIdChangePasswordResponse = string; -export type PostCurrentUserChangePasswordData = { - requestBody?: ChangePasswordCurrentUserRequestModel; +export type PostUserByIdClientCredentialsData = { + id: string; + requestBody?: CreateUserClientCredentialsRequestModel; }; -export type PostCurrentUserChangePasswordResponse = string; +export type PostUserByIdClientCredentialsResponse = string; + +export type GetUserByIdClientCredentialsData = { + id: string; +}; + +export type GetUserByIdClientCredentialsResponse = Array<(string)>; + +export type DeleteUserByIdClientCredentialsByClientIdData = { + clientId: string; + id: string; +}; + +export type DeleteUserByIdClientCredentialsByClientIdResponse = string; export type PostUserByIdResetPasswordData = { id: string; @@ -12959,6 +12996,69 @@ export type $OpenApiTs = { }; }; }; + '/umbraco/management/api/v1/user/{id}/client-credentials': { + post: { + req: PostUserByIdClientCredentialsData; + res: { + /** + * OK + */ + 200: string; + /** + * Bad Request + */ + 400: ProblemDetails; + /** + * The resource is protected and requires an authentication token + */ + 401: unknown; + /** + * The authenticated user do not have access to this resource + */ + 403: string; + }; + }; + get: { + req: GetUserByIdClientCredentialsData; + res: { + /** + * OK + */ + 200: Array<(string)>; + /** + * The resource is protected and requires an authentication token + */ + 401: unknown; + /** + * The authenticated user do not have access to this resource + */ + 403: unknown; + }; + }; + }; + '/umbraco/management/api/v1/user/{id}/client-credentials/{clientId}': { + delete: { + req: DeleteUserByIdClientCredentialsByClientIdData; + res: { + /** + * OK + */ + 200: string; + /** + * Bad Request + */ + 400: ProblemDetails; + /** + * The resource is protected and requires an authentication token + */ + 401: unknown; + /** + * The authenticated user do not have access to this resource + */ + 403: string; + }; + }; + }; '/umbraco/management/api/v1/user/{id}/reset-password': { post: { req: PostUserByIdResetPasswordData; From 4d64a5de19609d473716ae32229ae375454da6e5 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Fri, 30 Aug 2024 22:26:13 +0200 Subject: [PATCH 002/107] add utils for user model kind --- .../src/packages/user/user/utils/index.ts | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/utils/index.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/utils/index.ts index 5d1478f0fa..6189fbcb68 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/utils/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/utils/index.ts @@ -1 +1,8 @@ export * from './is-user.function.js'; + +export type UmbUserModelKindType = 'Default' | 'Api'; + +export const UmbUserModelKind = Object.freeze({ + DEFAULT: 'Default', + API: 'Api', +}); From a72fbc7334e31acbbe03747f9093df8d3f2e32a5 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Fri, 30 Aug 2024 22:26:52 +0200 Subject: [PATCH 003/107] add kind to user detail model --- src/Umbraco.Web.UI.Client/src/packages/user/user/types.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/types.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/types.ts index b092e1b3e8..b0cbe18174 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/types.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/types.ts @@ -5,6 +5,7 @@ import { UserStateModel, type UserTwoFactorProviderModel, } from '@umbraco-cms/backoffice/external/backend-api'; +import { UmbUserModelKindType } from './utils/index.js'; export type UmbUserStateEnum = UserStateModel; export const UmbUserStateEnum = UserStateModel; @@ -26,6 +27,7 @@ export interface UmbUserDetailModel extends UmbUserStartNodesModel { updateDate: string | null; userGroupUniques: Array; userName: string; + kind: UmbUserModelKindType; } export interface UmbUserStartNodesModel { From 6ef6f686467856515240e072c8b7699c3bc5820a Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Fri, 30 Aug 2024 22:27:36 +0200 Subject: [PATCH 004/107] map kind in user detail data source --- .../detail/user-detail.server.data-source.ts | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/repository/detail/user-detail.server.data-source.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/repository/detail/user-detail.server.data-source.ts index 8d924ca94f..0d89ee2a79 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/repository/detail/user-detail.server.data-source.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/repository/detail/user-detail.server.data-source.ts @@ -2,10 +2,15 @@ import type { UmbUserDetailModel, UmbUserStartNodesModel } from '../../types.js' import { UMB_USER_ENTITY_TYPE } from '../../entity.js'; import { UmbId } from '@umbraco-cms/backoffice/id'; import type { UmbDetailDataSource } from '@umbraco-cms/backoffice/repository'; -import type { CreateUserRequestModel, UpdateUserRequestModel } from '@umbraco-cms/backoffice/external/backend-api'; +import type { + CreateUserRequestModel, + UpdateUserRequestModel, + UserKindModel, +} from '@umbraco-cms/backoffice/external/backend-api'; import { UserService } from '@umbraco-cms/backoffice/external/backend-api'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources'; +import { UmbUserModelKind } from '../../utils/index.js'; /** * A data source for the User that fetches data from the server @@ -34,17 +39,18 @@ export class UmbUserServerDataSource implements UmbDetailDataSource Date: Fri, 30 Aug 2024 22:28:22 +0200 Subject: [PATCH 005/107] select kind when creating a new user --- .../modals/create/create-user-modal.element.ts | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/modals/create/create-user-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/modals/create/create-user-modal.element.ts index fdf1e15950..85b6facca1 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/modals/create/create-user-modal.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/modals/create/create-user-modal.element.ts @@ -1,4 +1,5 @@ import { UmbUserDetailRepository } from '../../repository/index.js'; +import { UmbUserModelKind, UmbUserModelKindType } from '../../utils/index.js'; import { UMB_CREATE_USER_SUCCESS_MODAL } from './create-user-success-modal.token.js'; import type { UmbUserGroupInputElement } from '@umbraco-cms/backoffice/user-group'; import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; @@ -24,6 +25,7 @@ export class UmbCreateUserModalElement extends UmbModalBaseElement { const formData = new FormData(form); + const kind = formData.get('kind') as UmbUserModelKindType; const name = formData.get('name') as string; const email = formData.get('email') as string; @@ -35,6 +37,7 @@ export class UmbCreateUserModalElement extends UmbModalBaseElement { const { data: userScaffold } = await this.#userDetailRepository.createScaffold(); if (!userScaffold) return; + userScaffold.kind = kind; userScaffold.name = name; userScaffold.email = email; userScaffold.userName = email; @@ -94,6 +97,17 @@ export class UmbCreateUserModalElement extends UmbModalBaseElement { #renderForm() { return html`
+ + Kind + + + ${UmbUserModelKind.DEFAULT} + ${UmbUserModelKind.API} + + + Name @@ -115,7 +129,8 @@ export class UmbCreateUserModalElement extends UmbModalBaseElement { UmbTextStyles, css` uui-input, - uui-input-password { + uui-input-password, + uui-combobox { width: 100%; } From 30afb52933109428ef25e2c58422c3aeaad50179 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Mon, 2 Sep 2024 13:11:19 +0200 Subject: [PATCH 006/107] add kind as observable part on user workspace --- .../src/packages/user/user/workspace/user-workspace.context.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/workspace/user-workspace.context.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/workspace/user-workspace.context.ts index 088d944b4f..69587e191d 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/workspace/user-workspace.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/workspace/user-workspace.context.ts @@ -25,6 +25,7 @@ export class UmbUserWorkspaceContext readonly data = this.#currentData.asObservable(); readonly state = this.#currentData.asObservablePart((x) => x?.state); readonly unique = this.#currentData.asObservablePart((x) => x?.unique); + readonly kind = this.#currentData.asObservablePart((x) => x?.kind); readonly userGroupUniques = this.#currentData.asObservablePart((x) => x?.userGroupUniques || []); readonly documentStartNodeUniques = this.#currentData.asObservablePart( (data) => data?.documentStartNodeUniques || [], From bfec23b744acfc480b796d4c2a6216c1d9115cb4 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Mon, 2 Sep 2024 13:11:39 +0200 Subject: [PATCH 007/107] observe user kind in user condition base --- .../user-allow-action-base.condition.ts | 26 +++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/conditions/user-allow-action-base.condition.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/conditions/user-allow-action-base.condition.ts index 161f04d1b4..fb5bf0f8d1 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/conditions/user-allow-action-base.condition.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/conditions/user-allow-action-base.condition.ts @@ -16,23 +16,45 @@ export abstract class UmbUserActionConditionBase { /** * The unique identifier of the user being edited + * @protected + * @type {string} + * @memberof UmbUserActionConditionBase */ protected userUnique?: string; /** * The state of the user being edited + * @protected + * @type {(UmbUserStateEnum | null)} + * @memberof UmbUserActionConditionBase */ protected userState?: UmbUserStateEnum | null; + /** + * The kind of user being edited + * @protected + * @type {string} + * @memberof UmbUserActionConditionBase + */ + protected userKind?: string; + + /** + * Creates an instance of UmbUserActionConditionBase. + * @param {UmbControllerHost} host The host controller + * @param {UmbConditionControllerArguments} args The condition arguments + * @memberof UmbUserActionConditionBase + */ constructor(host: UmbControllerHost, args: UmbConditionControllerArguments) { super(host, args); this.consumeContext(UMB_USER_WORKSPACE_CONTEXT, (context) => { + console.log(context); this.observe( - observeMultiple([context.unique, context.state]), - ([unique, state]) => { + observeMultiple([context.unique, context.state, context.kind]), + ([unique, state, kind]) => { this.userUnique = unique; this.userState = state; + this.userKind = kind; this._onUserDataChange(); }, '_umbActiveUser', From b162cbafa442193495ae2bfc713f7422e016a329 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Mon, 2 Sep 2024 13:12:04 +0200 Subject: [PATCH 008/107] register allow change password condition --- .../packages/user/change-password/manifests.ts | 5 +++++ .../conditions/allow-change-password/manifests.ts | 10 ++++++++++ ...user-allow-change-password-action.condition.ts | 15 +++++++++++++++ .../packages/user/user/conditions/manifests.ts | 6 ++++-- 4 files changed, 34 insertions(+), 2 deletions(-) create mode 100644 src/Umbraco.Web.UI.Client/src/packages/user/user/conditions/allow-change-password/manifests.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/user/user/conditions/allow-change-password/user-allow-change-password-action.condition.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/change-password/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/user/change-password/manifests.ts index 083dc29663..0a16bdecd3 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/change-password/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/change-password/manifests.ts @@ -14,6 +14,11 @@ export const manifests: Array = [ icon: 'icon-key', label: '#user_changePassword', }, + conditions: [ + { + alias: 'Umb.Condition.User.AllowChangePassword', + }, + ], }, { type: 'modal', diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/conditions/allow-change-password/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/conditions/allow-change-password/manifests.ts new file mode 100644 index 0000000000..a144bfcb8e --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/conditions/allow-change-password/manifests.ts @@ -0,0 +1,10 @@ +import type { ManifestTypes } from '@umbraco-cms/backoffice/extension-registry'; + +export const manifests: Array = [ + { + type: 'condition', + name: 'User Allow Change Password Condition', + alias: 'Umb.Condition.User.AllowChangePassword', + api: () => import('./user-allow-change-password-action.condition.js'), + }, +]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/conditions/allow-change-password/user-allow-change-password-action.condition.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/conditions/allow-change-password/user-allow-change-password-action.condition.ts new file mode 100644 index 0000000000..ed78c34e78 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/conditions/allow-change-password/user-allow-change-password-action.condition.ts @@ -0,0 +1,15 @@ +import { UmbUserModelKind } from '../../utils/index.js'; +import { UmbUserActionConditionBase } from '../user-allow-action-base.condition.js'; + +export class UmbUserAllowChangePasswordActionCondition extends UmbUserActionConditionBase { + async _onUserDataChange() { + // don't allow the current user to delete themselves + if (this.userKind === UmbUserModelKind.DEFAULT) { + this.permitted = true; + } else { + this.permitted = false; + } + } +} + +export { UmbUserAllowChangePasswordActionCondition as api }; diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/conditions/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/conditions/manifests.ts index 23b03f4ec4..4851681f7c 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/conditions/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/conditions/manifests.ts @@ -1,3 +1,4 @@ +import { manifests as userAllowChangePasswordActionManifests } from './allow-change-password/manifests.js'; import { manifests as userAllowDeleteActionManifests } from './allow-delete/manifests.js'; import { manifests as userAllowDisableActionManifests } from './allow-disable/manifests.js'; import { manifests as userAllowEnableActionManifests } from './allow-enable/manifests.js'; @@ -7,10 +8,11 @@ import { manifests as userAllowUnlockActionManifests } from './allow-unlock/mani import type { ManifestTypes } from '@umbraco-cms/backoffice/extension-registry'; export const manifests: Array = [ + ...userAllowChangePasswordActionManifests, + ...userAllowDeleteActionManifests, ...userAllowDisableActionManifests, ...userAllowEnableActionManifests, - ...userAllowUnlockActionManifests, ...userAllowExternalLoginActionManifests, ...userAllowMfaActionManifests, - ...userAllowDeleteActionManifests, + ...userAllowUnlockActionManifests, ]; From 9b2a4dc3d3fa7c7e29e30f376160aae96d7792e9 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Mon, 2 Sep 2024 14:52:29 +0200 Subject: [PATCH 009/107] add interface for client credentials server data source --- .../client-credential/repository/types.ts | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 src/Umbraco.Web.UI.Client/src/packages/user/user/client-credential/repository/types.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/client-credential/repository/types.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/client-credential/repository/types.ts new file mode 100644 index 0000000000..4573cc9a33 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/client-credential/repository/types.ts @@ -0,0 +1,21 @@ +import type { UmbDataSourceErrorResponse, UmbDataSourceResponse } from '@umbraco-cms/backoffice/repository'; + +export interface UmbUserClientCredentialsDataSourceCreateArgs { + user: { unique: string }; + client: { unique: string; secret: string }; +} + +export interface UmbUserClientCredentialsDataSourceReadArgs { + user: { unique: string }; +} + +export interface UmbUserClientCredentialsDataSourceDeleteArgs { + user: { unique: string }; + client: { unique: string }; +} + +export interface UmbUserClientCredentialsDataSource { + create(args: UmbUserClientCredentialsDataSourceCreateArgs): Promise; + read(args: UmbUserClientCredentialsDataSourceReadArgs): Promise>>; + delete: (args: UmbUserClientCredentialsDataSourceDeleteArgs) => Promise; +} From efe8b047eedcbbc17f613dd72b17b9809e998387 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Mon, 2 Sep 2024 14:52:45 +0200 Subject: [PATCH 010/107] add server client credentials data source --- ...r-client-credentials.server.data-source.ts | 73 +++++++++++++++++++ 1 file changed, 73 insertions(+) create mode 100644 src/Umbraco.Web.UI.Client/src/packages/user/user/client-credential/repository/user-client-credentials.server.data-source.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/client-credential/repository/user-client-credentials.server.data-source.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/client-credential/repository/user-client-credentials.server.data-source.ts new file mode 100644 index 0000000000..8e795fca35 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/client-credential/repository/user-client-credentials.server.data-source.ts @@ -0,0 +1,73 @@ +import type { + UmbUserClientCredentialsDataSource, + UmbUserClientCredentialsDataSourceCreateArgs, + UmbUserClientCredentialsDataSourceDeleteArgs, + UmbUserClientCredentialsDataSourceReadArgs, +} from './types.js'; +import { UserService } from '@umbraco-cms/backoffice/external/backend-api'; +import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; +import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources'; + +/** + * Server data source for user client credentials + * @export + * @class UmbUserClientCredentialsServerDataSource + * @implements {UmbUserClientCredentialsDataSource} + */ +export class UmbUserClientCredentialsServerDataSource implements UmbUserClientCredentialsDataSource { + #host: UmbControllerHost; + + constructor(host: UmbControllerHost) { + this.#host = host; + } + + /** + * Creates a new client credentials for a user + * @param {UmbUserClientCredentialsDataSourceCreateArgs} args - The user and client to create the credentials for + * @returns {*} + * @memberof UmbUserClientCredentialsServerDataSource + */ + create(args: UmbUserClientCredentialsDataSourceCreateArgs) { + return tryExecuteAndNotify( + this.#host, + UserService.postUserByIdClientCredentials({ + id: args.user.unique, + requestBody: { + clientId: args.client.unique, + clientSecret: args.client.secret, + }, + }), + ); + } + + /** + * Reads the client credentials for a user + * @param {UmbUserClientCredentialsDataSourceReadArgs} args - The user to read the credentials for + * @returns {*} + * @memberof UmbUserClientCredentialsServerDataSource + */ + read(args: UmbUserClientCredentialsDataSourceReadArgs) { + return tryExecuteAndNotify( + this.#host, + UserService.getUserByIdClientCredentials({ + id: args.user.unique, + }), + ); + } + + /** + * Deletes the client credentials for a user + * @param {UmbUserClientCredentialsDataSourceDeleteArgs} args - The user and client unique to delete the credentials for + * @returns {*} + * @memberof UmbUserClientCredentialsServerDataSource + */ + delete(args: UmbUserClientCredentialsDataSourceDeleteArgs) { + return tryExecuteAndNotify( + this.#host, + UserService.deleteUserByIdClientCredentialsByClientId({ + id: args.user.unique, + clientId: args.client.unique, + }), + ); + } +} From ea80fbceb546c1211308fd6e7c72d62554722681 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Mon, 2 Sep 2024 14:52:56 +0200 Subject: [PATCH 011/107] Create index.ts --- .../src/packages/user/user/client-credential/index.ts | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 src/Umbraco.Web.UI.Client/src/packages/user/user/client-credential/index.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/client-credential/index.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/client-credential/index.ts new file mode 100644 index 0000000000..e69de29bb2 From aa9a1d85b01a114252fbc751cde92ad9694eeafb Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Mon, 2 Sep 2024 14:53:06 +0200 Subject: [PATCH 012/107] add repository alias --- .../packages/user/user/client-credential/repository/constants.ts | 1 + 1 file changed, 1 insertion(+) create mode 100644 src/Umbraco.Web.UI.Client/src/packages/user/user/client-credential/repository/constants.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/client-credential/repository/constants.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/client-credential/repository/constants.ts new file mode 100644 index 0000000000..7e4e853a5d --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/client-credential/repository/constants.ts @@ -0,0 +1 @@ +export const UMB_USER_CLIENT_CREDENTIALS_REPOSITORY_ALIAS = 'Umb.Repository.User.ClientCredentials'; From 88be0f3c1adb678875bde6a9ae7fee3ee50e4c14 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Mon, 2 Sep 2024 15:14:55 +0200 Subject: [PATCH 013/107] return credential as an object --- .../repository/data-source/index.ts | 2 ++ .../repository/data-source/types.ts | 24 +++++++++++++++++++ ...r-client-credentials.server.data-source.ts | 14 +++++++++-- 3 files changed, 38 insertions(+), 2 deletions(-) create mode 100644 src/Umbraco.Web.UI.Client/src/packages/user/user/client-credential/repository/data-source/index.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/user/user/client-credential/repository/data-source/types.ts rename src/Umbraco.Web.UI.Client/src/packages/user/user/client-credential/repository/{ => data-source}/user-client-credentials.server.data-source.ts (88%) diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/client-credential/repository/data-source/index.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/client-credential/repository/data-source/index.ts new file mode 100644 index 0000000000..16f734cbcb --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/client-credential/repository/data-source/index.ts @@ -0,0 +1,2 @@ +export * from './types.js'; +export * from './user-client-credentials.server.data-source.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/client-credential/repository/data-source/types.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/client-credential/repository/data-source/types.ts new file mode 100644 index 0000000000..14e6dd533e --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/client-credential/repository/data-source/types.ts @@ -0,0 +1,24 @@ +import type { UmbUserClientCredentialModel } from '../types.js'; +import type { UmbDataSourceErrorResponse, UmbDataSourceResponse } from '@umbraco-cms/backoffice/repository'; + +export interface UmbUserClientCredentialsDataSourceCreateArgs { + user: { unique: string }; + client: { unique: string; secret: string }; +} + +export interface UmbUserClientCredentialsDataSourceReadArgs { + user: { unique: string }; +} + +export interface UmbUserClientCredentialsDataSourceDeleteArgs { + user: { unique: string }; + client: { unique: string }; +} + +export interface UmbUserClientCredentialsDataSource { + create(args: UmbUserClientCredentialsDataSourceCreateArgs): Promise; + read( + args: UmbUserClientCredentialsDataSourceReadArgs, + ): Promise>>; + delete: (args: UmbUserClientCredentialsDataSourceDeleteArgs) => Promise; +} diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/client-credential/repository/user-client-credentials.server.data-source.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/client-credential/repository/data-source/user-client-credentials.server.data-source.ts similarity index 88% rename from src/Umbraco.Web.UI.Client/src/packages/user/user/client-credential/repository/user-client-credentials.server.data-source.ts rename to src/Umbraco.Web.UI.Client/src/packages/user/user/client-credential/repository/data-source/user-client-credentials.server.data-source.ts index 8e795fca35..c140625b7a 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/client-credential/repository/user-client-credentials.server.data-source.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/client-credential/repository/data-source/user-client-credentials.server.data-source.ts @@ -46,13 +46,23 @@ export class UmbUserClientCredentialsServerDataSource implements UmbUserClientCr * @returns {*} * @memberof UmbUserClientCredentialsServerDataSource */ - read(args: UmbUserClientCredentialsDataSourceReadArgs) { - return tryExecuteAndNotify( + async read(args: UmbUserClientCredentialsDataSourceReadArgs) { + const { data, error } = await tryExecuteAndNotify( this.#host, UserService.getUserByIdClientCredentials({ id: args.user.unique, }), ); + + if (data) { + const credentials = data.map((clientId) => ({ + unique: clientId, + })); + + return { data: credentials }; + } + + return { error }; } /** From 1c08c74613b713cdfc70462bf6e0afb72c8e8274 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Mon, 2 Sep 2024 15:18:32 +0200 Subject: [PATCH 014/107] add repository --- .../client-credential/repository/index.ts | 2 + .../client-credential/repository/manifests.ts | 11 ++++ .../client-credential/repository/types.ts | 28 +++------ .../user-client-credentials.repository.ts | 61 +++++++++++++++++++ 4 files changed, 84 insertions(+), 18 deletions(-) create mode 100644 src/Umbraco.Web.UI.Client/src/packages/user/user/client-credential/repository/index.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/user/user/client-credential/repository/manifests.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/user/user/client-credential/repository/user-client-credentials.repository.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/client-credential/repository/index.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/client-credential/repository/index.ts new file mode 100644 index 0000000000..abf2760126 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/client-credential/repository/index.ts @@ -0,0 +1,2 @@ +export * from './user-client-credentials.repository.js'; +export * from './constants.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/client-credential/repository/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/client-credential/repository/manifests.ts new file mode 100644 index 0000000000..2c6b56a623 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/client-credential/repository/manifests.ts @@ -0,0 +1,11 @@ +import { UMB_USER_CLIENT_CREDENTIALS_REPOSITORY_ALIAS } from './constants.js'; +import type { ManifestTypes, UmbBackofficeManifestKind } from '@umbraco-cms/backoffice/extension-registry'; + +export const manifests: Array = [ + { + type: 'repository', + alias: UMB_USER_CLIENT_CREDENTIALS_REPOSITORY_ALIAS, + name: 'User Client Credentials Repository', + api: () => import('./user-client-credentials.repository.js'), + }, +]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/client-credential/repository/types.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/client-credential/repository/types.ts index 4573cc9a33..a27c8121f7 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/client-credential/repository/types.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/client-credential/repository/types.ts @@ -1,21 +1,13 @@ -import type { UmbDataSourceErrorResponse, UmbDataSourceResponse } from '@umbraco-cms/backoffice/repository'; +import type { + UmbUserClientCredentialsDataSourceCreateArgs, + UmbUserClientCredentialsDataSourceDeleteArgs, + UmbUserClientCredentialsDataSourceReadArgs, +} from './data-source/index.js'; -export interface UmbUserClientCredentialsDataSourceCreateArgs { - user: { unique: string }; - client: { unique: string; secret: string }; -} +export type UmbUserClientCredentialsRepositoryCreateArgs = UmbUserClientCredentialsDataSourceCreateArgs; +export type UmbUserClientCredentialsRepositoryReadArgs = UmbUserClientCredentialsDataSourceReadArgs; +export type UmbUserClientCredentialsRepositoryDeleteArgs = UmbUserClientCredentialsDataSourceDeleteArgs; -export interface UmbUserClientCredentialsDataSourceReadArgs { - user: { unique: string }; -} - -export interface UmbUserClientCredentialsDataSourceDeleteArgs { - user: { unique: string }; - client: { unique: string }; -} - -export interface UmbUserClientCredentialsDataSource { - create(args: UmbUserClientCredentialsDataSourceCreateArgs): Promise; - read(args: UmbUserClientCredentialsDataSourceReadArgs): Promise>>; - delete: (args: UmbUserClientCredentialsDataSourceDeleteArgs) => Promise; +export interface UmbUserClientCredentialModel { + unique: string; } diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/client-credential/repository/user-client-credentials.repository.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/client-credential/repository/user-client-credentials.repository.ts new file mode 100644 index 0000000000..338de3ab8f --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/client-credential/repository/user-client-credentials.repository.ts @@ -0,0 +1,61 @@ +import type { UmbUserClientCredentialsDataSource } from './data-source/index.js'; +import { UmbUserClientCredentialsServerDataSource } from './data-source/user-client-credentials.server.data-source.js'; +import type { + UmbUserClientCredentialsRepositoryCreateArgs, + UmbUserClientCredentialsRepositoryDeleteArgs, + UmbUserClientCredentialsRepositoryReadArgs, +} from './types.js'; +import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; +import { UmbRepositoryBase } from '@umbraco-cms/backoffice/repository'; + +/** + * UmbUserClientCredentialsRepository + * @export + * @class UmbUserClientCredentialsRepository + * @extends {UmbRepositoryBase} + */ +export class UmbUserClientCredentialsRepository extends UmbRepositoryBase { + #source: UmbUserClientCredentialsDataSource; + + /** + * Creates an instance of UmbUserClientCredentialsRepository. + * @param {UmbControllerHost} host - The controller host + * @memberof UmbUserClientCredentialsRepository + */ + constructor(host: UmbControllerHost) { + super(host); + this.#source = new UmbUserClientCredentialsServerDataSource(host); + } + + /** + * Creates a new client credentials for a user + * @param {UmbUserClientCredentialsRepositoryCreateArgs} args - The user and client to create the credentials for + * @returns {*} + * @memberof UmbUserClientCredentialsRepository + */ + async create(args: UmbUserClientCredentialsRepositoryCreateArgs) { + return this.#source.create(args); + } + + /** + * Reads the client credentials for a user + * @param {UmbUserClientCredentialsRepositoryReadArgs} args - The user to read the credentials for + * @returns {*} + * @memberof UmbUserClientCredentialsRepository + */ + async read(args: UmbUserClientCredentialsRepositoryReadArgs) { + return this.#source.read(args); + } + + /** + * Deletes the client credentials for a user + * @param {UmbUserClientCredentialsRepositoryDeleteArgs} args - The user and client unique to delete the credentials for + * @returns {*} + * @memberof UmbUserClientCredentialsRepository + */ + async delete(args: UmbUserClientCredentialsRepositoryDeleteArgs) { + return this.#source.delete(args); + } +} + +export { UmbUserClientCredentialsRepository as api }; From c3f4d4e290c57a46269d3be80c1d87df549ab2ba Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Mon, 2 Sep 2024 16:01:42 +0200 Subject: [PATCH 015/107] clean up --- .../user/user/client-credential/index.ts | 1 + .../user/user/client-credential/manifests.ts | 1 + .../client-credential/repository/constants.ts | 2 +- .../repository/data-source/index.ts | 2 +- .../repository/data-source/types.ts | 31 +++------- ...r-client-credential.server.data-source.ts} | 34 +++++------ .../client-credential/repository/index.ts | 3 +- .../client-credential/repository/manifests.ts | 6 +- .../client-credential/repository/types.ts | 20 +++--- .../user-client-credential.repository.ts | 61 +++++++++++++++++++ .../user-client-credentials.repository.ts | 61 ------------------- .../src/packages/user/user/manifests.ts | 10 +-- 12 files changed, 115 insertions(+), 117 deletions(-) create mode 100644 src/Umbraco.Web.UI.Client/src/packages/user/user/client-credential/manifests.ts rename src/Umbraco.Web.UI.Client/src/packages/user/user/client-credential/repository/data-source/{user-client-credentials.server.data-source.ts => user-client-credential.server.data-source.ts} (55%) create mode 100644 src/Umbraco.Web.UI.Client/src/packages/user/user/client-credential/repository/user-client-credential.repository.ts delete mode 100644 src/Umbraco.Web.UI.Client/src/packages/user/user/client-credential/repository/user-client-credentials.repository.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/client-credential/index.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/client-credential/index.ts index e69de29bb2..3d76f338dd 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/client-credential/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/client-credential/index.ts @@ -0,0 +1 @@ +export * from './repository/index.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/client-credential/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/client-credential/manifests.ts new file mode 100644 index 0000000000..0a214139c1 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/client-credential/manifests.ts @@ -0,0 +1 @@ +export * from './repository/manifests.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/client-credential/repository/constants.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/client-credential/repository/constants.ts index 7e4e853a5d..6cbdba610a 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/client-credential/repository/constants.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/client-credential/repository/constants.ts @@ -1 +1 @@ -export const UMB_USER_CLIENT_CREDENTIALS_REPOSITORY_ALIAS = 'Umb.Repository.User.ClientCredentials'; +export const UMB_USER_CLIENT_CREDENTIAL_REPOSITORY_ALIAS = 'Umb.Repository.User.ClientCredential'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/client-credential/repository/data-source/index.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/client-credential/repository/data-source/index.ts index 16f734cbcb..dd7152279d 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/client-credential/repository/data-source/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/client-credential/repository/data-source/index.ts @@ -1,2 +1,2 @@ export * from './types.js'; -export * from './user-client-credentials.server.data-source.js'; +export * from './user-client-credential.server.data-source.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/client-credential/repository/data-source/types.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/client-credential/repository/data-source/types.ts index 14e6dd533e..0bbb27574a 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/client-credential/repository/data-source/types.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/client-credential/repository/data-source/types.ts @@ -1,24 +1,13 @@ -import type { UmbUserClientCredentialModel } from '../types.js'; +import type { + UmbCreateUserClientCredentialRequestArgs, + UmbDeleteUserClientCredentialRequestArgs, + UmbUserClientCredentialModel, + UmbUserClientCredentialRequestArgs, +} from '../types.js'; import type { UmbDataSourceErrorResponse, UmbDataSourceResponse } from '@umbraco-cms/backoffice/repository'; -export interface UmbUserClientCredentialsDataSourceCreateArgs { - user: { unique: string }; - client: { unique: string; secret: string }; -} - -export interface UmbUserClientCredentialsDataSourceReadArgs { - user: { unique: string }; -} - -export interface UmbUserClientCredentialsDataSourceDeleteArgs { - user: { unique: string }; - client: { unique: string }; -} - -export interface UmbUserClientCredentialsDataSource { - create(args: UmbUserClientCredentialsDataSourceCreateArgs): Promise; - read( - args: UmbUserClientCredentialsDataSourceReadArgs, - ): Promise>>; - delete: (args: UmbUserClientCredentialsDataSourceDeleteArgs) => Promise; +export interface UmbUserClientCredentialDataSource { + create(args: UmbCreateUserClientCredentialRequestArgs): Promise; + read(args: UmbUserClientCredentialRequestArgs): Promise>>; + delete: (args: UmbDeleteUserClientCredentialRequestArgs) => Promise; } diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/client-credential/repository/data-source/user-client-credentials.server.data-source.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/client-credential/repository/data-source/user-client-credential.server.data-source.ts similarity index 55% rename from src/Umbraco.Web.UI.Client/src/packages/user/user/client-credential/repository/data-source/user-client-credentials.server.data-source.ts rename to src/Umbraco.Web.UI.Client/src/packages/user/user/client-credential/repository/data-source/user-client-credential.server.data-source.ts index c140625b7a..f46aa92732 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/client-credential/repository/data-source/user-client-credentials.server.data-source.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/client-credential/repository/data-source/user-client-credential.server.data-source.ts @@ -1,9 +1,9 @@ import type { - UmbUserClientCredentialsDataSource, - UmbUserClientCredentialsDataSourceCreateArgs, - UmbUserClientCredentialsDataSourceDeleteArgs, - UmbUserClientCredentialsDataSourceReadArgs, -} from './types.js'; + UmbCreateUserClientCredentialRequestArgs, + UmbDeleteUserClientCredentialRequestArgs, + UmbUserClientCredentialRequestArgs, +} from '../types.js'; +import type { UmbUserClientCredentialDataSource } from './types.js'; import { UserService } from '@umbraco-cms/backoffice/external/backend-api'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources'; @@ -11,10 +11,10 @@ import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources'; /** * Server data source for user client credentials * @export - * @class UmbUserClientCredentialsServerDataSource - * @implements {UmbUserClientCredentialsDataSource} + * @class UmbUserClientCredentialServerDataSource + * @implements {UmbUserClientCredentialDataSource} */ -export class UmbUserClientCredentialsServerDataSource implements UmbUserClientCredentialsDataSource { +export class UmbUserClientCredentialServerDataSource implements UmbUserClientCredentialDataSource { #host: UmbControllerHost; constructor(host: UmbControllerHost) { @@ -23,11 +23,11 @@ export class UmbUserClientCredentialsServerDataSource implements UmbUserClientCr /** * Creates a new client credentials for a user - * @param {UmbUserClientCredentialsDataSourceCreateArgs} args - The user and client to create the credentials for + * @param {UmbCreateUserClientCredentialRequestArgs} args - The user and client to create the credentials for * @returns {*} - * @memberof UmbUserClientCredentialsServerDataSource + * @memberof UmbUserClientCredentialServerDataSource */ - create(args: UmbUserClientCredentialsDataSourceCreateArgs) { + create(args: UmbCreateUserClientCredentialRequestArgs) { return tryExecuteAndNotify( this.#host, UserService.postUserByIdClientCredentials({ @@ -42,11 +42,11 @@ export class UmbUserClientCredentialsServerDataSource implements UmbUserClientCr /** * Reads the client credentials for a user - * @param {UmbUserClientCredentialsDataSourceReadArgs} args - The user to read the credentials for + * @param {UmbUserClientCredentialRequestArgs} args - The user to read the credentials for * @returns {*} - * @memberof UmbUserClientCredentialsServerDataSource + * @memberof UmbUserClientCredentialServerDataSource */ - async read(args: UmbUserClientCredentialsDataSourceReadArgs) { + async read(args: UmbUserClientCredentialRequestArgs) { const { data, error } = await tryExecuteAndNotify( this.#host, UserService.getUserByIdClientCredentials({ @@ -67,11 +67,11 @@ export class UmbUserClientCredentialsServerDataSource implements UmbUserClientCr /** * Deletes the client credentials for a user - * @param {UmbUserClientCredentialsDataSourceDeleteArgs} args - The user and client unique to delete the credentials for + * @param {UmbDeleteUserClientCredentialRequestArgs} args - The user and client unique to delete the credentials for * @returns {*} - * @memberof UmbUserClientCredentialsServerDataSource + * @memberof UmbUserClientCredentialServerDataSource */ - delete(args: UmbUserClientCredentialsDataSourceDeleteArgs) { + delete(args: UmbDeleteUserClientCredentialRequestArgs) { return tryExecuteAndNotify( this.#host, UserService.deleteUserByIdClientCredentialsByClientId({ diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/client-credential/repository/index.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/client-credential/repository/index.ts index abf2760126..ec915a3b12 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/client-credential/repository/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/client-credential/repository/index.ts @@ -1,2 +1,3 @@ -export * from './user-client-credentials.repository.js'; +export * from './user-client-credential.repository.js'; export * from './constants.js'; +export * from './types.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/client-credential/repository/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/client-credential/repository/manifests.ts index 2c6b56a623..a77e1c8998 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/client-credential/repository/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/client-credential/repository/manifests.ts @@ -1,11 +1,11 @@ -import { UMB_USER_CLIENT_CREDENTIALS_REPOSITORY_ALIAS } from './constants.js'; +import { UMB_USER_CLIENT_CREDENTIAL_REPOSITORY_ALIAS } from './constants.js'; import type { ManifestTypes, UmbBackofficeManifestKind } from '@umbraco-cms/backoffice/extension-registry'; export const manifests: Array = [ { type: 'repository', - alias: UMB_USER_CLIENT_CREDENTIALS_REPOSITORY_ALIAS, + alias: UMB_USER_CLIENT_CREDENTIAL_REPOSITORY_ALIAS, name: 'User Client Credentials Repository', - api: () => import('./user-client-credentials.repository.js'), + api: () => import('./user-client-credential.repository.js'), }, ]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/client-credential/repository/types.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/client-credential/repository/types.ts index a27c8121f7..900d6aadd5 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/client-credential/repository/types.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/client-credential/repository/types.ts @@ -1,12 +1,16 @@ -import type { - UmbUserClientCredentialsDataSourceCreateArgs, - UmbUserClientCredentialsDataSourceDeleteArgs, - UmbUserClientCredentialsDataSourceReadArgs, -} from './data-source/index.js'; +export interface UmbCreateUserClientCredentialRequestArgs { + user: { unique: string }; + client: { unique: string; secret: string }; +} -export type UmbUserClientCredentialsRepositoryCreateArgs = UmbUserClientCredentialsDataSourceCreateArgs; -export type UmbUserClientCredentialsRepositoryReadArgs = UmbUserClientCredentialsDataSourceReadArgs; -export type UmbUserClientCredentialsRepositoryDeleteArgs = UmbUserClientCredentialsDataSourceDeleteArgs; +export interface UmbUserClientCredentialRequestArgs { + user: { unique: string }; +} + +export interface UmbDeleteUserClientCredentialRequestArgs { + user: { unique: string }; + client: { unique: string }; +} export interface UmbUserClientCredentialModel { unique: string; diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/client-credential/repository/user-client-credential.repository.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/client-credential/repository/user-client-credential.repository.ts new file mode 100644 index 0000000000..4d25eedafa --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/client-credential/repository/user-client-credential.repository.ts @@ -0,0 +1,61 @@ +import type { UmbUserClientCredentialDataSource } from './data-source/index.js'; +import { UmbUserClientCredentialServerDataSource } from './data-source/user-client-credential.server.data-source.js'; +import type { + UmbCreateUserClientCredentialRequestArgs, + UmbDeleteUserClientCredentialRequestArgs, + UmbUserClientCredentialRequestArgs, +} from './types.js'; +import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; +import { UmbRepositoryBase } from '@umbraco-cms/backoffice/repository'; + +/** + * UmbUserClientCredentialRepository + * @export + * @class UmbUserClientCredentialRepository + * @extends {UmbRepositoryBase} + */ +export class UmbUserClientCredentialRepository extends UmbRepositoryBase { + #source: UmbUserClientCredentialDataSource; + + /** + * Creates an instance of UmbUserClientCredentialRepository. + * @param {UmbControllerHost} host - The controller host + * @memberof UmbUserClientCredentialRepository + */ + constructor(host: UmbControllerHost) { + super(host); + this.#source = new UmbUserClientCredentialServerDataSource(host); + } + + /** + * Creates a new client credentials for a user + * @param {UmbCreateUserClientCredentialRequestArgs} args - The user and client to create the credentials for + * @returns {*} + * @memberof UmbUserClientCredentialRepository + */ + async requestCreate(args: UmbCreateUserClientCredentialRequestArgs) { + return this.#source.create(args); + } + + /** + * Reads the client credentials for a user + * @param {UmbUserClientCredentialRequestArgs} args - The user to read the credentials for + * @returns {*} + * @memberof UmbUserClientCredentialRepository + */ + async requestClientCredentials(args: UmbUserClientCredentialRequestArgs) { + return this.#source.read(args); + } + + /** + * Deletes the client credentials for a user + * @param {UmbDeleteUserClientCredentialRequestArgs} args - The user and client unique to delete the credentials for + * @returns {*} + * @memberof UmbUserClientCredentialRepository + */ + async requestDelete(args: UmbDeleteUserClientCredentialRequestArgs) { + return this.#source.delete(args); + } +} + +export { UmbUserClientCredentialRepository as api }; diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/client-credential/repository/user-client-credentials.repository.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/client-credential/repository/user-client-credentials.repository.ts deleted file mode 100644 index 338de3ab8f..0000000000 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/client-credential/repository/user-client-credentials.repository.ts +++ /dev/null @@ -1,61 +0,0 @@ -import type { UmbUserClientCredentialsDataSource } from './data-source/index.js'; -import { UmbUserClientCredentialsServerDataSource } from './data-source/user-client-credentials.server.data-source.js'; -import type { - UmbUserClientCredentialsRepositoryCreateArgs, - UmbUserClientCredentialsRepositoryDeleteArgs, - UmbUserClientCredentialsRepositoryReadArgs, -} from './types.js'; -import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; -import { UmbRepositoryBase } from '@umbraco-cms/backoffice/repository'; - -/** - * UmbUserClientCredentialsRepository - * @export - * @class UmbUserClientCredentialsRepository - * @extends {UmbRepositoryBase} - */ -export class UmbUserClientCredentialsRepository extends UmbRepositoryBase { - #source: UmbUserClientCredentialsDataSource; - - /** - * Creates an instance of UmbUserClientCredentialsRepository. - * @param {UmbControllerHost} host - The controller host - * @memberof UmbUserClientCredentialsRepository - */ - constructor(host: UmbControllerHost) { - super(host); - this.#source = new UmbUserClientCredentialsServerDataSource(host); - } - - /** - * Creates a new client credentials for a user - * @param {UmbUserClientCredentialsRepositoryCreateArgs} args - The user and client to create the credentials for - * @returns {*} - * @memberof UmbUserClientCredentialsRepository - */ - async create(args: UmbUserClientCredentialsRepositoryCreateArgs) { - return this.#source.create(args); - } - - /** - * Reads the client credentials for a user - * @param {UmbUserClientCredentialsRepositoryReadArgs} args - The user to read the credentials for - * @returns {*} - * @memberof UmbUserClientCredentialsRepository - */ - async read(args: UmbUserClientCredentialsRepositoryReadArgs) { - return this.#source.read(args); - } - - /** - * Deletes the client credentials for a user - * @param {UmbUserClientCredentialsRepositoryDeleteArgs} args - The user and client unique to delete the credentials for - * @returns {*} - * @memberof UmbUserClientCredentialsRepository - */ - async delete(args: UmbUserClientCredentialsRepositoryDeleteArgs) { - return this.#source.delete(args); - } -} - -export { UmbUserClientCredentialsRepository as api }; diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/manifests.ts index a5eb9bfeea..3eae6c756b 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/manifests.ts @@ -1,24 +1,26 @@ +import { manifests as clientCredentialManifests } from './client-credential/manifests.js'; import { manifests as collectionManifests } from './collection/manifests.js'; import { manifests as conditionsManifests } from './conditions/manifests.js'; import { manifests as entityActionsManifests } from './entity-actions/manifests.js'; import { manifests as entityBulkActionManifests } from './entity-bulk-actions/manifests.js'; import { manifests as inviteManifests } from './invite/manifests.js'; import { manifests as modalManifests } from './modals/manifests.js'; +import { manifests as propertyEditorManifests } from './property-editor/manifests.js'; import { manifests as repositoryManifests } from './repository/manifests.js'; import { manifests as sectionViewManifests } from './section-view/manifests.js'; -import { manifests as propertyEditorManifests } from './property-editor/manifests.js'; import { manifests as workspaceManifests } from './workspace/manifests.js'; -import type { ManifestTypes } from '@umbraco-cms/backoffice/extension-registry'; +import type { ManifestTypes, UmbBackofficeManifestKind } from '@umbraco-cms/backoffice/extension-registry'; -export const manifests: Array = [ +export const manifests: Array = [ + ...clientCredentialManifests, ...collectionManifests, ...conditionsManifests, ...entityActionsManifests, ...entityBulkActionManifests, ...inviteManifests, ...modalManifests, + ...propertyEditorManifests, ...repositoryManifests, ...sectionViewManifests, - ...propertyEditorManifests, ...workspaceManifests, ]; From c3d96fa96f18e2d741b112c668fe661fee25bd12 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Mon, 2 Sep 2024 17:46:46 +0200 Subject: [PATCH 016/107] remove console log --- .../user/user/conditions/user-allow-action-base.condition.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/conditions/user-allow-action-base.condition.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/conditions/user-allow-action-base.condition.ts index fb5bf0f8d1..bdae21f4af 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/conditions/user-allow-action-base.condition.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/conditions/user-allow-action-base.condition.ts @@ -48,7 +48,6 @@ export abstract class UmbUserActionConditionBase super(host, args); this.consumeContext(UMB_USER_WORKSPACE_CONTEXT, (context) => { - console.log(context); this.observe( observeMultiple([context.unique, context.state, context.kind]), ([unique, state, kind]) => { From 043883c1cc65a63eea867c097efcce486b4a7211 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Mon, 2 Sep 2024 21:48:26 +0200 Subject: [PATCH 017/107] return newly created credential id --- .../user-client-credential.server.data-source.ts | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/client-credential/repository/data-source/user-client-credential.server.data-source.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/client-credential/repository/data-source/user-client-credential.server.data-source.ts index f46aa92732..af80fd15b6 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/client-credential/repository/data-source/user-client-credential.server.data-source.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/client-credential/repository/data-source/user-client-credential.server.data-source.ts @@ -27,8 +27,8 @@ export class UmbUserClientCredentialServerDataSource implements UmbUserClientCre * @returns {*} * @memberof UmbUserClientCredentialServerDataSource */ - create(args: UmbCreateUserClientCredentialRequestArgs) { - return tryExecuteAndNotify( + async create(args: UmbCreateUserClientCredentialRequestArgs) { + const { error } = await tryExecuteAndNotify( this.#host, UserService.postUserByIdClientCredentials({ id: args.user.unique, @@ -38,6 +38,12 @@ export class UmbUserClientCredentialServerDataSource implements UmbUserClientCre }, }), ); + + if (!error) { + return { data: { unique: args.client.unique } }; + } + + return { error }; } /** From 70e68d6e305a862e0329f348173321668a373d6f Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Mon, 2 Sep 2024 21:50:47 +0200 Subject: [PATCH 018/107] add create modal --- .../client-credential/create/manifests.ts | 5 + .../create/modal/constants.ts | 1 + ...te-user-client-credential-modal.element.ts | 104 ++++++++++++++++++ ...eate-user-client-credential-modal.token.ts | 25 +++++ .../create/modal/manifests.ts | 11 ++ .../user/user/client-credential/manifests.ts | 6 +- ...er-workspace-client-credentials.element.ts | 90 +++++++++++++++ .../user-workspace-editor.element.ts | 2 + 8 files changed, 243 insertions(+), 1 deletion(-) create mode 100644 src/Umbraco.Web.UI.Client/src/packages/user/user/client-credential/create/manifests.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/user/user/client-credential/create/modal/constants.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/user/user/client-credential/create/modal/create-user-client-credential-modal.element.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/user/user/client-credential/create/modal/create-user-client-credential-modal.token.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/user/user/client-credential/create/modal/manifests.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/user/user/workspace/components/user-workspace-client-credentials/user-workspace-client-credentials.element.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/client-credential/create/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/client-credential/create/manifests.ts new file mode 100644 index 0000000000..420b53915c --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/client-credential/create/manifests.ts @@ -0,0 +1,5 @@ +import { manifests as modalManifests } from './modal/manifests.js'; + +import type { ManifestTypes, UmbBackofficeManifestKind } from '@umbraco-cms/backoffice/extension-registry'; + +export const manifests: Array = [...modalManifests]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/client-credential/create/modal/constants.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/client-credential/create/modal/constants.ts new file mode 100644 index 0000000000..955ffa9cd6 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/client-credential/create/modal/constants.ts @@ -0,0 +1 @@ +export const UMB_CREATE_USER_CLIENT_CREDENTIAL_MODAL_ALIAS = 'Umb.Modal.User.ClientCredential.Create'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/client-credential/create/modal/create-user-client-credential-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/client-credential/create/modal/create-user-client-credential-modal.element.ts new file mode 100644 index 0000000000..dcd8c703f9 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/client-credential/create/modal/create-user-client-credential-modal.element.ts @@ -0,0 +1,104 @@ +import type { UmbCreateUserClientCredentialRequestArgs } from '../../repository/index.js'; +import { UmbUserClientCredentialRepository } from '../../repository/index.js'; +import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; +import { css, html, customElement, query } from '@umbraco-cms/backoffice/external/lit'; +import { UmbModalBaseElement } from '@umbraco-cms/backoffice/modal'; + +const elementName = 'umb-create-user-client-credential-modal'; +@customElement(elementName) +export class UmbCreateUserModalElement extends UmbModalBaseElement { + @query('#CreateUserClientCredentialForm') + _form?: HTMLFormElement; + + #userClientCredentialRepository = new UmbUserClientCredentialRepository(this); + + #uniquePrefix = 'umbraco-back-office-'; + + async #onSubmit(e: SubmitEvent) { + e.preventDefault(); + + const form = e.target as HTMLFormElement; + if (!form) return; + + const isValid = form.checkValidity(); + if (!isValid) return; + + const formData = new FormData(form); + + const unique = formData.get('unique') as string; + const secret = formData.get('secret') as string; + + const payload: UmbCreateUserClientCredentialRequestArgs = { + user: { unique: this.data.user.unique }, + client: { unique, secret }, + }; + + // TODO: figure out when to use email or username + const { data } = await this.#userClientCredentialRepository.requestCreate(payload); + debugger; + } + + override render() { + return html` +

Lorem

+ + ${this.#renderForm()} + + +
`; + } + + #renderForm() { + return html` + + + Id + +
${this.#uniquePrefix}
+
+
+ + Secret + + + +
`; + } + + static override styles = [ + UmbTextStyles, + css` + uui-input, + uui-input-password { + width: 580px; + } + + .prepend { + user-select: none; + height: 100%; + padding: 0 var(--uui-size-3); + border-right: 1px solid var(--uui-input-border-color, var(--uui-color-border)); + background: #f3f3f3; + color: grey; + display: flex; + justify-content: center; + align-items: center; + white-space: nowrap; + } + `, + ]; +} + +export { UmbCreateUserModalElement as element }; + +declare global { + interface HTMLElementTagNameMap { + [elementName]: UmbCreateUserModalElement; + } +} diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/client-credential/create/modal/create-user-client-credential-modal.token.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/client-credential/create/modal/create-user-client-credential-modal.token.ts new file mode 100644 index 0000000000..be33567081 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/client-credential/create/modal/create-user-client-credential-modal.token.ts @@ -0,0 +1,25 @@ +import { UMB_CREATE_USER_CLIENT_CREDENTIAL_MODAL_ALIAS } from './constants.js'; +import { UmbModalToken } from '@umbraco-cms/backoffice/modal'; + +export interface UmbCreateUserClientCredentialModalData { + user: { + unique: string; + }; +} + +export interface UmbBlockCatalogueModalValue { + client: { + unique: string; + secret: string; + }; +} + +export const UMB_CREATE_USER_CLIENT_CREDENTIAL_MODAL = new UmbModalToken( + UMB_CREATE_USER_CLIENT_CREDENTIAL_MODAL_ALIAS, + { + modal: { + type: 'dialog', + size: 'small', + }, + }, +); diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/client-credential/create/modal/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/client-credential/create/modal/manifests.ts new file mode 100644 index 0000000000..662ecec620 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/client-credential/create/modal/manifests.ts @@ -0,0 +1,11 @@ +import { UMB_CREATE_USER_CLIENT_CREDENTIAL_MODAL_ALIAS } from './constants.js'; +import type { ManifestTypes, UmbBackofficeManifestKind } from '@umbraco-cms/backoffice/extension-registry'; + +export const manifests: Array = [ + { + type: 'modal', + alias: UMB_CREATE_USER_CLIENT_CREDENTIAL_MODAL_ALIAS, + name: 'Create User Client Credential Modal', + js: () => import('./create-user-client-credential-modal.element.js'), + }, +]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/client-credential/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/client-credential/manifests.ts index 0a214139c1..eba4cdb996 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/client-credential/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/client-credential/manifests.ts @@ -1 +1,5 @@ -export * from './repository/manifests.js'; +import { manifests as createManifests } from './create/manifests.js'; +import { manifests as repositoryManifests } from './repository/manifests.js'; +import type { ManifestTypes, UmbBackofficeManifestKind } from '@umbraco-cms/backoffice/extension-registry'; + +export const manifests: Array = [...createManifests, ...repositoryManifests]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/workspace/components/user-workspace-client-credentials/user-workspace-client-credentials.element.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/workspace/components/user-workspace-client-credentials/user-workspace-client-credentials.element.ts new file mode 100644 index 0000000000..6733014ea1 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/workspace/components/user-workspace-client-credentials/user-workspace-client-credentials.element.ts @@ -0,0 +1,90 @@ +import { UMB_USER_WORKSPACE_CONTEXT } from '../../user-workspace.context-token.js'; +import type { UmbUserClientCredentialModel } from '../../../client-credential/index.js'; +import { UmbUserClientCredentialRepository } from '../../../client-credential/index.js'; +import { html, customElement, state, css } from '@umbraco-cms/backoffice/external/lit'; +import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; +import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; +import { UMB_MODAL_MANAGER_CONTEXT } from '@umbraco-cms/backoffice/modal'; +import { UMB_CREATE_USER_CLIENT_CREDENTIAL_MODAL } from '../../../client-credential/create/modal/create-user-client-credential-modal.token.js'; + +const elementName = 'umb-user-workspace-client-credentials'; +@customElement(elementName) +export class UmbUserWorkspaceClientCredentialsElement extends UmbLitElement { + @state() + private _userUnique?: string; + + @state() + private _clientCredentials: UmbUserClientCredentialModel[] = []; + + #userWorkspaceContext?: typeof UMB_USER_WORKSPACE_CONTEXT.TYPE; + #modalManagerContext? = UMB_MODAL_MANAGER_CONTEXT.TYPE; + #userClientCredentialRepository = new UmbUserClientCredentialRepository(this); + + constructor() { + super(); + + this.consumeContext(UMB_USER_WORKSPACE_CONTEXT, (instance) => { + this.#userWorkspaceContext = instance; + this.observe( + this.#userWorkspaceContext.unique, + async (unique) => this.#onUserUniqueChange(unique), + 'umbUserUniqueObserver', + ); + }); + + this.consumeContext(UMB_MODAL_MANAGER_CONTEXT, (instance) => { + this.#modalManagerContext = instance; + }); + } + + async #onUserUniqueChange(unique: string | undefined) { + if (unique && this._userUnique !== unique) { + const { data } = await this.#userClientCredentialRepository.requestClientCredentials({ user: { unique } }); + if (data) { + console.log(data); + } + } + + this._userUnique = unique; + } + + #onAdd() { + if (!this.#modalManagerContext) throw new Error('Modal Manager Context not available'); + + const modalContext = this.#modalManagerContext.open(this, UMB_CREATE_USER_CLIENT_CREDENTIAL_MODAL, { + data: { + user: { + unique: this._userUnique, + }, + }, + }); + + modalContext.onSubmit().then((result) => { + console.log('submit', result); + }); + + console.log('add'); + } + + override render() { + return html` +
Client Credentials
+ +
`; + } + + static override styles = [ + UmbTextStyles, + css` + uui-input { + width: 100%; + } + `, + ]; +} + +declare global { + interface HTMLElementTagNameMap { + [elementName]: UmbUserWorkspaceClientCredentialsElement; + } +} diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/workspace/user-workspace-editor.element.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/workspace/user-workspace-editor.element.ts index 2c9d30f10f..1305454d14 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/workspace/user-workspace-editor.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/workspace/user-workspace-editor.element.ts @@ -13,6 +13,7 @@ import './components/user-workspace-profile-settings/user-workspace-profile-sett import './components/user-workspace-access/user-workspace-access.element.js'; import './components/user-workspace-info/user-workspace-info.element.js'; import './components/user-workspace-avatar/user-workspace-avatar.element.js'; +import './components/user-workspace-client-credentials/user-workspace-client-credentials.element.js'; @customElement('umb-user-workspace-editor') export class UmbUserWorkspaceEditorElement extends UmbLitElement { @@ -73,6 +74,7 @@ export class UmbUserWorkspaceEditorElement extends UmbLitElement { return html` + `; From 68ea237d2e7c120baa583c20013a8950919bca9a Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Mon, 2 Sep 2024 21:51:44 +0200 Subject: [PATCH 019/107] clean up --- .../user/modals/create/create-user-modal.element.ts | 12 +++++------- .../create/create-user-success-modal.element.ts | 2 ++ .../detail/user-detail.server.data-source.ts | 4 ++-- .../src/packages/user/user/repository/item/types.ts | 2 ++ .../repository/item/user-item.server.data-source.ts | 1 + .../src/packages/user/user/types.ts | 4 ++-- .../src/packages/user/user/utils/index.ts | 4 ++-- 7 files changed, 16 insertions(+), 13 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/modals/create/create-user-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/modals/create/create-user-modal.element.ts index 85b6facca1..d3dc9ed3cc 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/modals/create/create-user-modal.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/modals/create/create-user-modal.element.ts @@ -1,5 +1,5 @@ import { UmbUserDetailRepository } from '../../repository/index.js'; -import { UmbUserModelKind, UmbUserModelKindType } from '../../utils/index.js'; +import { UmbUserKind, UmbUserKindType } from '../../utils/index.js'; import { UMB_CREATE_USER_SUCCESS_MODAL } from './create-user-success-modal.token.js'; import type { UmbUserGroupInputElement } from '@umbraco-cms/backoffice/user-group'; import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; @@ -25,7 +25,7 @@ export class UmbCreateUserModalElement extends UmbModalBaseElement { const formData = new FormData(form); - const kind = formData.get('kind') as UmbUserModelKindType; + const kind = formData.get('kind') as UmbUserKindType; const name = formData.get('name') as string; const email = formData.get('email') as string; @@ -99,12 +99,10 @@ export class UmbCreateUserModalElement extends UmbModalBaseElement {
Kind - + - ${UmbUserModelKind.DEFAULT} - ${UmbUserModelKind.API} + ${UmbUserKind.DEFAULT} + ${UmbUserKind.API} diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/modals/create/create-user-success-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/modals/create/create-user-success-modal.element.ts index 8185df073f..03a6872298 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/modals/create/create-user-success-modal.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/modals/create/create-user-success-modal.element.ts @@ -36,6 +36,8 @@ export class UmbCreateUserSuccessModalElement extends UmbModalBaseElement< const unique = this.data?.user.unique; if (!unique) throw new Error('No user unique is provided'); + debugger; + const [userItemResponse, newPasswordResponse] = await Promise.all([ this.#userItemRepository.requestItems([unique]), this.#userNewPasswordRepository.requestNewPassword(unique), diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/repository/detail/user-detail.server.data-source.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/repository/detail/user-detail.server.data-source.ts index 0d89ee2a79..88a9c88a09 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/repository/detail/user-detail.server.data-source.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/repository/detail/user-detail.server.data-source.ts @@ -10,7 +10,7 @@ import type { import { UserService } from '@umbraco-cms/backoffice/external/backend-api'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources'; -import { UmbUserModelKind } from '../../utils/index.js'; +import { UmbUserKind } from '../../utils/index.js'; /** * A data source for the User that fetches data from the server @@ -46,7 +46,7 @@ export class UmbUserServerDataSource implements UmbDetailDataSource; entityType: UmbUserEntityType; + kind: UmbUserKindType; name: string; unique: string; } diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/repository/item/user-item.server.data-source.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/repository/item/user-item.server.data-source.ts index 4856549327..d435990d00 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/repository/item/user-item.server.data-source.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/repository/item/user-item.server.data-source.ts @@ -33,5 +33,6 @@ const mapper = (item: UserItemResponseModel): UmbUserItemModel => { entityType: UMB_USER_ENTITY_TYPE, name: item.name, unique: item.id, + kind: item.kind, }; }; diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/types.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/types.ts index b0cbe18174..4c3b9f9935 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/types.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/types.ts @@ -5,7 +5,7 @@ import { UserStateModel, type UserTwoFactorProviderModel, } from '@umbraco-cms/backoffice/external/backend-api'; -import { UmbUserModelKindType } from './utils/index.js'; +import { UmbUserKindType } from './utils/index.js'; export type UmbUserStateEnum = UserStateModel; export const UmbUserStateEnum = UserStateModel; @@ -27,7 +27,7 @@ export interface UmbUserDetailModel extends UmbUserStartNodesModel { updateDate: string | null; userGroupUniques: Array; userName: string; - kind: UmbUserModelKindType; + kind: UmbUserKindType; } export interface UmbUserStartNodesModel { diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/utils/index.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/utils/index.ts index 6189fbcb68..4115ca2bbc 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/utils/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/utils/index.ts @@ -1,8 +1,8 @@ export * from './is-user.function.js'; -export type UmbUserModelKindType = 'Default' | 'Api'; +export type UmbUserKindType = 'Default' | 'Api'; -export const UmbUserModelKind = Object.freeze({ +export const UmbUserKind = Object.freeze({ DEFAULT: 'Default', API: 'Api', }); From 466a456967a5d5a9cee9a7618b7d85f1dfb21650 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 3 Sep 2024 09:20:56 +0200 Subject: [PATCH 020/107] map kind --- .../collection/repository/user-collection.server.data-source.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/collection/repository/user-collection.server.data-source.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/collection/repository/user-collection.server.data-source.ts index 57af3559cc..de1a3a767f 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/collection/repository/user-collection.server.data-source.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/collection/repository/user-collection.server.data-source.ts @@ -86,6 +86,7 @@ export class UmbUserCollectionServerDataSource implements UmbCollectionDataSourc lastLockoutDate: item.lastLockoutDate || null, lastPasswordChangeDate: item.lastPasswordChangeDate || null, isAdmin: item.isAdmin, + kind: item.kind, }; return userDetail; From 40ae96596f5daf2db851cd602fa503e02c6731e2 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 3 Sep 2024 09:21:30 +0200 Subject: [PATCH 021/107] move client credentials to the sidebar + stack the elements --- .../user-workspace-avatar.element.ts | 1 - ...er-workspace-client-credentials.element.ts | 6 +++++- .../user-workspace-info.element.ts | 8 ++++---- .../user-workspace-editor.element.ts | 19 ++++++++++--------- 4 files changed, 19 insertions(+), 15 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/workspace/components/user-workspace-avatar/user-workspace-avatar.element.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/workspace/components/user-workspace-avatar/user-workspace-avatar.element.ts index a7ceaacf4c..307900260b 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/workspace/components/user-workspace-avatar/user-workspace-avatar.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/workspace/components/user-workspace-avatar/user-workspace-avatar.element.ts @@ -143,7 +143,6 @@ export class UmbUserAvatarElement extends UmbLitElement { css` :host { display: block; - margin-bottom: var(--uui-size-space-4); } #Avatar { diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/workspace/components/user-workspace-client-credentials/user-workspace-client-credentials.element.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/workspace/components/user-workspace-client-credentials/user-workspace-client-credentials.element.ts index 6733014ea1..c5dd062e8b 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/workspace/components/user-workspace-client-credentials/user-workspace-client-credentials.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/workspace/components/user-workspace-client-credentials/user-workspace-client-credentials.element.ts @@ -1,11 +1,11 @@ import { UMB_USER_WORKSPACE_CONTEXT } from '../../user-workspace.context-token.js'; import type { UmbUserClientCredentialModel } from '../../../client-credential/index.js'; import { UmbUserClientCredentialRepository } from '../../../client-credential/index.js'; +import { UMB_CREATE_USER_CLIENT_CREDENTIAL_MODAL } from '../../../client-credential/create/modal/create-user-client-credential-modal.token.js'; import { html, customElement, state, css } from '@umbraco-cms/backoffice/external/lit'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; import { UMB_MODAL_MANAGER_CONTEXT } from '@umbraco-cms/backoffice/modal'; -import { UMB_CREATE_USER_CLIENT_CREDENTIAL_MODAL } from '../../../client-credential/create/modal/create-user-client-credential-modal.token.js'; const elementName = 'umb-user-workspace-client-credentials'; @customElement(elementName) @@ -76,6 +76,10 @@ export class UmbUserWorkspaceClientCredentialsElement extends UmbLitElement { static override styles = [ UmbTextStyles, css` + :host { + display: block; + } + uui-input { width: 100%; } diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/workspace/components/user-workspace-info/user-workspace-info.element.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/workspace/components/user-workspace-info/user-workspace-info.element.ts index 471781d27e..27c46e106a 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/workspace/components/user-workspace-info/user-workspace-info.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/workspace/components/user-workspace-info/user-workspace-info.element.ts @@ -104,12 +104,12 @@ export class UmbUserWorkspaceInfoElement extends UmbLitElement { static override styles = [ UmbTextStyles, css` - uui-tag { - width: fit-content; + :host { + display: block; } - #user-info { - margin-bottom: var(--uui-size-space-4); + uui-tag { + width: fit-content; } #state { diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/workspace/user-workspace-editor.element.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/workspace/user-workspace-editor.element.ts index 1305454d14..54458b0d19 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/workspace/user-workspace-editor.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/workspace/user-workspace-editor.element.ts @@ -74,7 +74,6 @@ export class UmbUserWorkspaceEditorElement extends UmbLitElement { return html` - `; @@ -84,14 +83,16 @@ export class UmbUserWorkspaceEditorElement extends UmbLitElement { if (!this._user) return nothing; return html` - - - - - - + + + + + + + + `; } From ed86010ff98fa26baa43f3baf43080f41e045836 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 3 Sep 2024 09:21:35 +0200 Subject: [PATCH 022/107] Update user-allow-change-password-action.condition.ts --- .../user-allow-change-password-action.condition.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/conditions/allow-change-password/user-allow-change-password-action.condition.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/conditions/allow-change-password/user-allow-change-password-action.condition.ts index ed78c34e78..d82ad989ae 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/conditions/allow-change-password/user-allow-change-password-action.condition.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/conditions/allow-change-password/user-allow-change-password-action.condition.ts @@ -1,10 +1,10 @@ -import { UmbUserModelKind } from '../../utils/index.js'; +import { UmbUserKind } from '../../utils/index.js'; import { UmbUserActionConditionBase } from '../user-allow-action-base.condition.js'; export class UmbUserAllowChangePasswordActionCondition extends UmbUserActionConditionBase { async _onUserDataChange() { // don't allow the current user to delete themselves - if (this.userKind === UmbUserModelKind.DEFAULT) { + if (this.userKind === UmbUserKind.DEFAULT) { this.permitted = true; } else { this.permitted = false; From 2caa0b28e58644e00385fe99274864d50d2c5014 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 3 Sep 2024 09:21:53 +0200 Subject: [PATCH 023/107] return data from create --- ...eate-user-client-credential-modal.element.ts | 17 +++++++++++++++-- ...create-user-client-credential-modal.token.ts | 2 +- .../repository/data-source/types.ts | 2 +- 3 files changed, 17 insertions(+), 4 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/client-credential/create/modal/create-user-client-credential-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/client-credential/create/modal/create-user-client-credential-modal.element.ts index dcd8c703f9..6a8c9ab5f6 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/client-credential/create/modal/create-user-client-credential-modal.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/client-credential/create/modal/create-user-client-credential-modal.element.ts @@ -1,12 +1,19 @@ import type { UmbCreateUserClientCredentialRequestArgs } from '../../repository/index.js'; import { UmbUserClientCredentialRepository } from '../../repository/index.js'; +import type { + UmbCreateUserClientCredentialModalData, + UmbCreateUserClientCredentialModalValue, +} from './create-user-client-credential-modal.token.js'; import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; import { css, html, customElement, query } from '@umbraco-cms/backoffice/external/lit'; import { UmbModalBaseElement } from '@umbraco-cms/backoffice/modal'; const elementName = 'umb-create-user-client-credential-modal'; @customElement(elementName) -export class UmbCreateUserModalElement extends UmbModalBaseElement { +export class UmbCreateUserModalElement extends UmbModalBaseElement< + UmbCreateUserClientCredentialModalData, + UmbCreateUserClientCredentialModalValue +> { @query('#CreateUserClientCredentialForm') _form?: HTMLFormElement; @@ -17,6 +24,8 @@ export class UmbCreateUserModalElement extends UmbModalBaseElement { async #onSubmit(e: SubmitEvent) { e.preventDefault(); + if (this.data?.user?.unique === undefined) throw new Error('User unique is required'); + const form = e.target as HTMLFormElement; if (!form) return; @@ -35,7 +44,11 @@ export class UmbCreateUserModalElement extends UmbModalBaseElement { // TODO: figure out when to use email or username const { data } = await this.#userClientCredentialRepository.requestCreate(payload); - debugger; + + if (data) { + this.updateValue({ client: { unique: data.unique, secret } }); + this._submitModal(); + } } override render() { diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/client-credential/create/modal/create-user-client-credential-modal.token.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/client-credential/create/modal/create-user-client-credential-modal.token.ts index be33567081..be0a6e9c6e 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/client-credential/create/modal/create-user-client-credential-modal.token.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/client-credential/create/modal/create-user-client-credential-modal.token.ts @@ -7,7 +7,7 @@ export interface UmbCreateUserClientCredentialModalData { }; } -export interface UmbBlockCatalogueModalValue { +export interface UmbCreateUserClientCredentialModalValue { client: { unique: string; secret: string; diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/client-credential/repository/data-source/types.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/client-credential/repository/data-source/types.ts index 0bbb27574a..6b3356f8f5 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/client-credential/repository/data-source/types.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/client-credential/repository/data-source/types.ts @@ -7,7 +7,7 @@ import type { import type { UmbDataSourceErrorResponse, UmbDataSourceResponse } from '@umbraco-cms/backoffice/repository'; export interface UmbUserClientCredentialDataSource { - create(args: UmbCreateUserClientCredentialRequestArgs): Promise; + create(args: UmbCreateUserClientCredentialRequestArgs): Promise>; read(args: UmbUserClientCredentialRequestArgs): Promise>>; delete: (args: UmbDeleteUserClientCredentialRequestArgs) => Promise; } From 0cc4b8c21044e4855b2f39216cab50d4c640eb32 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 3 Sep 2024 09:25:28 +0200 Subject: [PATCH 024/107] style add button --- .../user-workspace-client-credentials.element.ts | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/workspace/components/user-workspace-client-credentials/user-workspace-client-credentials.element.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/workspace/components/user-workspace-client-credentials/user-workspace-client-credentials.element.ts index c5dd062e8b..4259feea7c 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/workspace/components/user-workspace-client-credentials/user-workspace-client-credentials.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/workspace/components/user-workspace-client-credentials/user-workspace-client-credentials.element.ts @@ -69,7 +69,11 @@ export class UmbUserWorkspaceClientCredentialsElement extends UmbLitElement { override render() { return html`
Client Credentials
- +
`; } @@ -83,6 +87,10 @@ export class UmbUserWorkspaceClientCredentialsElement extends UmbLitElement { uui-input { width: 100%; } + + #add-button { + width: 100%; + } `, ]; } From 4d7c3bda4b07261a87f812de05f6373f63766a40 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 3 Sep 2024 09:56:46 +0200 Subject: [PATCH 025/107] wire up delete --- ...er-workspace-client-credentials.element.ts | 38 ++++++++++++++++--- 1 file changed, 33 insertions(+), 5 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/workspace/components/user-workspace-client-credentials/user-workspace-client-credentials.element.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/workspace/components/user-workspace-client-credentials/user-workspace-client-credentials.element.ts index 4259feea7c..c2a6aba25c 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/workspace/components/user-workspace-client-credentials/user-workspace-client-credentials.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/workspace/components/user-workspace-client-credentials/user-workspace-client-credentials.element.ts @@ -1,11 +1,14 @@ import { UMB_USER_WORKSPACE_CONTEXT } from '../../user-workspace.context-token.js'; -import type { UmbUserClientCredentialModel } from '../../../client-credential/index.js'; +import type { + UmbDeleteUserClientCredentialRequestArgs, + UmbUserClientCredentialModel, +} from '../../../client-credential/index.js'; import { UmbUserClientCredentialRepository } from '../../../client-credential/index.js'; import { UMB_CREATE_USER_CLIENT_CREDENTIAL_MODAL } from '../../../client-credential/create/modal/create-user-client-credential-modal.token.js'; import { html, customElement, state, css } from '@umbraco-cms/backoffice/external/lit'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; -import { UMB_MODAL_MANAGER_CONTEXT } from '@umbraco-cms/backoffice/modal'; +import { UMB_MODAL_MANAGER_CONTEXT, umbConfirmModal } from '@umbraco-cms/backoffice/modal'; const elementName = 'umb-user-workspace-client-credentials'; @customElement(elementName) @@ -41,15 +44,17 @@ export class UmbUserWorkspaceClientCredentialsElement extends UmbLitElement { if (unique && this._userUnique !== unique) { const { data } = await this.#userClientCredentialRepository.requestClientCredentials({ user: { unique } }); if (data) { - console.log(data); + this._clientCredentials = data; } } this._userUnique = unique; } - #onAdd() { + #onAdd(event: Event) { + event.stopPropagation(); if (!this.#modalManagerContext) throw new Error('Modal Manager Context not available'); + if (!this._userUnique) throw new Error('User unique not available'); const modalContext = this.#modalManagerContext.open(this, UMB_CREATE_USER_CLIENT_CREDENTIAL_MODAL, { data: { @@ -62,13 +67,36 @@ export class UmbUserWorkspaceClientCredentialsElement extends UmbLitElement { modalContext.onSubmit().then((result) => { console.log('submit', result); }); + } - console.log('add'); + async #onDelete(event: Event, client: UmbUserClientCredentialModel) { + event.stopPropagation(); + if (!this._userUnique) throw new Error('User unique not available'); + + await umbConfirmModal(this, { + headline: `Delete ${client.unique}`, + content: `Are you sure you want to delete ${client.unique}?`, + confirmLabel: 'Delete', + color: 'danger', + }); + + const payload: UmbDeleteUserClientCredentialRequestArgs = { + user: { unique: this._userUnique }, + client: { unique: client.unique }, + }; + + this.#userClientCredentialRepository.requestDelete(payload); } override render() { return html`
Client Credentials
+ ${this._clientCredentials.map( + (client) => + html`
+ ${client.unique} this.#onDelete(event, client)}>Delete +
`, + )} Date: Tue, 3 Sep 2024 10:39:11 +0200 Subject: [PATCH 026/107] only render client credentials for api kinds --- ...er-workspace-client-credentials.element.ts | 33 +++++++++++++++---- 1 file changed, 26 insertions(+), 7 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/workspace/components/user-workspace-client-credentials/user-workspace-client-credentials.element.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/workspace/components/user-workspace-client-credentials/user-workspace-client-credentials.element.ts index c2a6aba25c..5177dbf7d0 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/workspace/components/user-workspace-client-credentials/user-workspace-client-credentials.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/workspace/components/user-workspace-client-credentials/user-workspace-client-credentials.element.ts @@ -5,7 +5,8 @@ import type { } from '../../../client-credential/index.js'; import { UmbUserClientCredentialRepository } from '../../../client-credential/index.js'; import { UMB_CREATE_USER_CLIENT_CREDENTIAL_MODAL } from '../../../client-credential/create/modal/create-user-client-credential-modal.token.js'; -import { html, customElement, state, css } from '@umbraco-cms/backoffice/external/lit'; +import { UmbUserKind } from '../../../utils/index.js'; +import { html, customElement, state, css, nothing } from '@umbraco-cms/backoffice/external/lit'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; import { UMB_MODAL_MANAGER_CONTEXT, umbConfirmModal } from '@umbraco-cms/backoffice/modal'; @@ -16,6 +17,9 @@ export class UmbUserWorkspaceClientCredentialsElement extends UmbLitElement { @state() private _userUnique?: string; + @state() + private _userKind?: string; + @state() private _clientCredentials: UmbUserClientCredentialModel[] = []; @@ -28,6 +32,9 @@ export class UmbUserWorkspaceClientCredentialsElement extends UmbLitElement { this.consumeContext(UMB_USER_WORKSPACE_CONTEXT, (instance) => { this.#userWorkspaceContext = instance; + + this.observe(this.#userWorkspaceContext.kind, (kind) => (this._userKind = kind), 'umbUserKindObserver'); + this.observe( this.#userWorkspaceContext.unique, async (unique) => this.#onUserUniqueChange(unique), @@ -89,14 +96,11 @@ export class UmbUserWorkspaceClientCredentialsElement extends UmbLitElement { } override render() { + if (this._userKind !== UmbUserKind.API) return nothing; + return html`
Client Credentials
- ${this._clientCredentials.map( - (client) => - html`
- ${client.unique} this.#onDelete(event, client)}>Delete -
`, - )} + ${this._clientCredentials.map((client) => html` ${this.#renderItem(client)} `)} `; } + #renderItem(client: UmbUserClientCredentialModel) { + return html` + + + this.#onDelete(event, client)} + label="Delete ${client.unique}" + compact + > + + `; + } + static override styles = [ UmbTextStyles, css` From 42e4bdaf94856daec5e08385e123b9f837fef244 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 3 Sep 2024 10:53:25 +0200 Subject: [PATCH 027/107] set modal types --- .../create-user-client-credential-modal.token.ts | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/client-credential/create/modal/create-user-client-credential-modal.token.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/client-credential/create/modal/create-user-client-credential-modal.token.ts index be0a6e9c6e..a0179a2ea7 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/client-credential/create/modal/create-user-client-credential-modal.token.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/client-credential/create/modal/create-user-client-credential-modal.token.ts @@ -14,12 +14,12 @@ export interface UmbCreateUserClientCredentialModalValue { }; } -export const UMB_CREATE_USER_CLIENT_CREDENTIAL_MODAL = new UmbModalToken( - UMB_CREATE_USER_CLIENT_CREDENTIAL_MODAL_ALIAS, - { - modal: { - type: 'dialog', - size: 'small', - }, +export const UMB_CREATE_USER_CLIENT_CREDENTIAL_MODAL = new UmbModalToken< + UmbCreateUserClientCredentialModalData, + UmbCreateUserClientCredentialModalValue +>(UMB_CREATE_USER_CLIENT_CREDENTIAL_MODAL_ALIAS, { + modal: { + type: 'dialog', + size: 'small', }, -); +}); From 5212c59a165e18f28b7b9e4d11759a4ed22f32a8 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 3 Sep 2024 10:53:44 +0200 Subject: [PATCH 028/107] reload when creating and deleting --- ...er-workspace-client-credentials.element.ts | 33 +++++++++++++------ 1 file changed, 23 insertions(+), 10 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/workspace/components/user-workspace-client-credentials/user-workspace-client-credentials.element.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/workspace/components/user-workspace-client-credentials/user-workspace-client-credentials.element.ts index 5177dbf7d0..7d3fa116f9 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/workspace/components/user-workspace-client-credentials/user-workspace-client-credentials.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/workspace/components/user-workspace-client-credentials/user-workspace-client-credentials.element.ts @@ -47,15 +47,26 @@ export class UmbUserWorkspaceClientCredentialsElement extends UmbLitElement { }); } - async #onUserUniqueChange(unique: string | undefined) { + #onUserUniqueChange(unique: string | undefined) { if (unique && this._userUnique !== unique) { - const { data } = await this.#userClientCredentialRepository.requestClientCredentials({ user: { unique } }); - if (data) { - this._clientCredentials = data; - } + this._userUnique = unique; + this.#loadClientCredentials(); } - this._userUnique = unique; + if (!unique) { + this._userUnique = undefined; + this._clientCredentials = []; + } + } + + async #loadClientCredentials() { + if (!this._userUnique) throw new Error('User unique not available'); + + const { data } = await this.#userClientCredentialRepository.requestClientCredentials({ + user: { unique: this._userUnique }, + }); + + this._clientCredentials = data ?? []; } #onAdd(event: Event) { @@ -71,9 +82,7 @@ export class UmbUserWorkspaceClientCredentialsElement extends UmbLitElement { }, }); - modalContext.onSubmit().then((result) => { - console.log('submit', result); - }); + modalContext.onSubmit().then(() => this.#loadClientCredentials()); } async #onDelete(event: Event, client: UmbUserClientCredentialModel) { @@ -92,7 +101,11 @@ export class UmbUserWorkspaceClientCredentialsElement extends UmbLitElement { client: { unique: client.unique }, }; - this.#userClientCredentialRepository.requestDelete(payload); + const { error } = await this.#userClientCredentialRepository.requestDelete(payload); + + if (!error) { + this.#loadClientCredentials(); + } } override render() { From a6c2fa7ccca218774540c82820045c1ede201df9 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 3 Sep 2024 11:00:03 +0200 Subject: [PATCH 029/107] add kind to info --- src/Umbraco.Web.UI.Client/src/assets/lang/da-dk.ts | 1 + src/Umbraco.Web.UI.Client/src/assets/lang/en-us.ts | 1 + .../user-workspace-info/user-workspace-info.element.ts | 4 ++++ 3 files changed, 6 insertions(+) diff --git a/src/Umbraco.Web.UI.Client/src/assets/lang/da-dk.ts b/src/Umbraco.Web.UI.Client/src/assets/lang/da-dk.ts index 29ba011438..6546006c07 100644 --- a/src/Umbraco.Web.UI.Client/src/assets/lang/da-dk.ts +++ b/src/Umbraco.Web.UI.Client/src/assets/lang/da-dk.ts @@ -1857,6 +1857,7 @@ export default { inviteAnotherUser: 'Invitér anden bruger', inviteUserHelp: 'Invitér nye brugere til at give dem adgang til Umbraco. En invitation vil blive sendt\n via e-mail til brugeren med oplysninger om, hvordan man logger ind i Umbraco.\n ', + kind: 'Slags', language: 'Sprog', languageHelp: 'Indstil det sprog, du vil se i menuer og dialoger', lastLockoutDate: 'Senest låst ude', diff --git a/src/Umbraco.Web.UI.Client/src/assets/lang/en-us.ts b/src/Umbraco.Web.UI.Client/src/assets/lang/en-us.ts index a212371ec1..4905ce13d9 100644 --- a/src/Umbraco.Web.UI.Client/src/assets/lang/en-us.ts +++ b/src/Umbraco.Web.UI.Client/src/assets/lang/en-us.ts @@ -1849,6 +1849,7 @@ export default { ? 'The email address is used for notifications, password recovery, and as the username for logging in' : 'The email address is used for notifications and password recovery'; }, + kind: 'Kind', newPassword: 'New password', newPasswordFormatLengthTip: 'Minimum %0% character(s) to go!', newPasswordFormatNonAlphaTip: 'There should be at least %0% special character(s) in there.', diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/workspace/components/user-workspace-info/user-workspace-info.element.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/workspace/components/user-workspace-info/user-workspace-info.element.ts index 27c46e106a..da83d0569b 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/workspace/components/user-workspace-info/user-workspace-info.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/workspace/components/user-workspace-info/user-workspace-info.element.ts @@ -42,6 +42,10 @@ export class UmbUserWorkspaceInfoElement extends UmbLitElement { } this._userInfo = [ + { + labelKey: 'user_kind', + value: user.kind, + }, { labelKey: 'user_lastLogin', value: user.lastLoginDate From 637aef966d65ab6c49fda254dac41a3d4f2360d3 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 3 Sep 2024 11:05:53 +0200 Subject: [PATCH 030/107] use stack component --- .../user-workspace-access.element.ts | 6 +++--- .../user-workspace-assign-access.element.ts | 11 +++++++++-- .../user-workspace-profile-settings.element.ts | 4 ++++ .../user/workspace/user-workspace-editor.element.ts | 8 +++++--- 4 files changed, 21 insertions(+), 8 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/workspace/components/user-workspace-access/user-workspace-access.element.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/workspace/components/user-workspace-access/user-workspace-access.element.ts index 6be3f5d9b4..7177e91909 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/workspace/components/user-workspace-access/user-workspace-access.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/workspace/components/user-workspace-access/user-workspace-access.element.ts @@ -28,7 +28,7 @@ export class UmbUserWorkspaceAccessElement extends UmbLitElement { } override render() { - return html` + return html`
Based on the assigned groups and start nodes, the user has access to the following nodes - - + + + + + `; } From 3a4770dad5c7b306f0c376271e547c91822f7520 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 3 Sep 2024 11:06:52 +0200 Subject: [PATCH 031/107] Update collection-view-bundle.element.ts --- .../core/collection/components/collection-view-bundle.element.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/collection/components/collection-view-bundle.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/collection/components/collection-view-bundle.element.ts index 9936840c15..651f524f46 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/collection/components/collection-view-bundle.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/collection/components/collection-view-bundle.element.ts @@ -159,6 +159,7 @@ export class UmbCollectionViewBundleElement extends UmbLitElement { :host { --uui-button-content-align: left; --uui-menu-item-flat-structure: 1; + display: contents; } .filter-dropdown { From 7ecb8d26e8fd69838ab95ed1cc6713ff0dc439bc Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 3 Sep 2024 11:08:50 +0200 Subject: [PATCH 032/107] Update create-user-client-credential-modal.element.ts --- .../modal/create-user-client-credential-modal.element.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/client-credential/create/modal/create-user-client-credential-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/client-credential/create/modal/create-user-client-credential-modal.element.ts index 6a8c9ab5f6..6907dd828b 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/client-credential/create/modal/create-user-client-credential-modal.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/client-credential/create/modal/create-user-client-credential-modal.element.ts @@ -52,9 +52,7 @@ export class UmbCreateUserModalElement extends UmbModalBaseElement< } override render() { - return html` -

Lorem

- + return html` ${this.#renderForm()} Date: Tue, 3 Sep 2024 12:57:41 +0200 Subject: [PATCH 033/107] add description --- .../create/modal/create-user-client-credential-modal.element.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/client-credential/create/modal/create-user-client-credential-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/client-credential/create/modal/create-user-client-credential-modal.element.ts index 6907dd828b..dc48873e55 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/client-credential/create/modal/create-user-client-credential-modal.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/client-credential/create/modal/create-user-client-credential-modal.element.ts @@ -74,7 +74,9 @@ export class UmbCreateUserModalElement extends UmbModalBaseElement<
${this.#uniquePrefix}
+ +
The secret cannot be retrieved again.
Secret
From d5817d5c75539b2d4e95dd94f129995a85241351 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 3 Sep 2024 12:58:08 +0200 Subject: [PATCH 034/107] clean up ui --- .../user-workspace-client-credentials.element.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/workspace/components/user-workspace-client-credentials/user-workspace-client-credentials.element.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/workspace/components/user-workspace-client-credentials/user-workspace-client-credentials.element.ts index 7d3fa116f9..512d97f2d6 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/workspace/components/user-workspace-client-credentials/user-workspace-client-credentials.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/workspace/components/user-workspace-client-credentials/user-workspace-client-credentials.element.ts @@ -113,7 +113,7 @@ export class UmbUserWorkspaceClientCredentialsElement extends UmbLitElement { return html`
Client Credentials
- ${this._clientCredentials.map((client) => html` ${this.#renderItem(client)} `)} + ${this._clientCredentials.map((client) => html` ${this.#renderItem(client)} `)} - + this.#onDelete(event, client)} label="Delete ${client.unique}" compact - > `; From f7ff61220f59b456b5b8c3d4ed2e8d8e85048db2 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 3 Sep 2024 14:30:12 +0200 Subject: [PATCH 035/107] link to workspace --- .../name/user-table-name-column-layout.element.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/collection/views/table/column-layouts/name/user-table-name-column-layout.element.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/collection/views/table/column-layouts/name/user-table-name-column-layout.element.ts index b97ef2232e..849f47e095 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/collection/views/table/column-layouts/name/user-table-name-column-layout.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/collection/views/table/column-layouts/name/user-table-name-column-layout.element.ts @@ -40,7 +40,7 @@ export class UmbUserTableNameColumnLayoutElement extends LitElement { .name=${this.value.name || 'Unknown'} img-src=${ifDefined(this.value.avatarUrls.length > 0 ? avatarUrls[0].url : undefined)} img-srcset=${ifDefined(this.value.avatarUrls.length > 0 ? avatarSrcset : undefined)}> - ${this.value.name}
`; From e9279dd40452261a1b1e125c0c906656b340bb11 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 3 Sep 2024 14:35:31 +0200 Subject: [PATCH 036/107] link to workspace --- .../views/grid/user-grid-collection-view.element.ts | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/collection/views/grid/user-grid-collection-view.element.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/collection/views/grid/user-grid-collection-view.element.ts index 7de4d20ea5..5f97e6f361 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/collection/views/grid/user-grid-collection-view.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/collection/views/grid/user-grid-collection-view.element.ts @@ -50,12 +50,6 @@ export class UmbUserGridCollectionViewElement extends UmbLitElement { this._loading = false; } - //TODO How should we handle url stuff? - private _handleOpenCard(unique: string) { - //TODO this will not be needed when cards works as links with href - history.pushState(null, '', 'section/user-management/view/users/user/edit/' + unique); //TODO Change to a tag with href and make dynamic - } - #onSelect(user: UmbUserDetailModel) { this.#collectionContext?.selection.select(user.unique ?? ''); } @@ -102,10 +96,10 @@ export class UmbUserGridCollectionViewElement extends UmbLitElement { return html` 0} ?selected=${this.#collectionContext?.selection.isSelected(user.unique)} - @open=${() => this._handleOpenCard(user.unique)} @selected=${() => this.#onSelect(user)} @deselected=${() => this.#onDeselect(user)}> ${this.#renderUserTag(user)} ${this.#renderUserGroupNames(user)} ${this.#renderUserLoginDate(user)} From e5b458886af1ea84412e35dbd2c78426dc7f21c7 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 3 Sep 2024 15:02:03 +0200 Subject: [PATCH 037/107] add user section paths --- .../src/packages/user/user-section/paths.ts | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 src/Umbraco.Web.UI.Client/src/packages/user/user-section/paths.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user-section/paths.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user-section/paths.ts new file mode 100644 index 0000000000..f61a643ac5 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user-section/paths.ts @@ -0,0 +1,7 @@ +import { UMB_SECTION_PATH_PATTERN } from '@umbraco-cms/backoffice/section'; + +export const UMB_USER_SECTION_PATHNAME = 'user-management'; + +export const UMB_USER_SECTION_PATH = UMB_SECTION_PATH_PATTERN.generateAbsolute({ + sectionName: UMB_USER_SECTION_PATHNAME, +}); From 19b87e2ab14f29550099c03ab82c570e3a5727d0 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 3 Sep 2024 15:02:11 +0200 Subject: [PATCH 038/107] add user workspace paths --- src/Umbraco.Web.UI.Client/src/packages/user/user/paths.ts | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 src/Umbraco.Web.UI.Client/src/packages/user/user/paths.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/paths.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/paths.ts new file mode 100644 index 0000000000..e9040e7270 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/paths.ts @@ -0,0 +1,8 @@ +import { UMB_USER_SECTION_PATHNAME } from '../user-section/paths.js'; +import { UMB_USER_ENTITY_TYPE } from './entity.js'; +import { UMB_WORKSPACE_PATH_PATTERN } from '@umbraco-cms/backoffice/workspace'; + +export const UMB_USER_WORKSPACE_PATH = UMB_WORKSPACE_PATH_PATTERN.generateAbsolute({ + sectionName: UMB_USER_SECTION_PATHNAME, + entityType: UMB_USER_ENTITY_TYPE, +}); From 69671848102a8ebbdc71bffdaaea7235ad12b090 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 3 Sep 2024 15:02:29 +0200 Subject: [PATCH 039/107] use paths consts --- .../views/grid/user-grid-collection-view.element.ts | 5 ++++- .../name/user-table-name-column-layout.element.ts | 7 ++++--- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/collection/views/grid/user-grid-collection-view.element.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/collection/views/grid/user-grid-collection-view.element.ts index 5f97e6f361..4a5aba82e4 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/collection/views/grid/user-grid-collection-view.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/collection/views/grid/user-grid-collection-view.element.ts @@ -2,6 +2,7 @@ import { getDisplayStateFromUserStatus } from '../../../utils.js'; import type { UmbUserCollectionContext } from '../../user-collection.context.js'; import type { UmbUserDetailModel } from '../../../types.js'; import { UMB_USER_COLLECTION_CONTEXT } from '../../user-collection.context-token.js'; +import { UMB_USER_WORKSPACE_PATH } from '../../../paths.js'; import { css, html, nothing, customElement, state, repeat, ifDefined } from '@umbraco-cms/backoffice/external/lit'; import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; @@ -93,10 +94,12 @@ export class UmbUserGridCollectionViewElement extends UmbLitElement { avatarSrcset += `${url.url} ${url.scale},`; }); + const href = UMB_USER_WORKSPACE_PATH + '/edit/' + user.unique; + return html` 0} ?selected=${this.#collectionContext?.selection.isSelected(user.unique)} diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/collection/views/table/column-layouts/name/user-table-name-column-layout.element.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/collection/views/table/column-layouts/name/user-table-name-column-layout.element.ts index 849f47e095..0e10cad16b 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/collection/views/table/column-layouts/name/user-table-name-column-layout.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/collection/views/table/column-layouts/name/user-table-name-column-layout.element.ts @@ -1,3 +1,4 @@ +import { UMB_USER_WORKSPACE_PATH } from '../../../../../paths.js'; import { html, LitElement, customElement, property, ifDefined } from '@umbraco-cms/backoffice/external/lit'; import type { UmbTableColumn, UmbTableItem } from '@umbraco-cms/backoffice/components'; @@ -34,15 +35,15 @@ export class UmbUserTableNameColumnLayoutElement extends LitElement { avatarSrcset += `${url.url} ${url.scale},`; }); + const href = UMB_USER_WORKSPACE_PATH + '/edit/' + this.value.unique; + return html`
0 ? avatarUrls[0].url : undefined)} img-srcset=${ifDefined(this.value.avatarUrls.length > 0 ? avatarSrcset : undefined)}> - ${this.value.name} + ${this.value.name}
`; } } From ce3fd605d509d1cd88d345acbb05a084ac96b379 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 3 Sep 2024 15:07:44 +0200 Subject: [PATCH 040/107] fix mock data --- .../src/mocks/data/user/user.data.ts | 143 +++++++++--------- .../src/mocks/data/user/user.db.ts | 37 ++--- 2 files changed, 94 insertions(+), 86 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/mocks/data/user/user.data.ts b/src/Umbraco.Web.UI.Client/src/mocks/data/user/user.data.ts index a1657a2531..2043e9d216 100644 --- a/src/Umbraco.Web.UI.Client/src/mocks/data/user/user.data.ts +++ b/src/Umbraco.Web.UI.Client/src/mocks/data/user/user.data.ts @@ -3,115 +3,120 @@ import type { UserResponseModel, UserTwoFactorProviderModel, } from '@umbraco-cms/backoffice/external/backend-api'; -import { UserStateModel } from '@umbraco-cms/backoffice/external/backend-api'; +import { UserKindModel, UserStateModel } from '@umbraco-cms/backoffice/external/backend-api'; export type UmbMockUserModel = UserResponseModel & UserItemResponseModel; export const data: Array = [ { - id: 'bca6c733-a63d-4353-a271-9a8b6bcca8bd', - documentStartNodeIds: [], - hasDocumentRootAccess: true, - mediaStartNodeIds: [], - hasMediaRootAccess: true, - name: 'Umbraco User', - email: 'noreply@umbraco.com', - languageIsoCode: 'en-us', - state: UserStateModel.ACTIVE, - lastLoginDate: '9/10/2022', - lastLockoutDate: '11/23/2021', - lastPasswordChangeDate: '1/10/2022', - updateDate: '2/10/2022', + avatarUrls: [], createDate: '3/13/2022', + documentStartNodeIds: [], + email: 'noreply@umbraco.com', failedLoginAttempts: 946, + hasDocumentRootAccess: true, + hasMediaRootAccess: true, + id: 'bca6c733-a63d-4353-a271-9a8b6bcca8bd', + isAdmin: true, + kind: UserKindModel.DEFAULT, + languageIsoCode: 'en-us', + lastLockoutDate: '11/23/2021', + lastLoginDate: '9/10/2022', + lastPasswordChangeDate: '1/10/2022', + mediaStartNodeIds: [], + name: 'Umbraco User', + state: UserStateModel.ACTIVE, + updateDate: '2/10/2022', userGroupIds: [{ id: 'user-group-administrators-id' }, { id: 'user-group-editors-id' }], userName: '', - avatarUrls: [], - isAdmin: true, }, { - id: '82e11d3d-b91d-43c9-9071-34d28e62e81d', - documentStartNodeIds: [{ id: 'simple-document-id' }], - hasDocumentRootAccess: true, - mediaStartNodeIds: [{ id: 'f2f81a40-c989-4b6b-84e2-057cecd3adc1' }], - hasMediaRootAccess: true, - name: 'Amelie Walker', - email: 'awalker1@domain.com', - languageIsoCode: 'da-dk', - state: UserStateModel.INACTIVE, - lastLoginDate: '2023-10-12T18:30:32.879Z', - lastLockoutDate: null, - lastPasswordChangeDate: '2023-10-12T18:30:32.879Z', - updateDate: '2023-10-12T18:30:32.879Z', + avatarUrls: [], createDate: '2023-10-12T18:30:32.879Z', + documentStartNodeIds: [{ id: 'simple-document-id' }], + email: 'awalker1@domain.com', failedLoginAttempts: 0, + hasDocumentRootAccess: true, + hasMediaRootAccess: true, + id: '82e11d3d-b91d-43c9-9071-34d28e62e81d', + isAdmin: true, + kind: UserKindModel.DEFAULT, + languageIsoCode: 'da-dk', + lastLockoutDate: null, + lastLoginDate: '2023-10-12T18:30:32.879Z', + lastPasswordChangeDate: '2023-10-12T18:30:32.879Z', + mediaStartNodeIds: [{ id: 'f2f81a40-c989-4b6b-84e2-057cecd3adc1' }], + name: 'Amelie Walker', + state: UserStateModel.INACTIVE, + updateDate: '2023-10-12T18:30:32.879Z', userGroupIds: [{ id: 'user-group-administrators-id' }], userName: '', - avatarUrls: [], - isAdmin: true, }, { - id: 'aa1d83a9-bc7f-47d2-b288-58d8a31f5017', + avatarUrls: [], + createDate: '2023-10-12T18:30:32.879Z', documentStartNodeIds: [], - mediaStartNodeIds: [], - hasDocumentRootAccess: true, - hasMediaRootAccess: true, - name: 'Oliver Kim', email: 'okim1@domain.com', + failedLoginAttempts: 0, + hasDocumentRootAccess: true, + hasMediaRootAccess: true, + id: 'aa1d83a9-bc7f-47d2-b288-58d8a31f5017', + isAdmin: false, + kind: UserKindModel.DEFAULT, languageIsoCode: 'da-dk', - state: UserStateModel.ACTIVE, - lastLoginDate: '2023-10-12T18:30:32.879Z', lastLockoutDate: null, + lastLoginDate: '2023-10-12T18:30:32.879Z', lastPasswordChangeDate: '2023-10-12T18:30:32.879Z', + mediaStartNodeIds: [], + name: 'Oliver Kim', + state: UserStateModel.ACTIVE, updateDate: '2023-10-12T18:30:32.879Z', - createDate: '2023-10-12T18:30:32.879Z', - failedLoginAttempts: 0, userGroupIds: [{ id: 'user-group-editors-id' }], userName: '', - avatarUrls: [], - isAdmin: false, }, { - id: 'ff2f4a50-d3d4-4bc4-869d-c7948c160e54', + avatarUrls: [], + createDate: '2023-10-12T18:30:32.879Z', documentStartNodeIds: [], - mediaStartNodeIds: [], - hasDocumentRootAccess: true, - hasMediaRootAccess: true, - name: 'Eliana Nieves', email: 'enieves1@domain.com', - languageIsoCode: 'en-us', - state: UserStateModel.INVITED, - lastLoginDate: '2023-10-12T18:30:32.879Z', - lastLockoutDate: null, - lastPasswordChangeDate: null, - updateDate: '2023-10-12T18:30:32.879Z', - createDate: '2023-10-12T18:30:32.879Z', failedLoginAttempts: 0, - userGroupIds: [{ id: 'user-group-editors-id' }], - userName: '', - avatarUrls: [], - isAdmin: false, - }, - { - id: 'c290c6d9-9f12-4838-8567-621b52a178de', - documentStartNodeIds: [], - mediaStartNodeIds: [], hasDocumentRootAccess: true, hasMediaRootAccess: true, - name: 'Jasmine Patel', - email: 'jpatel1@domain.com', + id: 'ff2f4a50-d3d4-4bc4-869d-c7948c160e54', + isAdmin: false, + kind: UserKindModel.DEFAULT, languageIsoCode: 'en-us', - state: UserStateModel.LOCKED_OUT, + lastLockoutDate: null, lastLoginDate: '2023-10-12T18:30:32.879Z', - lastLockoutDate: '2023-10-12T18:30:32.879Z', lastPasswordChangeDate: null, + mediaStartNodeIds: [], + name: 'Eliana Nieves', + state: UserStateModel.INVITED, updateDate: '2023-10-12T18:30:32.879Z', + userGroupIds: [{ id: 'user-group-editors-id' }], + userName: '', + }, + { + avatarUrls: [], createDate: '2023-10-12T18:30:32.879Z', + documentStartNodeIds: [], + email: 'jpatel1@domain.com', failedLoginAttempts: 25, + hasDocumentRootAccess: true, + hasMediaRootAccess: true, + id: 'c290c6d9-9f12-4838-8567-621b52a178de', + isAdmin: false, + kind: UserKindModel.DEFAULT, + languageIsoCode: 'en-us', + lastLockoutDate: '2023-10-12T18:30:32.879Z', + lastLoginDate: '2023-10-12T18:30:32.879Z', + lastPasswordChangeDate: null, + mediaStartNodeIds: [], + name: 'Jasmine Patel', + state: UserStateModel.LOCKED_OUT, + updateDate: '2023-10-12T18:30:32.879Z', userGroupIds: [{ id: 'user-group-editors-id' }, { id: 'user-group-sensitive-data-id' }], userName: '', - avatarUrls: [], - isAdmin: false, }, ]; diff --git a/src/Umbraco.Web.UI.Client/src/mocks/data/user/user.db.ts b/src/Umbraco.Web.UI.Client/src/mocks/data/user/user.db.ts index 414f584edf..2416aeb899 100644 --- a/src/Umbraco.Web.UI.Client/src/mocks/data/user/user.db.ts +++ b/src/Umbraco.Web.UI.Client/src/mocks/data/user/user.db.ts @@ -195,9 +195,10 @@ class UmbUserMockDB extends UmbEntityMockDbBase { const itemMapper = (item: UmbMockUserModel): UserItemResponseModel => { return { - id: item.id, - name: item.name, avatarUrls: item.avatarUrls, + id: item.id, + kind: item.kind, + name: item.name, }; }; @@ -222,30 +223,32 @@ const createMockMapper = (item: CreateUserRequestModel): UmbMockUserModel => { lastLockoutDate: null, lastPasswordChangeDate: null, isAdmin: item.userGroupIds.map((reference) => reference.id).includes(umbUserGroupMockDb.getAll()[0].id), + kind: item.kind, }; }; const detailResponseMapper = (item: UmbMockUserModel): UserResponseModel => { return { - email: item.email, - userName: item.userName, - name: item.name, - userGroupIds: item.userGroupIds, - id: item.id, - languageIsoCode: item.languageIsoCode, + avatarUrls: item.avatarUrls, + createDate: item.createDate, documentStartNodeIds: item.documentStartNodeIds, - mediaStartNodeIds: item.mediaStartNodeIds, + email: item.email, + failedLoginAttempts: item.failedLoginAttempts, hasDocumentRootAccess: item.hasDocumentRootAccess, hasMediaRootAccess: item.hasMediaRootAccess, - avatarUrls: item.avatarUrls, - state: item.state, - failedLoginAttempts: item.failedLoginAttempts, - createDate: item.createDate, - updateDate: item.updateDate, - lastLoginDate: item.lastLoginDate, - lastLockoutDate: item.lastLockoutDate, - lastPasswordChangeDate: item.lastPasswordChangeDate, + id: item.id, isAdmin: item.isAdmin, + kind: item.kind, + languageIsoCode: item.languageIsoCode, + lastLockoutDate: item.lastLockoutDate, + lastLoginDate: item.lastLoginDate, + lastPasswordChangeDate: item.lastPasswordChangeDate, + mediaStartNodeIds: item.mediaStartNodeIds, + name: item.name, + state: item.state, + updateDate: item.updateDate, + userGroupIds: item.userGroupIds, + userName: item.userName, }; }; From 47c49bcdcb8b1cde9d677eeb5a16fa8db8de8546 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 3 Sep 2024 15:10:28 +0200 Subject: [PATCH 041/107] update mock data --- .../src/mocks/data/member/member.data.ts | 9 ++++++++- .../src/mocks/data/member/member.db.ts | 2 ++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/mocks/data/member/member.data.ts b/src/Umbraco.Web.UI.Client/src/mocks/data/member/member.data.ts index d82092d4a2..ee2d5c0e1d 100644 --- a/src/Umbraco.Web.UI.Client/src/mocks/data/member/member.data.ts +++ b/src/Umbraco.Web.UI.Client/src/mocks/data/member/member.data.ts @@ -1,4 +1,8 @@ -import type { MemberResponseModel, MemberItemResponseModel } from '@umbraco-cms/backoffice/external/backend-api'; +import { + type MemberResponseModel, + type MemberItemResponseModel, + MemberKindModel, +} from '@umbraco-cms/backoffice/external/backend-api'; export type UmbMockMemberModel = MemberResponseModel & MemberItemResponseModel; @@ -26,6 +30,7 @@ export const data: Array = [ updateDate: '2023-02-06T15:32:24.957009', }, ], + kind: MemberKindModel.DEFAULT, }, { email: 'member2@member.com', @@ -50,6 +55,7 @@ export const data: Array = [ updateDate: '2023-02-06T15:32:24.957009', }, ], + kind: MemberKindModel.DEFAULT, }, { email: 'member3@member.com', @@ -74,5 +80,6 @@ export const data: Array = [ updateDate: '2023-02-06T15:31:51.354764', }, ], + kind: MemberKindModel.DEFAULT, }, ]; diff --git a/src/Umbraco.Web.UI.Client/src/mocks/data/member/member.db.ts b/src/Umbraco.Web.UI.Client/src/mocks/data/member/member.db.ts index 59b36d0ead..c97ec93af9 100644 --- a/src/Umbraco.Web.UI.Client/src/mocks/data/member/member.db.ts +++ b/src/Umbraco.Web.UI.Client/src/mocks/data/member/member.db.ts @@ -66,6 +66,7 @@ const detailResponseMapper = (item: UmbMockMemberModel): MemberResponseModel => isApproved: item.isApproved, isLockedOut: item.isLockedOut, isTwoFactorEnabled: item.isTwoFactorEnabled, + kind: item.kind, lastLockoutDate: item.lastLockoutDate, lastLoginDate: item.lastLoginDate, lastPasswordChangeDate: item.lastPasswordChangeDate, @@ -79,6 +80,7 @@ const detailResponseMapper = (item: UmbMockMemberModel): MemberResponseModel => const itemResponseMapper = (item: UmbMockMemberModel): MemberItemResponseModel => { return { id: item.id, + kind: item.kind, memberType: item.memberType, variants: item.variants, }; From 7831038c70a4942193ef7373b324cbe89aa697ab Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 3 Sep 2024 16:14:58 +0200 Subject: [PATCH 042/107] filter info on api users --- .../user-workspace-info/user-workspace-info.element.ts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/workspace/components/user-workspace-info/user-workspace-info.element.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/workspace/components/user-workspace-info/user-workspace-info.element.ts index da83d0569b..3294e78ac2 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/workspace/components/user-workspace-info/user-workspace-info.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/workspace/components/user-workspace-info/user-workspace-info.element.ts @@ -2,6 +2,7 @@ import type { UmbUserDisplayStatus } from '../../../utils.js'; import { TimeFormatOptions, getDisplayStateFromUserStatus } from '../../../utils.js'; import { UMB_USER_WORKSPACE_CONTEXT } from '../../user-workspace.context-token.js'; import type { UmbUserDetailModel } from '../../../types.js'; +import { UmbUserKind } from '../../../utils/index.js'; import { html, customElement, state, css, repeat, ifDefined, nothing } from '@umbraco-cms/backoffice/external/lit'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; @@ -69,6 +70,11 @@ export class UmbUserWorkspaceInfoElement extends UmbLitElement { { labelKey: 'user_updateDate', value: this.localize.date(user.updateDate!, TimeFormatOptions) }, { labelKey: 'general_id', value: user.unique }, ]; + + if (user.kind === UmbUserKind.API) { + const include = ['user_kind', 'user_createDate', 'user_updateDate', 'general_id']; + this._userInfo = this._userInfo.filter((item) => include.includes(item.labelKey)); + } }; override render() { From 02c15e941eeecc5aedae28886b9094bcaa993af6 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 3 Sep 2024 16:25:45 +0200 Subject: [PATCH 043/107] hide UI language when editing an api user --- .../user-workspace-profile-settings.element.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/workspace/components/user-workspace-profile-settings/user-workspace-profile-settings.element.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/workspace/components/user-workspace-profile-settings/user-workspace-profile-settings.element.ts index 6a672827cc..fd4e67c615 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/workspace/components/user-workspace-profile-settings/user-workspace-profile-settings.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/workspace/components/user-workspace-profile-settings/user-workspace-profile-settings.element.ts @@ -5,6 +5,7 @@ import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; import type { UmbChangeEvent } from '@umbraco-cms/backoffice/event'; import type { UmbUiCultureInputElement } from '@umbraco-cms/backoffice/localization'; +import { UmbUserKind } from '../../../utils/index.js'; @customElement('umb-user-workspace-profile-settings') export class UmbUserWorkspaceProfileSettingsElement extends UmbLitElement { @@ -84,9 +85,7 @@ export class UmbUserWorkspaceProfileSettingsElement extends UmbLitElement { } #renderUsernameProperty() { - if (this._usernameIsEmail) { - return nothing; - } + if (this._usernameIsEmail) return nothing; return html` Date: Tue, 3 Sep 2024 21:17:17 +0200 Subject: [PATCH 044/107] add dropdown to user collection create --- .../create-user-collection-action.element.ts | 80 +++++++++++++++++++ .../action/create-user.collection-action.ts | 32 -------- .../user/user/collection/action/manifests.ts | 7 +- 3 files changed, 81 insertions(+), 38 deletions(-) create mode 100644 src/Umbraco.Web.UI.Client/src/packages/user/user/collection/action/create-user-collection-action.element.ts delete mode 100644 src/Umbraco.Web.UI.Client/src/packages/user/user/collection/action/create-user.collection-action.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/collection/action/create-user-collection-action.element.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/collection/action/create-user-collection-action.element.ts new file mode 100644 index 0000000000..183a0bf573 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/collection/action/create-user-collection-action.element.ts @@ -0,0 +1,80 @@ +import { UMB_CREATE_USER_MODAL } from '../../modals/create/create-user-modal.token.js'; +import { html, customElement, state } from '@umbraco-cms/backoffice/external/lit'; +import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; +import { UMB_MODAL_MANAGER_CONTEXT } from '@umbraco-cms/backoffice/modal'; +import { UMB_ENTITY_CONTEXT } from '@umbraco-cms/backoffice/entity'; +import { UMB_ACTION_EVENT_CONTEXT } from '@umbraco-cms/backoffice/action'; +import { UmbRequestReloadChildrenOfEntityEvent } from '@umbraco-cms/backoffice/entity-action'; + +const elementName = 'umb-create-user-collection-action-button'; +@customElement(elementName) +export class UmbCollectionActionButtonElement extends UmbLitElement { + @state() + private _popoverOpen = false; + + async #onClick(event: Event) { + event.stopPropagation(); + const modalManager = await this.getContext(UMB_MODAL_MANAGER_CONTEXT); + const entityContext = await this.getContext(UMB_ENTITY_CONTEXT); + + const unique = entityContext.getUnique(); + const entityType = entityContext.getEntityType(); + + if (unique === undefined) throw new Error('Missing unique'); + if (!entityType) throw new Error('Missing entityType'); + + const modalContext = modalManager.open(this, UMB_CREATE_USER_MODAL); + modalContext?.onSubmit().catch(async () => { + // modal is closed after creation instead of navigating to the new user. + // We therefore need to reload the children of the entity + const eventContext = await this.getContext(UMB_ACTION_EVENT_CONTEXT); + const event = new UmbRequestReloadChildrenOfEntityEvent({ + entityType, + unique, + }); + + eventContext.dispatchEvent(event); + }); + } + + #onPopoverToggle(event: ToggleEvent) { + // TODO: This ignorer is just neede for JSON SCHEMA TO WORK, As its not updated with latest TS jet. + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore + this._popoverOpen = event.newState === 'open'; + } + + override render() { + const label = this.localize.term('general_create'); + + return html` + + ${label} + + + + + + + + + + + + + + + `; + } +} + +export { UmbCollectionActionButtonElement as element }; + +declare global { + interface HTMLElementTagNameMap { + [elementName]: UmbCollectionActionButtonElement; + } +} diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/collection/action/create-user.collection-action.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/collection/action/create-user.collection-action.ts deleted file mode 100644 index 73ac577b54..0000000000 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/collection/action/create-user.collection-action.ts +++ /dev/null @@ -1,32 +0,0 @@ -import { UMB_CREATE_USER_MODAL } from '../../modals/create/create-user-modal.token.js'; -import { UMB_ACTION_EVENT_CONTEXT } from '@umbraco-cms/backoffice/action'; -import { UmbControllerBase } from '@umbraco-cms/backoffice/class-api'; -import { UMB_ENTITY_CONTEXT } from '@umbraco-cms/backoffice/entity'; -import { UmbRequestReloadChildrenOfEntityEvent } from '@umbraco-cms/backoffice/entity-action'; -import { UMB_MODAL_MANAGER_CONTEXT } from '@umbraco-cms/backoffice/modal'; - -export class UmbCreateUserCollectionAction extends UmbControllerBase { - async execute() { - const modalManager = await this.getContext(UMB_MODAL_MANAGER_CONTEXT); - const entityContext = await this.getContext(UMB_ENTITY_CONTEXT); - - const unique = entityContext.getUnique(); - const entityType = entityContext.getEntityType(); - - if (unique === undefined) throw new Error('Missing unique'); - if (!entityType) throw new Error('Missing entityType'); - - const modalContext = modalManager.open(this, UMB_CREATE_USER_MODAL); - modalContext?.onSubmit().catch(async () => { - // modal is closed after creation instead of navigating to the new user. - // We therefore need to reload the children of the entity - const eventContext = await this.getContext(UMB_ACTION_EVENT_CONTEXT); - const event = new UmbRequestReloadChildrenOfEntityEvent({ - entityType, - unique, - }); - - eventContext.dispatchEvent(event); - }); - } -} diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/collection/action/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/collection/action/manifests.ts index 7d2451635c..204d4cd117 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/collection/action/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/collection/action/manifests.ts @@ -1,17 +1,12 @@ -import { UmbCreateUserCollectionAction } from './create-user.collection-action.js'; import { UMB_COLLECTION_ALIAS_CONDITION } from '@umbraco-cms/backoffice/collection'; import type { ManifestTypes } from '@umbraco-cms/backoffice/extension-registry'; export const createManifest: ManifestTypes = { type: 'collectionAction', - kind: 'button', name: 'Create User Collection Action', alias: 'Umb.CollectionAction.User.Create', - api: UmbCreateUserCollectionAction, + element: () => import('./create-user-collection-action.element.js'), weight: 200, - meta: { - label: '#general_create', - }, conditions: [ { alias: UMB_COLLECTION_ALIAS_CONDITION, From 0891e33b8027aac343adbcc65fe07bf38342349f Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Wed, 4 Sep 2024 10:25:40 +0200 Subject: [PATCH 045/107] add user avatar component --- .../grid/user-grid-collection-view.element.ts | 29 +------ .../packages/user/user/components/index.ts | 3 +- .../user-avatar/user-avatar.element.ts | 80 +++++++++++++++++++ 3 files changed, 83 insertions(+), 29 deletions(-) create mode 100644 src/Umbraco.Web.UI.Client/src/packages/user/user/components/user-avatar/user-avatar.element.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/collection/views/grid/user-grid-collection-view.element.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/collection/views/grid/user-grid-collection-view.element.ts index 4a5aba82e4..f80fa2d9b4 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/collection/views/grid/user-grid-collection-view.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/collection/views/grid/user-grid-collection-view.element.ts @@ -73,27 +73,6 @@ export class UmbUserGridCollectionViewElement extends UmbLitElement { } #renderUserCard(user: UmbUserDetailModel) { - const avatarUrls = [ - { - scale: '1x', - url: user.avatarUrls?.[1], - }, - { - scale: '2x', - url: user.avatarUrls?.[2], - }, - { - scale: '3x', - url: user.avatarUrls?.[3], - }, - ]; - - let avatarSrcset = ''; - - avatarUrls.forEach((url) => { - avatarSrcset += `${url.url} ${url.scale},`; - }); - const href = UMB_USER_WORKSPACE_PATH + '/edit/' + user.unique; return html` @@ -106,13 +85,7 @@ export class UmbUserGridCollectionViewElement extends UmbLitElement { @selected=${() => this.#onSelect(user)} @deselected=${() => this.#onDeselect(user)}> ${this.#renderUserTag(user)} ${this.#renderUserGroupNames(user)} ${this.#renderUserLoginDate(user)} - - 0 ? avatarUrls[0].url : undefined)} - img-srcset=${ifDefined(user.avatarUrls.length > 0 ? avatarSrcset : undefined)}> +
`; } diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/components/index.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/components/index.ts index 6f97b68e0a..a3e23b4c87 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/components/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/components/index.ts @@ -1,5 +1,6 @@ -import './user-input/user-input.element.js'; +import './user-avatar/user-avatar.element.js'; import './user-document-start-node/user-document-start-node.element.js'; +import './user-input/user-input.element.js'; import './user-media-start-node/user-media-start-node.element.js'; export * from './user-input/index.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/components/user-avatar/user-avatar.element.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/components/user-avatar/user-avatar.element.ts new file mode 100644 index 0000000000..56705be737 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/components/user-avatar/user-avatar.element.ts @@ -0,0 +1,80 @@ +import type { UmbUserItemModel } from '../../repository/index.js'; +import { css, html, customElement, property, nothing, ifDefined, state } from '@umbraco-cms/backoffice/external/lit'; +import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; +import { UmbUserKind } from '../../utils/index.js'; + +const elementName = 'umb-user-avatar'; +@customElement(elementName) +export class UmbUserAvatarElement extends UmbLitElement { + @property({ type: Object }) + public get user(): UmbUserItemModel | undefined { + return this.#user; + } + public set user(value: UmbUserItemModel | undefined) { + this.#user = value; + this.#setUrls(); + } + #user?: UmbUserItemModel | undefined; + + @state() + private _urls: Array<{ scale: string; url: string }> = []; + + @state() + private _srcset = ''; + + #setUrls() { + const urls = this.user?.avatarUrls ?? []; + this._srcset = ''; + + if (urls.length === 0) { + this._urls = []; + return; + } + + this._urls = [ + { + scale: '1x', + url: urls[1], + }, + { + scale: '2x', + url: urls[2], + }, + { + scale: '3x', + url: urls[3], + }, + ]; + + this._urls.forEach((url) => (this._srcset += `${url.url} ${url.scale},`)); + } + + override render() { + if (!this.user) return nothing; + + return html` 0 ? this._urls[0].url : undefined)} + img-srcset=${ifDefined(this._urls.length > 0 ? this._srcset : undefined)} + class="${this.user.kind === UmbUserKind.API ? 'api' : 'default'}">`; + } + + static override styles = [ + css` + uui-avatar { + background-color: transparent; + border: 1.5px solid var(--uui-color-divider-standalone); + } + + uui-avatar.api { + border-radius: var(--uui-border-radius); + } + `, + ]; +} + +declare global { + interface HTMLElementTagNameMap { + [elementName]: UmbUserAvatarElement; + } +} From 1ca7b620e8a18a2015c27b92fd7e2e05289152f6 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Wed, 4 Sep 2024 10:42:42 +0200 Subject: [PATCH 046/107] hide log in data for api users --- .../views/grid/user-grid-collection-view.element.ts | 7 ++++++- .../user/components/user-avatar/user-avatar.element.ts | 2 +- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/collection/views/grid/user-grid-collection-view.element.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/collection/views/grid/user-grid-collection-view.element.ts index f80fa2d9b4..50e9b8ca83 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/collection/views/grid/user-grid-collection-view.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/collection/views/grid/user-grid-collection-view.element.ts @@ -9,6 +9,7 @@ import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; import { UserStateModel } from '@umbraco-cms/backoffice/external/backend-api'; import type { UmbUserGroupDetailModel } from '@umbraco-cms/backoffice/user-group'; import { UmbUserGroupCollectionRepository } from '@umbraco-cms/backoffice/user-group'; +import { UmbUserKind } from '../../../utils/index.js'; @customElement('umb-user-grid-collection-view') export class UmbUserGridCollectionViewElement extends UmbLitElement { @@ -115,12 +116,14 @@ export class UmbUserGridCollectionViewElement extends UmbLitElement { } #renderUserLoginDate(user: UmbUserDetailModel) { + if (user.kind === UmbUserKind.API) return nothing; + if (!user.lastLoginDate) { return html``; } return html``; } @@ -142,6 +145,8 @@ export class UmbUserGridCollectionViewElement extends UmbLitElement { uui-card-user { width: 100%; height: 180px; + justify-content: normal; + padding-top: var(--uui-size-space-5); } .user-login-time { diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/components/user-avatar/user-avatar.element.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/components/user-avatar/user-avatar.element.ts index 56705be737..95834ad9a2 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/components/user-avatar/user-avatar.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/components/user-avatar/user-avatar.element.ts @@ -1,7 +1,7 @@ import type { UmbUserItemModel } from '../../repository/index.js'; +import { UmbUserKind } from '../../utils/index.js'; import { css, html, customElement, property, nothing, ifDefined, state } from '@umbraco-cms/backoffice/external/lit'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; -import { UmbUserKind } from '../../utils/index.js'; const elementName = 'umb-user-avatar'; @customElement(elementName) From 575d49204e4b4797c4e86ffc6161921ffb603a38 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Wed, 4 Sep 2024 11:13:05 +0200 Subject: [PATCH 047/107] split user into individual properties --- .../current-user-header-app.element.ts | 49 ++------------ .../grid/user-grid-collection-view.element.ts | 7 +- .../user-avatar/user-avatar.element.ts | 66 ++++++++++++------- 3 files changed, 52 insertions(+), 70 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/current-user/current-user-header-app.element.ts b/src/Umbraco.Web.UI.Client/src/packages/user/current-user/current-user-header-app.element.ts index 4349a8bec9..362d2d1e37 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/current-user/current-user-header-app.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/current-user/current-user-header-app.element.ts @@ -1,6 +1,6 @@ import { UMB_CURRENT_USER_MODAL } from './modals/current-user/current-user-modal.token.js'; import type { CSSResultGroup } from '@umbraco-cms/backoffice/external/lit'; -import { css, html, customElement, state, ifDefined } from '@umbraco-cms/backoffice/external/lit'; +import { css, html, customElement, state } from '@umbraco-cms/backoffice/external/lit'; import { UMB_MODAL_MANAGER_CONTEXT } from '@umbraco-cms/backoffice/modal'; import { UMB_CURRENT_USER_CONTEXT, type UmbCurrentUserModel } from '@umbraco-cms/backoffice/current-user'; import { UmbHeaderAppButtonElement } from '@umbraco-cms/backoffice/components'; @@ -10,9 +10,6 @@ export class UmbCurrentUserHeaderAppElement extends UmbHeaderAppButtonElement { @state() private _currentUser?: UmbCurrentUserModel; - @state() - private _userAvatarUrls: Array<{ url: string; descriptor: string }> = []; - #currentUserContext?: typeof UMB_CURRENT_USER_CONTEXT.TYPE; constructor() { @@ -31,8 +28,6 @@ export class UmbCurrentUserHeaderAppElement extends UmbHeaderAppButtonElement { this.#currentUserContext.currentUser, (currentUser) => { this._currentUser = currentUser; - if (!currentUser) return; - this.#setUserAvatarUrls(currentUser); }, 'umbCurrentUserObserver', ); @@ -43,41 +38,6 @@ export class UmbCurrentUserHeaderAppElement extends UmbHeaderAppButtonElement { modalManager.open(this, UMB_CURRENT_USER_MODAL); } - #setUserAvatarUrls = async (user: UmbCurrentUserModel | undefined) => { - if (!user || !user.avatarUrls || user.avatarUrls.length === 0) { - this._userAvatarUrls = []; - return; - } - - this._userAvatarUrls = [ - { - descriptor: '1x', - url: user.avatarUrls?.[0], - }, - { - descriptor: '2x', - url: user.avatarUrls?.[1], - }, - { - descriptor: '3x', - url: user.avatarUrls?.[2], - }, - ]; - }; - - #getAvatarSrcset() { - let string = ''; - - this._userAvatarUrls?.forEach((url) => { - string += `${url.url} ${url.descriptor},`; - }); - return string; - } - - #hasAvatar() { - return this._userAvatarUrls.length > 0; - } - override render() { return html` - + .name=${this._currentUser?.name} + .imgUrls=${this._currentUser?.avatarUrls || []}> `; } diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/collection/views/grid/user-grid-collection-view.element.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/collection/views/grid/user-grid-collection-view.element.ts index 50e9b8ca83..9bf21d2dfa 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/collection/views/grid/user-grid-collection-view.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/collection/views/grid/user-grid-collection-view.element.ts @@ -86,7 +86,12 @@ export class UmbUserGridCollectionViewElement extends UmbLitElement { @selected=${() => this.#onSelect(user)} @deselected=${() => this.#onDeselect(user)}> ${this.#renderUserTag(user)} ${this.#renderUserGroupNames(user)} ${this.#renderUserLoginDate(user)} - +
`; } diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/components/user-avatar/user-avatar.element.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/components/user-avatar/user-avatar.element.ts index 95834ad9a2..b1c5354955 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/components/user-avatar/user-avatar.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/components/user-avatar/user-avatar.element.ts @@ -1,62 +1,76 @@ -import type { UmbUserItemModel } from '../../repository/index.js'; +import type { UmbUserKindType } from '../../utils/index.js'; import { UmbUserKind } from '../../utils/index.js'; -import { css, html, customElement, property, nothing, ifDefined, state } from '@umbraco-cms/backoffice/external/lit'; +import { css, html, customElement, property, ifDefined, state, classMap } from '@umbraco-cms/backoffice/external/lit'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; const elementName = 'umb-user-avatar'; @customElement(elementName) export class UmbUserAvatarElement extends UmbLitElement { - @property({ type: Object }) - public get user(): UmbUserItemModel | undefined { - return this.#user; + @property({ type: String }) + name?: string; + + @property({ type: String }) + kind: UmbUserKindType = UmbUserKind.DEFAULT; + + @property({ type: Array, attribute: 'img-urls' }) + public get imgUrls(): Array { + return this.#imgUrls; } - public set user(value: UmbUserItemModel | undefined) { - this.#user = value; + public set imgUrls(value: Array) { + this.#imgUrls = value; this.#setUrls(); } - #user?: UmbUserItemModel | undefined; + #imgUrls: Array = []; @state() - private _urls: Array<{ scale: string; url: string }> = []; + private _imgSrc: Array<{ scale: string; url: string }> = []; @state() - private _srcset = ''; + private _imbSrcSet = ''; + + @state() + private hasImgUrls = false; #setUrls() { - const urls = this.user?.avatarUrls ?? []; - this._srcset = ''; + this._imbSrcSet = ''; - if (urls.length === 0) { - this._urls = []; + if (this.#imgUrls.length === 0) { + this._imgSrc = []; + this.hasImgUrls = false; return; } - this._urls = [ + this._imgSrc = [ { scale: '1x', - url: urls[1], + url: this.#imgUrls[1], }, { scale: '2x', - url: urls[2], + url: this.#imgUrls[2], }, { scale: '3x', - url: urls[3], + url: this.#imgUrls[3], }, ]; - this._urls.forEach((url) => (this._srcset += `${url.url} ${url.scale},`)); + this._imgSrc.forEach((url) => (this._imbSrcSet += `${url.url} ${url.scale},`)); + this.hasImgUrls = true; } override render() { - if (!this.user) return nothing; + const classes = { + default: this.kind === UmbUserKind.API, + api: this.kind === UmbUserKind.API, + 'has-image': this.hasImgUrls, + }; return html` 0 ? this._urls[0].url : undefined)} - img-srcset=${ifDefined(this._urls.length > 0 ? this._srcset : undefined)} - class="${this.user.kind === UmbUserKind.API ? 'api' : 'default'}">`; + .name=${this.name || 'Unknown'} + img-src=${ifDefined(this.hasImgUrls ? this._imgSrc[0].url : undefined)} + img-srcset=${ifDefined(this.hasImgUrls ? this._imbSrcSet : undefined)} + class=${classMap(classes)}>`; } static override styles = [ @@ -66,6 +80,10 @@ export class UmbUserAvatarElement extends UmbLitElement { border: 1.5px solid var(--uui-color-divider-standalone); } + uui-avatar.has-image { + border-color: transparent; + } + uui-avatar.api { border-radius: var(--uui-border-radius); } From bcdc33b00c8cb610a803909a3c5ea045c3b95f79 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Wed, 4 Sep 2024 11:26:25 +0200 Subject: [PATCH 048/107] use umb avatar in table --- .../user-table-name-column-layout.element.ts | 33 ++++--------------- .../user-table-collection-view.element.ts | 1 + .../user-avatar/user-avatar.element.ts | 2 +- 3 files changed, 9 insertions(+), 27 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/collection/views/table/column-layouts/name/user-table-name-column-layout.element.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/collection/views/table/column-layouts/name/user-table-name-column-layout.element.ts index 0e10cad16b..15292958c7 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/collection/views/table/column-layouts/name/user-table-name-column-layout.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/collection/views/table/column-layouts/name/user-table-name-column-layout.element.ts @@ -1,6 +1,7 @@ import { UMB_USER_WORKSPACE_PATH } from '../../../../../paths.js'; -import { html, LitElement, customElement, property, ifDefined } from '@umbraco-cms/backoffice/external/lit'; +import { html, LitElement, customElement, property } from '@umbraco-cms/backoffice/external/lit'; import type { UmbTableColumn, UmbTableItem } from '@umbraco-cms/backoffice/components'; +import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; @customElement('umb-user-table-name-column-layout') export class UmbUserTableNameColumnLayoutElement extends LitElement { @@ -14,38 +15,18 @@ export class UmbUserTableNameColumnLayoutElement extends LitElement { value!: any; override render() { - const avatarUrls = [ - { - scale: '1x', - url: this.value.avatarUrls?.[0], - }, - { - scale: '2x', - url: this.value.avatarUrls?.[1], - }, - { - scale: '3x', - url: this.value.avatarUrls?.[2], - }, - ]; - - let avatarSrcset = ''; - - avatarUrls.forEach((url) => { - avatarSrcset += `${url.url} ${url.scale},`; - }); - const href = UMB_USER_WORKSPACE_PATH + '/edit/' + this.value.unique; return html`
- 0 ? avatarUrls[0].url : undefined)} - img-srcset=${ifDefined(this.value.avatarUrls.length > 0 ? avatarSrcset : undefined)}> + name=${this.value.name} + kind=${this.value.kind} + .imgUrls=${this.value.avatarUrls}> ${this.value.name}
`; } + static override styles = [UmbTextStyles]; } export default UmbUserTableNameColumnLayoutElement; diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/collection/views/table/user-table-collection-view.element.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/collection/views/table/user-table-collection-view.element.ts index 375ca885b3..94e6f08a49 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/collection/views/table/user-table-collection-view.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/collection/views/table/user-table-collection-view.element.ts @@ -122,6 +122,7 @@ export class UmbUserTableCollectionViewElement extends UmbLitElement { unique: user.unique, name: user.name, avatarUrls: user.avatarUrls, + kind: user.kind, }, }, { diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/components/user-avatar/user-avatar.element.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/components/user-avatar/user-avatar.element.ts index b1c5354955..e655ed1161 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/components/user-avatar/user-avatar.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/components/user-avatar/user-avatar.element.ts @@ -12,7 +12,7 @@ export class UmbUserAvatarElement extends UmbLitElement { @property({ type: String }) kind: UmbUserKindType = UmbUserKind.DEFAULT; - @property({ type: Array, attribute: 'img-urls' }) + @property({ type: Array, attribute: false }) public get imgUrls(): Array { return this.#imgUrls; } From 3f970b41d0570b035ffc08b9bf2ac779b7414411 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Wed, 4 Sep 2024 11:59:19 +0200 Subject: [PATCH 049/107] user avatar in document + media history --- .../document-workspace-view-info-history.element.ts | 10 ++++++---- .../info/media-workspace-view-info-history.element.ts | 8 +++++--- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/workspace/views/info/document-workspace-view-info-history.element.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/workspace/views/info/document-workspace-view-info-history.element.ts index a7745267f2..c4ab3b3dd8 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/workspace/views/info/document-workspace-view-info-history.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/workspace/views/info/document-workspace-view-info-history.element.ts @@ -120,13 +120,15 @@ export class UmbDocumentWorkspaceViewInfoHistoryElement extends UmbLitElement { (item) => { const { text, style } = getDocumentHistoryTagStyleAndText(item.logType); const user = this.#userMap.get(item.user.unique); - const userName = user?.name ?? 'Unknown'; - const avatarUrl = user && Array.isArray(user.avatarUrls) ? user.avatarUrls[1] : undefined; return html` - + diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media/workspace/views/info/media-workspace-view-info-history.element.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media/workspace/views/info/media-workspace-view-info-history.element.ts index f8b464808d..46edfce147 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/media/media/workspace/views/info/media-workspace-view-info-history.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/media/media/workspace/views/info/media-workspace-view-info-history.element.ts @@ -102,13 +102,15 @@ export class UmbMediaWorkspaceViewInfoHistoryElement extends UmbLitElement { (item) => { const { text, style } = getMediaHistoryTagStyleAndText(item.logType); const user = this.#userMap.get(item.user.unique); - const userName = user?.name ?? 'Unknown'; - const avatarUrl = user && Array.isArray(user.avatarUrls) ? user.avatarUrls[1] : undefined; return html` - + From 173cb2b63111a52a93f87db6eb3c5e9ed2d32a9c Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Wed, 4 Sep 2024 12:08:22 +0200 Subject: [PATCH 050/107] use umb avatar in user workspace --- ...ent-workspace-view-info-history.element.ts | 2 +- ...dia-workspace-view-info-history.element.ts | 2 +- .../user-avatar/user-avatar.element.ts | 2 +- .../user-workspace-avatar.element.ts | 51 ++++--------------- 4 files changed, 12 insertions(+), 45 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/workspace/views/info/document-workspace-view-info-history.element.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/workspace/views/info/document-workspace-view-info-history.element.ts index c4ab3b3dd8..9388014614 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/workspace/views/info/document-workspace-view-info-history.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/workspace/views/info/document-workspace-view-info-history.element.ts @@ -127,7 +127,7 @@ export class UmbDocumentWorkspaceViewInfoHistoryElement extends UmbLitElement { diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media/workspace/views/info/media-workspace-view-info-history.element.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media/workspace/views/info/media-workspace-view-info-history.element.ts index 46edfce147..f13d1de9ac 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/media/media/workspace/views/info/media-workspace-view-info-history.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/media/media/workspace/views/info/media-workspace-view-info-history.element.ts @@ -109,7 +109,7 @@ export class UmbMediaWorkspaceViewInfoHistoryElement extends UmbLitElement { diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/components/user-avatar/user-avatar.element.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/components/user-avatar/user-avatar.element.ts index e655ed1161..a70b088bee 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/components/user-avatar/user-avatar.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/components/user-avatar/user-avatar.element.ts @@ -10,7 +10,7 @@ export class UmbUserAvatarElement extends UmbLitElement { name?: string; @property({ type: String }) - kind: UmbUserKindType = UmbUserKind.DEFAULT; + kind?: UmbUserKindType = UmbUserKind.DEFAULT; @property({ type: Array, attribute: false }) public get imgUrls(): Array { diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/workspace/components/user-workspace-avatar/user-workspace-avatar.element.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/workspace/components/user-workspace-avatar/user-workspace-avatar.element.ts index 307900260b..b3c7317d12 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/workspace/components/user-workspace-avatar/user-workspace-avatar.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/workspace/components/user-workspace-avatar/user-workspace-avatar.element.ts @@ -1,6 +1,6 @@ import type { UmbUserDetailModel } from '../../../types.js'; import { UMB_USER_WORKSPACE_CONTEXT } from '../../user-workspace.context-token.js'; -import { css, html, customElement, query, nothing, ifDefined, state } from '@umbraco-cms/backoffice/external/lit'; +import { css, html, customElement, query, nothing, state } from '@umbraco-cms/backoffice/external/lit'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; @customElement('umb-user-workspace-avatar') @@ -8,9 +8,6 @@ export class UmbUserAvatarElement extends UmbLitElement { @state() private _user?: UmbUserDetailModel; - @state() - private _userAvatarUrls: Array<{ url: string; scale: string }> = []; - @query('#AvatarFileField') _avatarFileField?: HTMLInputElement; @@ -38,30 +35,11 @@ export class UmbUserAvatarElement extends UmbLitElement { this.#userWorkspaceContext!.data, async (user) => { this._user = user; - this.#setUserAvatarUrls(user); }, 'umbUserObserver', ); }; - #setUserAvatarUrls = async (user: UmbUserDetailModel | undefined) => { - if (!user || !user.avatarUrls || user.avatarUrls.length === 0) { - this._userAvatarUrls = []; - return; - } - - this._userAvatarUrls = [ - { - scale: '1x', - url: user.avatarUrls?.[3], - }, - { - scale: '2x', - url: user.avatarUrls?.[4], - }, - ]; - }; - #uploadAvatar = async () => { try { const selectedFile = await this.#selectAvatar(); @@ -95,35 +73,24 @@ export class UmbUserAvatarElement extends UmbLitElement { #deleteAvatar = async () => { if (!this.#userWorkspaceContext) return; - const { error } = await this.#userWorkspaceContext.deleteAvatar(); - - if (!error) { - this._userAvatarUrls = []; - } + this.#userWorkspaceContext.deleteAvatar(); }; - #getAvatarSrcset() { - let string = ''; - - this._userAvatarUrls?.forEach((url) => { - string += `${url.url} ${url.scale},`; - }); - return string; - } - #hasAvatar() { - return this._userAvatarUrls.length > 0; + if (!this._user) return false; + return this._user.avatarUrls.length > 0; } override render() { + if (!this._user) return nothing; return html` - + .name=${this._user.name} + .kind=${this._user.kind} + .imgUrls=${this._user.avatarUrls ?? []}> ${this.#hasAvatar() From e6ce8731952029f61fdace08566459a66a85eac9 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Wed, 4 Sep 2024 12:29:28 +0200 Subject: [PATCH 051/107] use umb-user-avatar in user picker --- .../user/components/user-input/user-input.element.ts | 8 ++++++-- .../user/modals/user-picker/user-picker-modal.element.ts | 9 ++++++--- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/components/user-input/user-input.element.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/components/user-input/user-input.element.ts index 0ca83e9a7d..118cdc4a36 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/components/user-input/user-input.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/components/user-input/user-input.element.ts @@ -157,7 +157,11 @@ export class UmbUserInputElement extends UUIFormControlMixin(UmbLitElement, '') if (!item.unique) return nothing; return html` - + this.#removeItem(item)}> @@ -171,7 +175,7 @@ export class UmbUserInputElement extends UUIFormControlMixin(UmbLitElement, '') width: 100%; } - uui-avatar { + umb-user-avatar { font-size: var(--uui-size-4); } `, diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/modals/user-picker/user-picker-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/modals/user-picker/user-picker-modal.element.ts index 57c1262614..76356d5956 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/modals/user-picker/user-picker-modal.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/modals/user-picker/user-picker-modal.element.ts @@ -58,7 +58,11 @@ export class UmbUserPickerModalElement extends UmbModalBaseElement this.#selectionManager.select(user.unique)} @deselected=${() => this.#selectionManager.deselect(user.unique)} ?selected=${this.#selectionManager.isSelected(user.unique)}> - + `, )} @@ -74,8 +78,7 @@ export class UmbUserPickerModalElement extends UmbModalBaseElement Date: Wed, 4 Sep 2024 14:19:05 +0200 Subject: [PATCH 052/107] set img src based on element width --- .../user-avatar/user-avatar.element.ts | 73 +++++++++++++++---- 1 file changed, 57 insertions(+), 16 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/components/user-avatar/user-avatar.element.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/components/user-avatar/user-avatar.element.ts index a70b088bee..b146e43a0f 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/components/user-avatar/user-avatar.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/components/user-avatar/user-avatar.element.ts @@ -1,6 +1,17 @@ import type { UmbUserKindType } from '../../utils/index.js'; import { UmbUserKind } from '../../utils/index.js'; -import { css, html, customElement, property, ifDefined, state, classMap } from '@umbraco-cms/backoffice/external/lit'; +import type { UUIAvatarElement } from '@umbraco-cms/backoffice/external/uui'; +import type { PropertyValues } from '@umbraco-cms/backoffice/external/lit'; +import { + css, + html, + customElement, + property, + ifDefined, + state, + classMap, + query, +} from '@umbraco-cms/backoffice/external/lit'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; const elementName = 'umb-user-avatar'; @@ -18,45 +29,76 @@ export class UmbUserAvatarElement extends UmbLitElement { } public set imgUrls(value: Array) { this.#imgUrls = value; - this.#setUrls(); + this.hasImgUrls = value.length > 0; + this.#setImgSrcSizes(); } #imgUrls: Array = []; @state() - private _imgSrc: Array<{ scale: string; url: string }> = []; + private _imgSrcSizes: Array<{ w: number; url: string }> = []; @state() - private _imbSrcSet = ''; + private _imgSrc = ''; @state() private hasImgUrls = false; - #setUrls() { - this._imbSrcSet = ''; + @query('uui-avatar') + avatarElement!: UUIAvatarElement; + #setImgSrcSizes() { if (this.#imgUrls.length === 0) { - this._imgSrc = []; - this.hasImgUrls = false; + this._imgSrcSizes = []; return; } - this._imgSrc = [ + this._imgSrcSizes = [ { - scale: '1x', + w: 30, + url: this.#imgUrls[0], + }, + { + w: 60, url: this.#imgUrls[1], }, { - scale: '2x', + w: 90, url: this.#imgUrls[2], }, { - scale: '3x', + w: 150, url: this.#imgUrls[3], }, + { + w: 300, + url: this.#imgUrls[4], + }, ]; - this._imgSrc.forEach((url) => (this._imbSrcSet += `${url.url} ${url.scale},`)); - this.hasImgUrls = true; + this.#setImgSrc(); + } + + protected override firstUpdated(): void { + this.#setImgSrc(); + } + + async #setImgSrc() { + if (!this.hasImgUrls) return; + if (!this.avatarElement) return; + + setTimeout(() => { + // TODO: look into img sizes="auto" to let the browser handle the correct image size based on the element size + const elementSize = this.avatarElement.getBoundingClientRect(); + const elementWidth = elementSize.width; + + const matchingSizes = this._imgSrcSizes.filter((size) => { + // we multiply the element width to make sure we have a good quality image + return elementWidth * 1.5 <= size.w; + }); + + // We use the smallest image that is larger than the element width + this._imgSrc = matchingSizes[0]?.url; + }, 0); } override render() { @@ -68,8 +110,7 @@ export class UmbUserAvatarElement extends UmbLitElement { return html``; } From 9c60ab5f381b4a42b9e331a6f40ef1b4f9b470e1 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Wed, 4 Sep 2024 14:30:37 +0200 Subject: [PATCH 053/107] add better translations --- src/Umbraco.Web.UI.Client/src/assets/lang/da-dk.ts | 2 ++ src/Umbraco.Web.UI.Client/src/assets/lang/en-us.ts | 2 ++ .../action/create-user-collection-action.element.ts | 4 ++-- .../user-workspace-info/user-workspace-info.element.ts | 5 ++++- 4 files changed, 10 insertions(+), 3 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/assets/lang/da-dk.ts b/src/Umbraco.Web.UI.Client/src/assets/lang/da-dk.ts index 6546006c07..f975e527f1 100644 --- a/src/Umbraco.Web.UI.Client/src/assets/lang/da-dk.ts +++ b/src/Umbraco.Web.UI.Client/src/assets/lang/da-dk.ts @@ -1953,6 +1953,8 @@ export default { sortNameDescending: 'Navn (Å-A)', sortCreateDateAscending: 'Nyeste', sortCreateDateDescending: 'Ældste', + userKindDefault: 'Bruger', + userKindApi: 'API Bruger', sortLastLoginDateDescending: 'Sidst logget ind', noUserGroupsAdded: 'Ingen brugere er blevet tilføjet', '2faDisableText': 'Hvis du ønsker at slå denne totrinsbekræftelse fra, så skal du nu indtaste koden fra din enhed:', diff --git a/src/Umbraco.Web.UI.Client/src/assets/lang/en-us.ts b/src/Umbraco.Web.UI.Client/src/assets/lang/en-us.ts index 4905ce13d9..413a54ab63 100644 --- a/src/Umbraco.Web.UI.Client/src/assets/lang/en-us.ts +++ b/src/Umbraco.Web.UI.Client/src/assets/lang/en-us.ts @@ -1983,6 +1983,8 @@ export default { sortCreateDateDescending: 'Newest', sortCreateDateAscending: 'Oldest', sortLastLoginDateDescending: 'Last login', + userKindDefault: 'User', + userKindApi: 'API User', noUserGroupsAdded: 'No user groups have been added', '2faDisableText': 'If you wish to disable this two-factor provider, then you must enter the code shown on your authentication device:', diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/collection/action/create-user-collection-action.element.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/collection/action/create-user-collection-action.element.ts index 183a0bf573..3b5ba95990 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/collection/action/create-user-collection-action.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/collection/action/create-user-collection-action.element.ts @@ -58,10 +58,10 @@ export class UmbCollectionActionButtonElement extends UmbLitElement { @toggle=${this.#onPopoverToggle}> - + - + diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/workspace/components/user-workspace-info/user-workspace-info.element.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/workspace/components/user-workspace-info/user-workspace-info.element.ts index 3294e78ac2..3be3786c98 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/workspace/components/user-workspace-info/user-workspace-info.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/workspace/components/user-workspace-info/user-workspace-info.element.ts @@ -45,7 +45,10 @@ export class UmbUserWorkspaceInfoElement extends UmbLitElement { this._userInfo = [ { labelKey: 'user_kind', - value: user.kind, + value: + user.kind === UmbUserKind.API + ? this.localize.term('user_userKindApi') + : this.localize.term('user_userKindDefault'), }, { labelKey: 'user_lastLogin', From 65b638a90115b15edfc10c3b6b65a4e27bbb2b49 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Wed, 4 Sep 2024 14:48:01 +0200 Subject: [PATCH 054/107] add unplug icon from lucide --- .../core/icon-registry/icon-dictionary.json | 4 ++++ .../src/packages/core/icon-registry/icons.ts | 4 ++++ .../core/icon-registry/icons/icon-unplug.ts | 19 +++++++++++++++++++ 3 files changed, 27 insertions(+) create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/icon-registry/icons/icon-unplug.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/icon-registry/icon-dictionary.json b/src/Umbraco.Web.UI.Client/src/packages/core/icon-registry/icon-dictionary.json index 4288bb4b7d..63d7dcceae 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/icon-registry/icon-dictionary.json +++ b/src/Umbraco.Web.UI.Client/src/packages/core/icon-registry/icon-dictionary.json @@ -2308,6 +2308,10 @@ "name": "icon-unlocked", "file": "lock-open.svg" }, + { + "name": "icon-unplug", + "file": "unplug.svg" + }, { "name": "icon-untitled", "file": "box.svg", diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/icon-registry/icons.ts b/src/Umbraco.Web.UI.Client/src/packages/core/icon-registry/icons.ts index 5b8e14cb97..1300eed95e 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/icon-registry/icons.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/icon-registry/icons.ts @@ -1967,6 +1967,10 @@ name: "icon-unlocked", path: () => import("./icons/icon-unlocked.js"), },{ +name: "icon-unplug", + +path: () => import("./icons/icon-unplug.js"), +},{ name: "icon-untitled", legacy: true, path: () => import("./icons/icon-untitled.js"), diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/icon-registry/icons/icon-unplug.ts b/src/Umbraco.Web.UI.Client/src/packages/core/icon-registry/icons/icon-unplug.ts new file mode 100644 index 0000000000..be9a5e7702 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/icon-registry/icons/icon-unplug.ts @@ -0,0 +1,19 @@ +export default ` + + + + + + + + +`; \ No newline at end of file From a325f761130bd823c51f5dea83a448480d5f8526 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Wed, 4 Sep 2024 14:48:55 +0200 Subject: [PATCH 055/107] use unplug icon for api user --- .../collection/action/create-user-collection-action.element.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/collection/action/create-user-collection-action.element.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/collection/action/create-user-collection-action.element.ts index 3b5ba95990..11092189ec 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/collection/action/create-user-collection-action.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/collection/action/create-user-collection-action.element.ts @@ -62,7 +62,7 @@ export class UmbCollectionActionButtonElement extends UmbLitElement { - + From 61e95b6b10af42e4d90783bdef9fcebc68255d61 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Wed, 4 Sep 2024 14:50:25 +0200 Subject: [PATCH 056/107] use unplug icon in table --- .../views/table/user-table-collection-view.element.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/collection/views/table/user-table-collection-view.element.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/collection/views/table/user-table-collection-view.element.ts index 94e6f08a49..b0f1ab7fc2 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/collection/views/table/user-table-collection-view.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/collection/views/table/user-table-collection-view.element.ts @@ -19,6 +19,7 @@ import type { UmbReferenceByUnique } from '@umbraco-cms/backoffice/models'; import './column-layouts/name/user-table-name-column-layout.element.js'; import './column-layouts/status/user-table-status-column-layout.element.js'; +import { UmbUserKind } from '../../../utils/index.js'; @customElement('umb-user-table-collection-view') export class UmbUserTableCollectionViewElement extends UmbLitElement { @@ -114,7 +115,7 @@ export class UmbUserTableCollectionViewElement extends UmbLitElement { this._tableItems = this._users.map((user) => { return { id: user.unique, - icon: 'icon-user', + icon: user.kind === UmbUserKind.API ? 'icon-unplug' : 'icon-user', data: [ { columnAlias: 'userName', From 79c70c107a78d8e51626b8ef527422f5cf9681ca Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Wed, 4 Sep 2024 14:56:25 +0200 Subject: [PATCH 057/107] simplify transaltions --- src/Umbraco.Web.UI.Client/src/assets/lang/en-us.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/assets/lang/en-us.ts b/src/Umbraco.Web.UI.Client/src/assets/lang/en-us.ts index 413a54ab63..bb471cf0f9 100644 --- a/src/Umbraco.Web.UI.Client/src/assets/lang/en-us.ts +++ b/src/Umbraco.Web.UI.Client/src/assets/lang/en-us.ts @@ -1839,8 +1839,8 @@ export default { assignAccess: 'Assign access', administrators: 'Administrator', categoryField: 'Category field', - createDate: 'User created', - changePassword: 'Change your password', + createDate: 'Created', + changePassword: 'Change password', changePhoto: 'Change photo', configureMfa: 'Configure MFA', emailRequired: 'Required - enter an email address for this user', @@ -1936,7 +1936,7 @@ export default { startnodehelp: 'Limit the content tree to a specific start node', startnodes: 'Content start nodes', startnodeshelp: 'Limit the content tree to specific start nodes', - updateDate: 'User last updated', + updateDate: 'Updated', userCreated: 'has been created', userCreatedSuccessHelp: 'The new user has successfully been created. To log in to Umbraco use the\n password below.\n ', From 8c5c9f958499a4109632d3dc7cb23cf06a8f935e Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Wed, 4 Sep 2024 15:11:32 +0200 Subject: [PATCH 058/107] align entity actions position with content workspace --- .../user/user/workspace/user-workspace-editor.element.ts | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/workspace/user-workspace-editor.element.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/workspace/user-workspace-editor.element.ts index f7eaa4b38f..2526f44b14 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/workspace/user-workspace-editor.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/workspace/user-workspace-editor.element.ts @@ -66,6 +66,7 @@ export class UmbUserWorkspaceEditorElement extends UmbLitElement { + `; } @@ -89,11 +90,6 @@ export class UmbUserWorkspaceEditorElement extends UmbLitElement { - - - `; } From 29b3c2670ae226081135cd75b0bb6d86373f1cbb Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Wed, 4 Sep 2024 15:17:13 +0200 Subject: [PATCH 059/107] align entity action position --- .../user-group-workspace-editor.element.ts | 83 +++++++------------ 1 file changed, 30 insertions(+), 53 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user-group/workspace/user-group-workspace-editor.element.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user-group/workspace/user-group-workspace-editor.element.ts index 4888285574..613d012475 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user-group/workspace/user-group-workspace-editor.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user-group/workspace/user-group-workspace-editor.element.ts @@ -174,11 +174,7 @@ export class UmbUserGroupWorkspaceEditorElement extends UmbLitElement { alias="Umb.Workspace.UserGroup" class="uui-text" back-path="/section/user-management/view/user-groups"> - ${this.#renderHeader()} -
-
${this.#renderLeftColumn()}
-
${this.#renderRightColumn()}
-
+ ${this.#renderHeader()} ${this.#renderMain()} `; } @@ -225,40 +221,46 @@ export class UmbUserGroupWorkspaceEditorElement extends UmbLitElement { ${umbFocus()}> + + `; } - #renderLeftColumn() { + #renderMain() { if (!this._unique) return nothing; return html` - -
+
+ + +
- - - + + + - ${this.#renderLanguageAccess()} ${this.#renderDocumentAccess()} ${this.#renderMediaAccess()} -
+ ${this.#renderLanguageAccess()} ${this.#renderDocumentAccess()} ${this.#renderMediaAccess()} + - -
+ +
- - - -
+ + + +
- -
- -
+ +
+ +
+
+
`; } @@ -338,15 +340,6 @@ export class UmbUserGroupWorkspaceEditorElement extends UmbLitElement { `; } - #renderRightColumn() { - return html` - - - - - `; - } - static override styles = [ UmbTextStyles, css` @@ -375,25 +368,9 @@ export class UmbUserGroupWorkspaceEditorElement extends UmbLitElement { } #main { - display: grid; - grid-template-columns: 1fr 350px; - gap: var(--uui-size-layout-1); padding: var(--uui-size-layout-1); } - #left-column, - #right-column { - display: flex; - flex-direction: column; - gap: var(--uui-size-space-4); - } - - #right-column > uui-box > div { - display: flex; - flex-direction: column; - gap: var(--uui-size-space-2); - } - uui-input { width: 100%; } From 805813fe338d94da09709e49fbeb6638191bf34a Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Thu, 5 Sep 2024 08:41:05 +0200 Subject: [PATCH 060/107] add user group paths --- .../src/packages/user/user-group/paths.ts | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 src/Umbraco.Web.UI.Client/src/packages/user/user-group/paths.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user-group/paths.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user-group/paths.ts new file mode 100644 index 0000000000..6fc1f8cc7e --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user-group/paths.ts @@ -0,0 +1,8 @@ +import { UMB_USER_SECTION_PATHNAME } from '../user-section/paths.js'; +import { UMB_USER_GROUP_ENTITY_TYPE } from './entity.js'; +import { UMB_WORKSPACE_PATH_PATTERN } from '@umbraco-cms/backoffice/workspace'; + +export const UMB_USER_GROUP_WORKSPACE_PATH = UMB_WORKSPACE_PATH_PATTERN.generateAbsolute({ + sectionName: UMB_USER_SECTION_PATHNAME, + entityType: UMB_USER_GROUP_ENTITY_TYPE, +}); From 92df2e474758dbddb529da4614faa493049c6c8c Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Thu, 5 Sep 2024 08:55:57 +0200 Subject: [PATCH 061/107] link card to workspace --- .../components/user-group-table-name-column-layout.element.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user-group/collection/components/user-group-table-name-column-layout.element.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user-group/collection/components/user-group-table-name-column-layout.element.ts index 1a1274620d..f320f8ef79 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user-group/collection/components/user-group-table-name-column-layout.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user-group/collection/components/user-group-table-name-column-layout.element.ts @@ -1,3 +1,4 @@ +import { UMB_USER_GROUP_WORKSPACE_PATH } from '../../paths.js'; import { css, html, LitElement, customElement, property } from '@umbraco-cms/backoffice/external/lit'; import type { UmbTableItem } from '@umbraco-cms/backoffice/components'; import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; @@ -11,7 +12,7 @@ export class UmbUserGroupTableNameColumnLayoutElement extends LitElement { value!: any; override render() { - const href = `section/user-management/view/user-groups/user-group/edit/${this.item.id}`; + const href = UMB_USER_GROUP_WORKSPACE_PATH + '/edit/' + this.item.id; return html`${this.value.name}`; } From ff74af57e6f618b5d382952fda72271cc283f0c5 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Thu, 5 Sep 2024 10:37:25 +0200 Subject: [PATCH 062/107] add kind to modal data --- .../user/user/modals/create/create-user-modal.token.ts | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/modals/create/create-user-modal.token.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/modals/create/create-user-modal.token.ts index d8e2edf546..4486b12f4f 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/modals/create/create-user-modal.token.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/modals/create/create-user-modal.token.ts @@ -1,7 +1,14 @@ +import type { UmbUserKindType } from '../../utils/index.js'; import { UMB_CREATE_USER_MODAL_ALIAS } from './constants.js'; import { UmbModalToken } from '@umbraco-cms/backoffice/modal'; -export const UMB_CREATE_USER_MODAL = new UmbModalToken(UMB_CREATE_USER_MODAL_ALIAS, { +export interface UmbCreateUserModalData { + user: { + kind?: UmbUserKindType; + }; +} + +export const UMB_CREATE_USER_MODAL = new UmbModalToken(UMB_CREATE_USER_MODAL_ALIAS, { modal: { type: 'dialog', size: 'small', From ae1d5f6dc30150f82d4461fb4ded41a08912a2fd Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Thu, 5 Sep 2024 10:37:45 +0200 Subject: [PATCH 063/107] pass kind to modal --- .../create-user-collection-action.element.ts | 20 +++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/collection/action/create-user-collection-action.element.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/collection/action/create-user-collection-action.element.ts index 11092189ec..437243ed26 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/collection/action/create-user-collection-action.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/collection/action/create-user-collection-action.element.ts @@ -1,4 +1,6 @@ import { UMB_CREATE_USER_MODAL } from '../../modals/create/create-user-modal.token.js'; +import type { UmbUserKindType } from '../../utils/index.js'; +import { UmbUserKind } from '../../utils/index.js'; import { html, customElement, state } from '@umbraco-cms/backoffice/external/lit'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; import { UMB_MODAL_MANAGER_CONTEXT } from '@umbraco-cms/backoffice/modal'; @@ -12,7 +14,7 @@ export class UmbCollectionActionButtonElement extends UmbLitElement { @state() private _popoverOpen = false; - async #onClick(event: Event) { + async #onClick(event: Event, kind: UmbUserKindType) { event.stopPropagation(); const modalManager = await this.getContext(UMB_MODAL_MANAGER_CONTEXT); const entityContext = await this.getContext(UMB_ENTITY_CONTEXT); @@ -23,7 +25,13 @@ export class UmbCollectionActionButtonElement extends UmbLitElement { if (unique === undefined) throw new Error('Missing unique'); if (!entityType) throw new Error('Missing entityType'); - const modalContext = modalManager.open(this, UMB_CREATE_USER_MODAL); + const modalContext = modalManager.open(this, UMB_CREATE_USER_MODAL, { + data: { + user: { + kind, + }, + }, + }); modalContext?.onSubmit().catch(async () => { // modal is closed after creation instead of navigating to the new user. // We therefore need to reload the children of the entity @@ -58,10 +66,14 @@ export class UmbCollectionActionButtonElement extends UmbLitElement { @toggle=${this.#onPopoverToggle}> - + this.#onClick(event, UmbUserKind.DEFAULT)}> - + this.#onClick(event, UmbUserKind.API)}> From fae815cef3dbd3faeecfee984e03a538a390d97f Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Thu, 5 Sep 2024 10:44:54 +0200 Subject: [PATCH 064/107] remove debugger --- .../user/modals/create/create-user-success-modal.element.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/modals/create/create-user-success-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/modals/create/create-user-success-modal.element.ts index 03a6872298..8185df073f 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/modals/create/create-user-success-modal.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/modals/create/create-user-success-modal.element.ts @@ -36,8 +36,6 @@ export class UmbCreateUserSuccessModalElement extends UmbModalBaseElement< const unique = this.data?.user.unique; if (!unique) throw new Error('No user unique is provided'); - debugger; - const [userItemResponse, newPasswordResponse] = await Promise.all([ this.#userItemRepository.requestItems([unique]), this.#userNewPasswordRepository.requestNewPassword(unique), From b404743674798a1304b264dca11b206cd9335bdd Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Thu, 5 Sep 2024 10:45:09 +0200 Subject: [PATCH 065/107] pass kind to repo --- .../create/create-user-modal.element.ts | 24 ++++++++----------- 1 file changed, 10 insertions(+), 14 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/modals/create/create-user-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/modals/create/create-user-modal.element.ts index d3dc9ed3cc..3a2c03ba82 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/modals/create/create-user-modal.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/modals/create/create-user-modal.element.ts @@ -1,6 +1,8 @@ import { UmbUserDetailRepository } from '../../repository/index.js'; -import { UmbUserKind, UmbUserKindType } from '../../utils/index.js'; +import type { UmbUserKindType } from '../../utils/index.js'; +import { UmbUserKind } from '../../utils/index.js'; import { UMB_CREATE_USER_SUCCESS_MODAL } from './create-user-success-modal.token.js'; +import type { UmbCreateUserModalData } from './create-user-modal.token.js'; import type { UmbUserGroupInputElement } from '@umbraco-cms/backoffice/user-group'; import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; import { css, html, customElement, query } from '@umbraco-cms/backoffice/external/lit'; @@ -8,7 +10,7 @@ import { UmbModalBaseElement, UMB_MODAL_MANAGER_CONTEXT } from '@umbraco-cms/bac import type { UmbReferenceByUnique } from '@umbraco-cms/backoffice/models'; @customElement('umb-create-user-modal') -export class UmbCreateUserModalElement extends UmbModalBaseElement { +export class UmbCreateUserModalElement extends UmbModalBaseElement { #userDetailRepository = new UmbUserDetailRepository(this); @query('#CreateUserForm') @@ -25,7 +27,6 @@ export class UmbCreateUserModalElement extends UmbModalBaseElement { const formData = new FormData(form); - const kind = formData.get('kind') as UmbUserKindType; const name = formData.get('name') as string; const email = formData.get('email') as string; @@ -37,7 +38,7 @@ export class UmbCreateUserModalElement extends UmbModalBaseElement { const { data: userScaffold } = await this.#userDetailRepository.createScaffold(); if (!userScaffold) return; - userScaffold.kind = kind; + userScaffold.kind = this.data?.user.kind ?? UmbUserKind.DEFAULT; userScaffold.name = name; userScaffold.email = email; userScaffold.userName = email; @@ -47,7 +48,11 @@ export class UmbCreateUserModalElement extends UmbModalBaseElement { const { data } = await this.#userDetailRepository.create(userScaffold); if (data) { - this.#openSuccessModal(data.unique); + if (data.kind === UmbUserKind.DEFAULT) { + this.#openSuccessModal(data.unique); + } else { + this._submitModal(); + } } } @@ -97,15 +102,6 @@ export class UmbCreateUserModalElement extends UmbModalBaseElement { #renderForm() { return html` - - Kind - - - ${UmbUserKind.DEFAULT} - ${UmbUserKind.API} - - - Name From b98de68e273d0c51a2fdb71fb220dfc772ce7bc3 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Thu, 5 Sep 2024 11:07:44 +0200 Subject: [PATCH 066/107] use href --- .../modals/create/create-user-success-modal.element.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/modals/create/create-user-success-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/modals/create/create-user-success-modal.element.ts index 8185df073f..bb5bcef6bb 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/modals/create/create-user-success-modal.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/modals/create/create-user-success-modal.element.ts @@ -11,6 +11,7 @@ import type { UUIInputPasswordElement } from '@umbraco-cms/backoffice/external/u import type { UmbNotificationDefaultData, UmbNotificationContext } from '@umbraco-cms/backoffice/notification'; import { UMB_NOTIFICATION_CONTEXT } from '@umbraco-cms/backoffice/notification'; import { UmbModalBaseElement } from '@umbraco-cms/backoffice/modal'; +import { UMB_USER_WORKSPACE_PATH } from '../../paths.js'; @customElement('umb-create-user-success-modal') export class UmbCreateUserSuccessModalElement extends UmbModalBaseElement< @@ -69,10 +70,8 @@ export class UmbCreateUserSuccessModalElement extends UmbModalBaseElement< this._rejectModal({ type: 'createAnotherUser' }); }; - #onGoToProfile = (event: Event) => { - event.stopPropagation(); + #onGoToProfile = () => { this._submitModal(); - history.pushState(null, '', 'section/user-management/view/users/user/edit/' + this.data?.user.unique); //TODO: URL Should be dynamic }; override render() { @@ -98,7 +97,8 @@ export class UmbCreateUserSuccessModalElement extends UmbModalBaseElement< slot="actions" label="Go to profile" look="primary" - color="positive">
+ color="positive" + href=${UMB_USER_WORKSPACE_PATH + '/edit/' + this.data?.user.unique}>
`; } From 6ed3b9eb831619d20acd0cd004d355ce13e4af93 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Thu, 5 Sep 2024 15:20:30 +0200 Subject: [PATCH 067/107] translate create dialog headline and description --- src/Umbraco.Web.UI.Client/src/assets/lang/da-dk.ts | 3 +++ src/Umbraco.Web.UI.Client/src/assets/lang/en-us.ts | 8 ++++++++ .../user/user/modals/create/create-user-modal.element.ts | 7 ++----- 3 files changed, 13 insertions(+), 5 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/assets/lang/da-dk.ts b/src/Umbraco.Web.UI.Client/src/assets/lang/da-dk.ts index f975e527f1..d60320fb16 100644 --- a/src/Umbraco.Web.UI.Client/src/assets/lang/da-dk.ts +++ b/src/Umbraco.Web.UI.Client/src/assets/lang/da-dk.ts @@ -1831,6 +1831,9 @@ export default { administrators: 'Administrator', categoryField: 'Kategorifelt', createDate: 'Bruger oprettet', + createUserHeadline: (kind: string) => { + return kind === 'Api' ? 'Opret API bruger' : 'Opret bruger'; + }, changePassword: 'Skift dit kodeord', changePhoto: 'Skift billede', newPassword: 'Nyt kodeord', diff --git a/src/Umbraco.Web.UI.Client/src/assets/lang/en-us.ts b/src/Umbraco.Web.UI.Client/src/assets/lang/en-us.ts index bb471cf0f9..5e0d3f266e 100644 --- a/src/Umbraco.Web.UI.Client/src/assets/lang/en-us.ts +++ b/src/Umbraco.Web.UI.Client/src/assets/lang/en-us.ts @@ -1840,6 +1840,14 @@ export default { administrators: 'Administrator', categoryField: 'Category field', createDate: 'Created', + createUserHeadline: (kind: string) => { + return kind === 'Api' ? 'Create API user' : 'Create user'; + }, + createUserDescription: (kind: string) => { + const defaultUserText = `Create a user to give them access to Umbraco. When a user is created a password will be generated that you can share with them.`; + const apiUserText = `Create an Api User to allow external services to authenticate with the Umbraco Management API.`; + return kind === 'Api' ? apiUserText : defaultUserText; + }, changePassword: 'Change password', changePhoto: 'Change photo', configureMfa: 'Configure MFA', diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/modals/create/create-user-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/modals/create/create-user-modal.element.ts index 3a2c03ba82..adc53caec4 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/modals/create/create-user-modal.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/modals/create/create-user-modal.element.ts @@ -81,11 +81,8 @@ export class UmbCreateUserModalElement extends UmbModalBaseElement -

- Create new users to give them access to Umbraco. When a user is created a password will be generated that you - can share with the user. -

+ return html` +

${this.localize.term('user_createUserDescription', this.data?.user.kind)}

${this.#renderForm()} From 83f7f3bee3f40add43e03f136282df583b0d03ae Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Thu, 5 Sep 2024 15:21:14 +0200 Subject: [PATCH 068/107] remove unused --- .../user/user/modals/create/create-user-modal.element.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/modals/create/create-user-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/modals/create/create-user-modal.element.ts index adc53caec4..863fc88bec 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/modals/create/create-user-modal.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/modals/create/create-user-modal.element.ts @@ -1,5 +1,4 @@ import { UmbUserDetailRepository } from '../../repository/index.js'; -import type { UmbUserKindType } from '../../utils/index.js'; import { UmbUserKind } from '../../utils/index.js'; import { UMB_CREATE_USER_SUCCESS_MODAL } from './create-user-success-modal.token.js'; import type { UmbCreateUserModalData } from './create-user-modal.token.js'; From fb782d46a66f6248a60008b33a8c27f81ccc1515 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Thu, 5 Sep 2024 15:23:02 +0200 Subject: [PATCH 069/107] fix order --- .../user/modals/create/create-user-success-modal.element.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/modals/create/create-user-success-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/modals/create/create-user-success-modal.element.ts index bb5bcef6bb..f30bf145be 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/modals/create/create-user-success-modal.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/modals/create/create-user-success-modal.element.ts @@ -1,6 +1,7 @@ import { UmbUserItemRepository } from '../../repository/item/index.js'; import { UmbNewUserPasswordRepository } from '../../repository/new-password/index.js'; import type { UmbUserItemModel } from '../../repository/item/types.js'; +import { UMB_USER_WORKSPACE_PATH } from '../../paths.js'; import type { UmbCreateUserSuccessModalData, UmbCreateUserSuccessModalValue, @@ -11,7 +12,6 @@ import type { UUIInputPasswordElement } from '@umbraco-cms/backoffice/external/u import type { UmbNotificationDefaultData, UmbNotificationContext } from '@umbraco-cms/backoffice/notification'; import { UMB_NOTIFICATION_CONTEXT } from '@umbraco-cms/backoffice/notification'; import { UmbModalBaseElement } from '@umbraco-cms/backoffice/modal'; -import { UMB_USER_WORKSPACE_PATH } from '../../paths.js'; @customElement('umb-create-user-success-modal') export class UmbCreateUserSuccessModalElement extends UmbModalBaseElement< From 57f6cd64e5de3140cfd79809f012a7db4c5e807c Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Thu, 5 Sep 2024 15:42:27 +0200 Subject: [PATCH 070/107] reload collection after user creation --- .../create-user-collection-action.element.ts | 29 +++++++++++++------ 1 file changed, 20 insertions(+), 9 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/collection/action/create-user-collection-action.element.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/collection/action/create-user-collection-action.element.ts index 437243ed26..4ffcc353d0 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/collection/action/create-user-collection-action.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/collection/action/create-user-collection-action.element.ts @@ -4,6 +4,7 @@ import { UmbUserKind } from '../../utils/index.js'; import { html, customElement, state } from '@umbraco-cms/backoffice/external/lit'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; import { UMB_MODAL_MANAGER_CONTEXT } from '@umbraco-cms/backoffice/modal'; +import type { UmbEntityModel } from '@umbraco-cms/backoffice/entity'; import { UMB_ENTITY_CONTEXT } from '@umbraco-cms/backoffice/entity'; import { UMB_ACTION_EVENT_CONTEXT } from '@umbraco-cms/backoffice/action'; import { UmbRequestReloadChildrenOfEntityEvent } from '@umbraco-cms/backoffice/entity-action'; @@ -32,17 +33,27 @@ export class UmbCollectionActionButtonElement extends UmbLitElement { }, }, }); - modalContext?.onSubmit().catch(async () => { - // modal is closed after creation instead of navigating to the new user. - // We therefore need to reload the children of the entity - const eventContext = await this.getContext(UMB_ACTION_EVENT_CONTEXT); - const event = new UmbRequestReloadChildrenOfEntityEvent({ - entityType, - unique, - }); - eventContext.dispatchEvent(event); + modalContext + ?.onSubmit() + .then(() => { + this.#requestReloadChildrenOfEntity({ entityType, unique }); + }) + .catch(async () => { + // modal is closed after creation instead of navigating to the new user. + // We therefore need to reload the children of the entity + this.#requestReloadChildrenOfEntity({ entityType, unique }); + }); + } + + async #requestReloadChildrenOfEntity({ entityType, unique }: UmbEntityModel) { + const eventContext = await this.getContext(UMB_ACTION_EVENT_CONTEXT); + const event = new UmbRequestReloadChildrenOfEntityEvent({ + entityType, + unique, }); + + eventContext.dispatchEvent(event); } #onPopoverToggle(event: ToggleEvent) { From c171ae0b3da2c03517ed289df0d8d83107f034a1 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Mon, 9 Sep 2024 14:00:08 +0200 Subject: [PATCH 071/107] add a more generic description of username --- src/Umbraco.Web.UI.Client/src/assets/lang/da-dk.ts | 2 +- src/Umbraco.Web.UI.Client/src/assets/lang/en-us.ts | 2 +- src/Umbraco.Web.UI.Client/src/assets/lang/en.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/assets/lang/da-dk.ts b/src/Umbraco.Web.UI.Client/src/assets/lang/da-dk.ts index d60320fb16..1ffcb224a6 100644 --- a/src/Umbraco.Web.UI.Client/src/assets/lang/da-dk.ts +++ b/src/Umbraco.Web.UI.Client/src/assets/lang/da-dk.ts @@ -1868,7 +1868,7 @@ export default { lastPasswordChangeDate: 'Kodeord sidst ændret', loginname: 'Brugernavn', loginnameRequired: 'Påkrævet - indtast et brugernavn for denne bruger', - loginnameDescription: 'Brugernavnet bruges til at logge ind og til at identificere brugeren', + loginnameDescription: 'Et unikt navn til at identificere brugeren', mediastartnode: 'Startnode i mediearkivet', mediastartnodehelp: 'Begræns mediebiblioteket til en bestemt startnode', mediastartnodes: 'Medie startnoder', diff --git a/src/Umbraco.Web.UI.Client/src/assets/lang/en-us.ts b/src/Umbraco.Web.UI.Client/src/assets/lang/en-us.ts index 5e0d3f266e..45ed7d1318 100644 --- a/src/Umbraco.Web.UI.Client/src/assets/lang/en-us.ts +++ b/src/Umbraco.Web.UI.Client/src/assets/lang/en-us.ts @@ -1890,7 +1890,7 @@ export default { lastPasswordChangeDate: 'Password last changed', loginname: 'Username', loginnameRequired: 'Required - enter a username for this user', - loginnameDescription: 'The username is used for logging in', + loginnameDescription: 'A unique name that identifies the user', mediastartnode: 'Media start node', mediastartnodehelp: 'Limit the media library to a specific start node', mediastartnodes: 'Media start nodes', diff --git a/src/Umbraco.Web.UI.Client/src/assets/lang/en.ts b/src/Umbraco.Web.UI.Client/src/assets/lang/en.ts index 551e778e96..43eb4cf416 100644 --- a/src/Umbraco.Web.UI.Client/src/assets/lang/en.ts +++ b/src/Umbraco.Web.UI.Client/src/assets/lang/en.ts @@ -1939,7 +1939,7 @@ export default { lastPasswordChangeDate: 'Password last changed', loginname: 'Username', loginnameRequired: 'Required - enter a username for this user', - loginnameDescription: 'The username is used for logging in', + loginnameDescription: 'A unique name that identifies the user', mediastartnode: 'Media start node', mediastartnodehelp: 'Limit the media library to a specific start node', mediastartnodes: 'Media start nodes', From 1e4fdd76706f4c37a59fce57aa8268a1f1da0332 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Mon, 9 Sep 2024 14:08:01 +0200 Subject: [PATCH 072/107] always show email on username --- ...user-workspace-profile-settings.element.ts | 52 +++++++++---------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/workspace/components/user-workspace-profile-settings/user-workspace-profile-settings.element.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/workspace/components/user-workspace-profile-settings/user-workspace-profile-settings.element.ts index fd4e67c615..b37b11d69b 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/workspace/components/user-workspace-profile-settings/user-workspace-profile-settings.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/workspace/components/user-workspace-profile-settings/user-workspace-profile-settings.element.ts @@ -1,11 +1,11 @@ import { UMB_USER_WORKSPACE_CONTEXT } from '../../user-workspace.context-token.js'; import type { UmbUserDetailModel } from '../../../types.js'; +import { UmbUserKind } from '../../../utils/index.js'; import { html, customElement, state, ifDefined, css, nothing } from '@umbraco-cms/backoffice/external/lit'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; import type { UmbChangeEvent } from '@umbraco-cms/backoffice/event'; import type { UmbUiCultureInputElement } from '@umbraco-cms/backoffice/localization'; -import { UmbUserKind } from '../../../utils/index.js'; @customElement('umb-user-workspace-profile-settings') export class UmbUserWorkspaceProfileSettingsElement extends UmbLitElement { @@ -31,7 +31,7 @@ export class UmbUserWorkspaceProfileSettingsElement extends UmbLitElement { }); } - #onEmailChange(event: UmbChangeEvent) { + #onEmailInput(event: UmbChangeEvent) { const target = event.target as HTMLInputElement; if (typeof target?.value === 'string') { @@ -43,7 +43,7 @@ export class UmbUserWorkspaceProfileSettingsElement extends UmbLitElement { } } - #onUsernameChange(event: UmbChangeEvent) { + #onUsernameInput(event: UmbChangeEvent) { const target = event.target as HTMLInputElement; if (typeof target?.value === 'string') { @@ -62,31 +62,11 @@ export class UmbUserWorkspaceProfileSettingsElement extends UmbLitElement { override render() { return html`
Profile
- ${this.#renderEmailProperty()} ${this.#renderUsernameProperty()} ${this.#renderUILanguageProperty()} + ${this.#renderUsernameProperty()}${this.#renderEmailProperty()} ${this.#renderUILanguageProperty()}
`; } - #renderEmailProperty() { - return html` - - - - `; - } - #renderUsernameProperty() { - if (this._usernameIsEmail) return nothing; - return html` + value=${ifDefined(this._user?.userName)} + ?readonly=${this._usernameIsEmail}> + + `; + } + + #renderEmailProperty() { + return html` + + `; } From 73a94d4c9dcb0532e1d9ff038095d732859f457b Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Mon, 9 Sep 2024 15:42:43 +0200 Subject: [PATCH 073/107] Revert "add a more generic description of username" This reverts commit c171ae0b3da2c03517ed289df0d8d83107f034a1. --- src/Umbraco.Web.UI.Client/src/assets/lang/da-dk.ts | 2 +- src/Umbraco.Web.UI.Client/src/assets/lang/en-us.ts | 2 +- src/Umbraco.Web.UI.Client/src/assets/lang/en.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/assets/lang/da-dk.ts b/src/Umbraco.Web.UI.Client/src/assets/lang/da-dk.ts index 1ffcb224a6..d60320fb16 100644 --- a/src/Umbraco.Web.UI.Client/src/assets/lang/da-dk.ts +++ b/src/Umbraco.Web.UI.Client/src/assets/lang/da-dk.ts @@ -1868,7 +1868,7 @@ export default { lastPasswordChangeDate: 'Kodeord sidst ændret', loginname: 'Brugernavn', loginnameRequired: 'Påkrævet - indtast et brugernavn for denne bruger', - loginnameDescription: 'Et unikt navn til at identificere brugeren', + loginnameDescription: 'Brugernavnet bruges til at logge ind og til at identificere brugeren', mediastartnode: 'Startnode i mediearkivet', mediastartnodehelp: 'Begræns mediebiblioteket til en bestemt startnode', mediastartnodes: 'Medie startnoder', diff --git a/src/Umbraco.Web.UI.Client/src/assets/lang/en-us.ts b/src/Umbraco.Web.UI.Client/src/assets/lang/en-us.ts index 45ed7d1318..5e0d3f266e 100644 --- a/src/Umbraco.Web.UI.Client/src/assets/lang/en-us.ts +++ b/src/Umbraco.Web.UI.Client/src/assets/lang/en-us.ts @@ -1890,7 +1890,7 @@ export default { lastPasswordChangeDate: 'Password last changed', loginname: 'Username', loginnameRequired: 'Required - enter a username for this user', - loginnameDescription: 'A unique name that identifies the user', + loginnameDescription: 'The username is used for logging in', mediastartnode: 'Media start node', mediastartnodehelp: 'Limit the media library to a specific start node', mediastartnodes: 'Media start nodes', diff --git a/src/Umbraco.Web.UI.Client/src/assets/lang/en.ts b/src/Umbraco.Web.UI.Client/src/assets/lang/en.ts index 43eb4cf416..551e778e96 100644 --- a/src/Umbraco.Web.UI.Client/src/assets/lang/en.ts +++ b/src/Umbraco.Web.UI.Client/src/assets/lang/en.ts @@ -1939,7 +1939,7 @@ export default { lastPasswordChangeDate: 'Password last changed', loginname: 'Username', loginnameRequired: 'Required - enter a username for this user', - loginnameDescription: 'A unique name that identifies the user', + loginnameDescription: 'The username is used for logging in', mediastartnode: 'Media start node', mediastartnodehelp: 'Limit the media library to a specific start node', mediastartnodes: 'Media start nodes', From c48b988d6990e48d8788c5a8321a6b69eff79f3d Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Mon, 9 Sep 2024 15:42:49 +0200 Subject: [PATCH 074/107] Revert "always show email on username" This reverts commit 1e4fdd76706f4c37a59fce57aa8268a1f1da0332. --- ...user-workspace-profile-settings.element.ts | 52 +++++++++---------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/workspace/components/user-workspace-profile-settings/user-workspace-profile-settings.element.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/workspace/components/user-workspace-profile-settings/user-workspace-profile-settings.element.ts index b37b11d69b..fd4e67c615 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/workspace/components/user-workspace-profile-settings/user-workspace-profile-settings.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/workspace/components/user-workspace-profile-settings/user-workspace-profile-settings.element.ts @@ -1,11 +1,11 @@ import { UMB_USER_WORKSPACE_CONTEXT } from '../../user-workspace.context-token.js'; import type { UmbUserDetailModel } from '../../../types.js'; -import { UmbUserKind } from '../../../utils/index.js'; import { html, customElement, state, ifDefined, css, nothing } from '@umbraco-cms/backoffice/external/lit'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; import type { UmbChangeEvent } from '@umbraco-cms/backoffice/event'; import type { UmbUiCultureInputElement } from '@umbraco-cms/backoffice/localization'; +import { UmbUserKind } from '../../../utils/index.js'; @customElement('umb-user-workspace-profile-settings') export class UmbUserWorkspaceProfileSettingsElement extends UmbLitElement { @@ -31,7 +31,7 @@ export class UmbUserWorkspaceProfileSettingsElement extends UmbLitElement { }); } - #onEmailInput(event: UmbChangeEvent) { + #onEmailChange(event: UmbChangeEvent) { const target = event.target as HTMLInputElement; if (typeof target?.value === 'string') { @@ -43,7 +43,7 @@ export class UmbUserWorkspaceProfileSettingsElement extends UmbLitElement { } } - #onUsernameInput(event: UmbChangeEvent) { + #onUsernameChange(event: UmbChangeEvent) { const target = event.target as HTMLInputElement; if (typeof target?.value === 'string') { @@ -62,11 +62,31 @@ export class UmbUserWorkspaceProfileSettingsElement extends UmbLitElement { override render() { return html`
Profile
- ${this.#renderUsernameProperty()}${this.#renderEmailProperty()} ${this.#renderUILanguageProperty()} + ${this.#renderEmailProperty()} ${this.#renderUsernameProperty()} ${this.#renderUILanguageProperty()}
`; } + #renderEmailProperty() { + return html` + + + + `; + } + #renderUsernameProperty() { + if (this._usernameIsEmail) return nothing; + return html` - - `; - } - - #renderEmailProperty() { - return html` - - + value=${ifDefined(this._user?.userName)}> `; } From 42957136f1c7bb0895601485077bc3820e63b87e Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Mon, 9 Sep 2024 16:33:03 +0200 Subject: [PATCH 075/107] Update types.gen.ts --- .../src/external/backend-api/src/types.gen.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/external/backend-api/src/types.gen.ts b/src/Umbraco.Web.UI.Client/src/external/backend-api/src/types.gen.ts index 224bc0862b..8a194b70f5 100644 --- a/src/Umbraco.Web.UI.Client/src/external/backend-api/src/types.gen.ts +++ b/src/Umbraco.Web.UI.Client/src/external/backend-api/src/types.gen.ts @@ -1081,7 +1081,6 @@ export type InviteUserRequestModel = { name: string; userGroupIds: Array<(ReferenceByIdModel)>; id?: string | null; - kind: UserKindModel; message?: string | null; }; From 0e613cc545cce1e648808034acb3f53d1c2c380a Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Mon, 9 Sep 2024 16:35:58 +0200 Subject: [PATCH 076/107] Update ApiRequestOptions.ts --- .../backend-api/src/core/ApiRequestOptions.ts | 23 +++++++------------ 1 file changed, 8 insertions(+), 15 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/external/backend-api/src/core/ApiRequestOptions.ts b/src/Umbraco.Web.UI.Client/src/external/backend-api/src/core/ApiRequestOptions.ts index 939a0aa4c8..1758d98c4d 100644 --- a/src/Umbraco.Web.UI.Client/src/external/backend-api/src/core/ApiRequestOptions.ts +++ b/src/Umbraco.Web.UI.Client/src/external/backend-api/src/core/ApiRequestOptions.ts @@ -1,21 +1,14 @@ export type ApiRequestOptions = { - readonly body?: any; - readonly cookies?: Record; - readonly errors?: Record; - readonly formData?: Record | any[] | Blob | File; - readonly headers?: Record; - readonly mediaType?: string; - readonly method: - | 'DELETE' - | 'GET' - | 'HEAD' - | 'OPTIONS' - | 'PATCH' - | 'POST' - | 'PUT'; + readonly method: 'GET' | 'PUT' | 'POST' | 'DELETE' | 'OPTIONS' | 'HEAD' | 'PATCH'; + readonly url: string; readonly path?: Record; + readonly cookies?: Record; + readonly headers?: Record; readonly query?: Record; + readonly formData?: Record; + readonly body?: any; + readonly mediaType?: string; readonly responseHeader?: string; readonly responseTransformer?: (data: unknown) => Promise; - readonly url: string; + readonly errors?: Record; }; \ No newline at end of file From 16cf11f3106d029a79ede580574120c49b242d31 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Mon, 9 Sep 2024 16:36:57 +0200 Subject: [PATCH 077/107] Delete index.ts --- .../src/packages/user/user/collection/action/index.ts | 1 - 1 file changed, 1 deletion(-) delete mode 100644 src/Umbraco.Web.UI.Client/src/packages/user/user/collection/action/index.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/collection/action/index.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/collection/action/index.ts deleted file mode 100644 index 807c9a6fee..0000000000 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/collection/action/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { UmbCreateUserCollectionAction } from './create-user.collection-action.js'; From acdeafebbfecd2b1772f695c3825244c5e1d3e8e Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Mon, 9 Sep 2024 16:38:30 +0200 Subject: [PATCH 078/107] Update member.db.ts --- .../src/mocks/data/member/member.db.ts | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/mocks/data/member/member.db.ts b/src/Umbraco.Web.UI.Client/src/mocks/data/member/member.db.ts index c97ec93af9..ca5fb77e98 100644 --- a/src/Umbraco.Web.UI.Client/src/mocks/data/member/member.db.ts +++ b/src/Umbraco.Web.UI.Client/src/mocks/data/member/member.db.ts @@ -6,10 +6,11 @@ import { UmbMockContentCollectionManager } from '../utils/content/content-collec import type { UmbMockMemberModel } from './member.data.js'; import { data } from './member.data.js'; import { UmbId } from '@umbraco-cms/backoffice/id'; -import type { - CreateMemberRequestModel, - MemberItemResponseModel, - MemberResponseModel, +import { + MemberKindModel, + type CreateMemberRequestModel, + type MemberItemResponseModel, + type MemberResponseModel, } from '@umbraco-cms/backoffice/external/backend-api'; class UmbMemberMockDB extends UmbEntityMockDbBase { @@ -39,6 +40,7 @@ const createDetailMockMapper = (request: CreateMemberRequestModel): UmbMockMembe lastLockoutDate: null, lastLoginDate: null, lastPasswordChangeDate: null, + kind: MemberKindModel.DEFAULT, memberType: { id: memberType.id, icon: memberType.icon, From bd50abeffbe7f36b4d95d0767318f887e472caf0 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Mon, 9 Sep 2024 16:42:22 +0200 Subject: [PATCH 079/107] inherit color --- .../user/user/components/user-avatar/user-avatar.element.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/components/user-avatar/user-avatar.element.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/components/user-avatar/user-avatar.element.ts index b146e43a0f..e36bf586a7 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/components/user-avatar/user-avatar.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/components/user-avatar/user-avatar.element.ts @@ -119,6 +119,7 @@ export class UmbUserAvatarElement extends UmbLitElement { uui-avatar { background-color: transparent; border: 1.5px solid var(--uui-color-divider-standalone); + color: inherit; } uui-avatar.has-image { From 319c2511b677c730278190255b7eb7b9b47662b4 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Mon, 9 Sep 2024 16:53:36 +0200 Subject: [PATCH 080/107] Update types.ts --- src/Umbraco.Web.UI.Client/src/packages/user/user/types.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/types.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/types.ts index 4c3b9f9935..cbb8fe2fe2 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/types.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/types.ts @@ -1,11 +1,11 @@ import type { UmbUserEntityType } from './entity.js'; +import type { UmbUserKindType } from './utils/index.js'; import type { UmbReferenceByUnique } from '@umbraco-cms/backoffice/models'; import { type UserConfigurationResponseModel, UserStateModel, type UserTwoFactorProviderModel, } from '@umbraco-cms/backoffice/external/backend-api'; -import { UmbUserKindType } from './utils/index.js'; export type UmbUserStateEnum = UserStateModel; export const UmbUserStateEnum = UserStateModel; From 2b79836ad6a2907fbfb6ed753fcd084a1164cb4a Mon Sep 17 00:00:00 2001 From: Jacob Overgaard <752371+iOvergaard@users.noreply.github.com> Date: Mon, 9 Sep 2024 17:52:00 +0200 Subject: [PATCH 081/107] feat: add new sysinfo package --- src/Umbraco.Web.UI.Client/package.json | 1 + .../sysinfo/components/sysinfo.element.ts | 149 ++++++++++++++++++ .../src/packages/sysinfo/index.ts | 1 + .../src/packages/sysinfo/manifests.ts | 12 ++ .../src/packages/sysinfo/modals/index.ts | 1 + .../sysinfo/modals/sysinfo-modal.token.ts | 9 ++ .../src/packages/sysinfo/package.json | 8 + .../sysinfo/repository/sysinfo.repository.ts | 20 +++ .../src/packages/sysinfo/umbraco-package.ts | 10 ++ .../src/packages/sysinfo/vite.config.ts | 12 ++ src/Umbraco.Web.UI.Client/tsconfig.json | 1 + 11 files changed, 224 insertions(+) create mode 100644 src/Umbraco.Web.UI.Client/src/packages/sysinfo/components/sysinfo.element.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/sysinfo/index.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/sysinfo/manifests.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/sysinfo/modals/index.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/sysinfo/modals/sysinfo-modal.token.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/sysinfo/package.json create mode 100644 src/Umbraco.Web.UI.Client/src/packages/sysinfo/repository/sysinfo.repository.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/sysinfo/umbraco-package.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/sysinfo/vite.config.ts diff --git a/src/Umbraco.Web.UI.Client/package.json b/src/Umbraco.Web.UI.Client/package.json index 0d7af660b1..ac79713592 100644 --- a/src/Umbraco.Web.UI.Client/package.json +++ b/src/Umbraco.Web.UI.Client/package.json @@ -83,6 +83,7 @@ "./store": "./dist-cms/packages/core/store/index.js", "./style": "./dist-cms/packages/core/style/index.js", "./stylesheet": "./dist-cms/packages/templating/stylesheets/index.js", + "./sysinfo": "./dist-cms/packages/sysinfo/index.js", "./tags": "./dist-cms/packages/tags/index.js", "./template": "./dist-cms/packages/templating/templates/index.js", "./temporary-file": "./dist-cms/packages/core/temporary-file/index.js", diff --git a/src/Umbraco.Web.UI.Client/src/packages/sysinfo/components/sysinfo.element.ts b/src/Umbraco.Web.UI.Client/src/packages/sysinfo/components/sysinfo.element.ts new file mode 100644 index 0000000000..df42673db5 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/sysinfo/components/sysinfo.element.ts @@ -0,0 +1,149 @@ +import { css, customElement, html, state, when } from '@umbraco-cms/backoffice/external/lit'; +import { UmbSysinfoRepository } from '../repository/sysinfo.repository'; +import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; +import { UmbModalBaseElement } from '@umbraco-cms/backoffice/modal'; +import { UMB_NOTIFICATION_CONTEXT } from '@umbraco-cms/backoffice/notification'; + +type ServerKeyValue = { + name: string; + data: string; +}; + +@customElement('umb-sysinfo') +export class UmbSysinfoElement extends UmbModalBaseElement { + @state() + private _serverKeyValues: Array = []; + + @state() + private _loading = false; + + #sysinfoRepository = new UmbSysinfoRepository(this); + #notificationContext?: typeof UMB_NOTIFICATION_CONTEXT.TYPE; + + constructor() { + super(); + + this.consumeContext(UMB_NOTIFICATION_CONTEXT, (context) => { + this.#notificationContext = context; + }); + + this.#populate(); + } + + async #populate() { + this._loading = true; + this._serverKeyValues = []; + + const [serverTroubleshooting, serverInformation] = await Promise.all([ + this.#sysinfoRepository.requestTroubleShooting(), + this.#sysinfoRepository.requestServerInformation(), + ]); + + if (serverTroubleshooting) { + this._serverKeyValues = [...this._serverKeyValues, ...serverTroubleshooting.items]; + } + + if (serverInformation) { + this._serverKeyValues.push({ name: 'Umbraco build version', data: serverInformation.version }); + this._serverKeyValues.push({ name: 'Server time offset', data: serverInformation.baseUtcOffset }); + this._serverKeyValues.push({ name: 'Runtime mode', data: serverInformation.runtimeMode }); + } + + this._loading = false; + } + + #renderServerKeyValues() { + return this._serverKeyValues.map((serverKeyValue) => { + return html` + + ${serverKeyValue.name} + ${serverKeyValue.data} + + `; + }); + } + + override render() { + return html` + + + ${when( + this._loading, + () => html``, + () => html` + + + + + + + Name + Data + + + ${this.#renderServerKeyValues()} + + + `, + )} + + + + + + + `; + } + + #copyToClipboard() { + try { + const text = ` +Umbraco system information\n +--------------------------------\n +${this._serverKeyValues.map((serverKeyValue) => `${serverKeyValue.name}: ${serverKeyValue.data}`).join('\n')}`; + navigator.clipboard.writeText(text); + + this.#notificationContext?.peek('positive', { + data: { + headline: 'System information', + message: this.localize.term('speechBubbles_copySuccessMessage'), + }, + }); + } catch { + this.#notificationContext?.peek('danger', { + data: { + headline: 'System information', + message: this.localize.term('speechBubbles_cannotCopyInformation'), + }, + }); + } + } + + static override styles = [ + UmbTextStyles, + css` + #sysinfo-table { + --uui-box-default-padding: 0; + width: 100%; + max-height: 300px; + overflow: auto; + } + `, + ]; +} + +export default UmbSysinfoElement; + +declare global { + interface HTMLElementTagNameMap { + 'umb-sysinfo': UmbSysinfoElement; + } +} diff --git a/src/Umbraco.Web.UI.Client/src/packages/sysinfo/index.ts b/src/Umbraco.Web.UI.Client/src/packages/sysinfo/index.ts new file mode 100644 index 0000000000..9e897c4aa4 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/sysinfo/index.ts @@ -0,0 +1 @@ +export * from './modals/index.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/sysinfo/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/sysinfo/manifests.ts new file mode 100644 index 0000000000..fa57d5b840 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/sysinfo/manifests.ts @@ -0,0 +1,12 @@ +import type { ManifestModal, ManifestTypes } from '@umbraco-cms/backoffice/extension-registry'; + +export const UMB_SYSINFO_MODAL_ALIAS = 'Umb.Modal.Sysinfo'; + +const modalManifest: ManifestModal = { + type: 'modal', + alias: UMB_SYSINFO_MODAL_ALIAS, + name: 'Sysinfo Modal', + js: () => import('./components/sysinfo.element.js'), +}; + +export const manifests: Array = [modalManifest]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/sysinfo/modals/index.ts b/src/Umbraco.Web.UI.Client/src/packages/sysinfo/modals/index.ts new file mode 100644 index 0000000000..575d63fbd5 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/sysinfo/modals/index.ts @@ -0,0 +1 @@ +export * from './sysinfo-modal.token.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/sysinfo/modals/sysinfo-modal.token.ts b/src/Umbraco.Web.UI.Client/src/packages/sysinfo/modals/sysinfo-modal.token.ts new file mode 100644 index 0000000000..d68114a4e3 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/sysinfo/modals/sysinfo-modal.token.ts @@ -0,0 +1,9 @@ +import { UmbModalToken } from '@umbraco-cms/backoffice/modal'; +import { UMB_SYSINFO_MODAL_ALIAS } from '../manifests.js'; + +export const UMB_SYSINFO_MODAL = new UmbModalToken(UMB_SYSINFO_MODAL_ALIAS, { + modal: { + type: 'dialog', + size: 'medium', + }, +}); diff --git a/src/Umbraco.Web.UI.Client/src/packages/sysinfo/package.json b/src/Umbraco.Web.UI.Client/src/packages/sysinfo/package.json new file mode 100644 index 0000000000..560e33a11f --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/sysinfo/package.json @@ -0,0 +1,8 @@ +{ + "name": "@umbraco-backoffice/sysinfo", + "private": true, + "type": "module", + "scripts": { + "build": "vite build" + } +} diff --git a/src/Umbraco.Web.UI.Client/src/packages/sysinfo/repository/sysinfo.repository.ts b/src/Umbraco.Web.UI.Client/src/packages/sysinfo/repository/sysinfo.repository.ts new file mode 100644 index 0000000000..39ea64fbe9 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/sysinfo/repository/sysinfo.repository.ts @@ -0,0 +1,20 @@ +import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; +import { UmbRepositoryBase } from '@umbraco-cms/backoffice/repository'; +import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources'; +import { ServerService } from '@umbraco-cms/backoffice/external/backend-api'; + +export class UmbSysinfoRepository extends UmbRepositoryBase { + constructor(host: UmbControllerHost) { + super(host, 'Umb.Repository.Sysinfo'); + } + + async requestTroubleShooting() { + const { data } = await tryExecuteAndNotify(this, ServerService.getServerTroubleshooting()); + return data; + } + + async requestServerInformation() { + const { data } = await tryExecuteAndNotify(this, ServerService.getServerInformation()); + return data; + } +} diff --git a/src/Umbraco.Web.UI.Client/src/packages/sysinfo/umbraco-package.ts b/src/Umbraco.Web.UI.Client/src/packages/sysinfo/umbraco-package.ts new file mode 100644 index 0000000000..0e9273dec4 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/sysinfo/umbraco-package.ts @@ -0,0 +1,10 @@ +export const name = 'Umbraco.Core.Sysinfo'; +export const version = '0.0.1'; +export const extensions = [ + { + name: 'Sysinfo Bundle', + alias: 'Umb.Bundle.Sysinfo', + type: 'bundle', + js: () => import('./manifests.js'), + }, +]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/sysinfo/vite.config.ts b/src/Umbraco.Web.UI.Client/src/packages/sysinfo/vite.config.ts new file mode 100644 index 0000000000..6244c942d2 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/sysinfo/vite.config.ts @@ -0,0 +1,12 @@ +import { defineConfig } from 'vite'; +import { rmSync } from 'fs'; +import { getDefaultConfig } from '../../vite-config-base'; + +const dist = '../../../dist-cms/packages/sysinfo'; + +// delete the unbundled dist folder +rmSync(dist, { recursive: true, force: true }); + +export default defineConfig({ + ...getDefaultConfig({ dist }), +}); diff --git a/src/Umbraco.Web.UI.Client/tsconfig.json b/src/Umbraco.Web.UI.Client/tsconfig.json index 13058d558f..1d69cbe783 100644 --- a/src/Umbraco.Web.UI.Client/tsconfig.json +++ b/src/Umbraco.Web.UI.Client/tsconfig.json @@ -109,6 +109,7 @@ DON'T EDIT THIS FILE DIRECTLY. It is generated by /devops/tsconfig/index.js "@umbraco-cms/backoffice/store": ["./src/packages/core/store/index.ts"], "@umbraco-cms/backoffice/style": ["./src/packages/core/style/index.ts"], "@umbraco-cms/backoffice/stylesheet": ["./src/packages/templating/stylesheets/index.ts"], + "@umbraco-cms/backoffice/sysinfo": ["./src/packages/sysinfo/index.ts"], "@umbraco-cms/backoffice/tags": ["./src/packages/tags/index.ts"], "@umbraco-cms/backoffice/template": ["./src/packages/templating/templates/index.ts"], "@umbraco-cms/backoffice/temporary-file": ["./src/packages/core/temporary-file/index.ts"], From 11051e29fe79d793445ac8742b0e4114ea153289 Mon Sep 17 00:00:00 2001 From: Jacob Overgaard <752371+iOvergaard@users.noreply.github.com> Date: Mon, 9 Sep 2024 17:59:06 +0200 Subject: [PATCH 082/107] feat: add localization --- src/Umbraco.Web.UI.Client/src/assets/lang/da-dk.ts | 1 + src/Umbraco.Web.UI.Client/src/assets/lang/de-de.ts | 8 ++++++++ src/Umbraco.Web.UI.Client/src/assets/lang/en-us.ts | 1 + src/Umbraco.Web.UI.Client/src/assets/lang/en.ts | 1 + 4 files changed, 11 insertions(+) diff --git a/src/Umbraco.Web.UI.Client/src/assets/lang/da-dk.ts b/src/Umbraco.Web.UI.Client/src/assets/lang/da-dk.ts index 29ba011438..0250bfb286 100644 --- a/src/Umbraco.Web.UI.Client/src/assets/lang/da-dk.ts +++ b/src/Umbraco.Web.UI.Client/src/assets/lang/da-dk.ts @@ -2223,6 +2223,7 @@ export default { labelForArrayOfItems: 'Samling af %0%', labelForRemoveAllEntries: 'Fjern alle elementer', labelForClearClipboard: 'Ryd udklipsholder', + labelForCopyToClipboard: 'Kopier til udklipsholder', }, propertyActions: { tooltipForPropertyActionsMenu: 'Åben egenskabshandlinger', diff --git a/src/Umbraco.Web.UI.Client/src/assets/lang/de-de.ts b/src/Umbraco.Web.UI.Client/src/assets/lang/de-de.ts index 50fbf86afe..98b445f5a6 100644 --- a/src/Umbraco.Web.UI.Client/src/assets/lang/de-de.ts +++ b/src/Umbraco.Web.UI.Client/src/assets/lang/de-de.ts @@ -1967,6 +1967,14 @@ export default { selectAllLogLevelFilters: 'Wählen Sie Alle', deselectAllLogLevelFilters: 'Alle abwählen', }, + clipboard: { + labelForCopyAllEntries: '%0% kopieren', + labelForArrayOfItemsFrom: '%0% von %1%', + labelForArrayOfItems: 'Sammlung von %0%', + labelForRemoveAllEntries: 'Alle Elemente entfernen', + labelForClearClipboard: 'Zwischenablage löschen', + labelForCopyToClipboard: 'Kopieren in Zwischenablage', + }, formsDashboard: { formsHeadline: 'Umbraco Forms', formsDescription: diff --git a/src/Umbraco.Web.UI.Client/src/assets/lang/en-us.ts b/src/Umbraco.Web.UI.Client/src/assets/lang/en-us.ts index a212371ec1..26331a339d 100644 --- a/src/Umbraco.Web.UI.Client/src/assets/lang/en-us.ts +++ b/src/Umbraco.Web.UI.Client/src/assets/lang/en-us.ts @@ -2288,6 +2288,7 @@ export default { labelForArrayOfItems: 'Collection of %0%', labelForRemoveAllEntries: 'Remove all items', labelForClearClipboard: 'Clear clipboard', + labelForCopyToClipboard: 'Copy to clipboard', }, propertyActions: { tooltipForPropertyActionsMenu: 'Open Property Actions', diff --git a/src/Umbraco.Web.UI.Client/src/assets/lang/en.ts b/src/Umbraco.Web.UI.Client/src/assets/lang/en.ts index 551e778e96..532405afd9 100644 --- a/src/Umbraco.Web.UI.Client/src/assets/lang/en.ts +++ b/src/Umbraco.Web.UI.Client/src/assets/lang/en.ts @@ -2354,6 +2354,7 @@ export default { labelForArrayOfItems: 'Collection of %0%', labelForRemoveAllEntries: 'Remove all items', labelForClearClipboard: 'Clear clipboard', + labelForCopyToClipboard: 'Copy to clipboard', }, propertyActions: { tooltipForPropertyActionsMenu: 'Open Property Actions', From 92cc3b685eec5a5c657dc1c73af632e5fd03ea6e Mon Sep 17 00:00:00 2001 From: Jacob Overgaard <752371+iOvergaard@users.noreply.github.com> Date: Mon, 9 Sep 2024 17:59:16 +0200 Subject: [PATCH 083/107] feat: load the sysinfo package --- .../src/apps/backoffice/backoffice.element.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Umbraco.Web.UI.Client/src/apps/backoffice/backoffice.element.ts b/src/Umbraco.Web.UI.Client/src/apps/backoffice/backoffice.element.ts index d59e98126c..144e8eda69 100644 --- a/src/Umbraco.Web.UI.Client/src/apps/backoffice/backoffice.element.ts +++ b/src/Umbraco.Web.UI.Client/src/apps/backoffice/backoffice.element.ts @@ -33,6 +33,7 @@ const CORE_PACKAGES = [ import('../../packages/search/umbraco-package.js'), import('../../packages/settings/umbraco-package.js'), import('../../packages/static-file/umbraco-package.js'), + import('../../packages/sysinfo/umbraco-package.js'), import('../../packages/tags/umbraco-package.js'), import('../../packages/telemetry/umbraco-package.js'), import('../../packages/templating/umbraco-package.js'), From 0c801a40b9fa4a2916d31855a9044f5c1f039bd9 Mon Sep 17 00:00:00 2001 From: Jacob Overgaard <752371+iOvergaard@users.noreply.github.com> Date: Mon, 9 Sep 2024 17:59:37 +0200 Subject: [PATCH 084/107] fix: ensure the currentUser observable filters away undefined values so you can use firstValueFrom --- .../src/packages/user/current-user/current-user.context.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/current-user/current-user.context.ts b/src/Umbraco.Web.UI.Client/src/packages/user/current-user/current-user.context.ts index 6849d0c64e..b6836e70b7 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/current-user/current-user.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/current-user/current-user.context.ts @@ -3,7 +3,7 @@ import { UmbCurrentUserRepository } from './repository/index.js'; import { UMB_CURRENT_USER_CONTEXT } from './current-user.context.token.js'; import { UmbContextBase } from '@umbraco-cms/backoffice/class-api'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; -import { firstValueFrom } from '@umbraco-cms/backoffice/external/rxjs'; +import { filter, firstValueFrom } from '@umbraco-cms/backoffice/external/rxjs'; import { UMB_AUTH_CONTEXT } from '@umbraco-cms/backoffice/auth'; import { UmbObjectState } from '@umbraco-cms/backoffice/observable-api'; import { umbLocalizationRegistry } from '@umbraco-cms/backoffice/localization'; @@ -14,7 +14,7 @@ import { ensurePathEndsWithSlash } from '@umbraco-cms/backoffice/utils'; export class UmbCurrentUserContext extends UmbContextBase { #currentUser = new UmbObjectState(undefined); - readonly currentUser = this.#currentUser.asObservable(); + readonly currentUser = this.#currentUser.asObservable().pipe(filter((user) => !!user)); readonly allowedSections = this.#currentUser.asObservablePart((user) => user?.allowedSections); readonly avatarUrls = this.#currentUser.asObservablePart((user) => user?.avatarUrls); readonly documentStartNodeUniques = this.#currentUser.asObservablePart((user) => user?.documentStartNodeUniques); From 611f02bc966486d3f55960d822115637ca40cce8 Mon Sep 17 00:00:00 2001 From: Jacob Overgaard <752371+iOvergaard@users.noreply.github.com> Date: Mon, 9 Sep 2024 18:01:02 +0200 Subject: [PATCH 085/107] feat: show a System information button in the logo popover if the user is an admin --- .../backoffice-header-logo.element.ts | 34 ++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/apps/backoffice/components/backoffice-header-logo.element.ts b/src/Umbraco.Web.UI.Client/src/apps/backoffice/components/backoffice-header-logo.element.ts index e7f82483b0..48a93afc79 100644 --- a/src/Umbraco.Web.UI.Client/src/apps/backoffice/components/backoffice-header-logo.element.ts +++ b/src/Umbraco.Web.UI.Client/src/apps/backoffice/components/backoffice-header-logo.element.ts @@ -1,13 +1,19 @@ +import { isCurrentUserAnAdmin } from '@umbraco-cms/backoffice/current-user'; import { UMB_BACKOFFICE_CONTEXT } from '../backoffice.context.js'; import { css, html, customElement, state } from '@umbraco-cms/backoffice/external/lit'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; +import { UMB_MODAL_MANAGER_CONTEXT } from '@umbraco-cms/backoffice/modal'; +import { UMB_SYSINFO_MODAL } from '@umbraco-cms/backoffice/sysinfo'; @customElement('umb-backoffice-header-logo') export class UmbBackofficeHeaderLogoElement extends UmbLitElement { @state() private _version?: string; + @state() + private _isUserAdmin = false; + constructor() { super(); @@ -21,6 +27,12 @@ export class UmbBackofficeHeaderLogoElement extends UmbLitElement { '_observeVersion', ); }); + + this.#isAdmin(); + } + + async #isAdmin() { + this._isUserAdmin = await isCurrentUserAnAdmin(this); } override render() { @@ -31,15 +43,35 @@ export class UmbBackofficeHeaderLogoElement extends UmbLitElement { `; } + async #openSystemInformation() { + const modalManager = await this.getContext(UMB_MODAL_MANAGER_CONTEXT); + modalManager + .open(this, UMB_SYSINFO_MODAL) + .onSubmit() + .catch(() => {}); + } + static override styles = [ UmbTextStyles, css` From 3c23ffd531a529d4096ba183430a5f7cc2d22345 Mon Sep 17 00:00:00 2001 From: Jacob Overgaard <752371+iOvergaard@users.noreply.github.com> Date: Mon, 9 Sep 2024 18:08:46 +0200 Subject: [PATCH 086/107] chore: add 'readonly' to styles property --- .../src/packages/sysinfo/components/sysinfo.element.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/sysinfo/components/sysinfo.element.ts b/src/Umbraco.Web.UI.Client/src/packages/sysinfo/components/sysinfo.element.ts index df42673db5..47f4b24c34 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/sysinfo/components/sysinfo.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/sysinfo/components/sysinfo.element.ts @@ -127,7 +127,7 @@ ${this._serverKeyValues.map((serverKeyValue) => `${serverKeyValue.name}: ${serve } } - static override styles = [ + static override readonly styles = [ UmbTextStyles, css` #sysinfo-table { From 29293edb4e42d1f1aba5adf9bade6bd2aa262ba0 Mon Sep 17 00:00:00 2001 From: Jacob Overgaard <752371+iOvergaard@users.noreply.github.com> Date: Mon, 9 Sep 2024 18:10:40 +0200 Subject: [PATCH 087/107] chore: avoid nesting template literals --- .../src/packages/sysinfo/components/sysinfo.element.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/sysinfo/components/sysinfo.element.ts b/src/Umbraco.Web.UI.Client/src/packages/sysinfo/components/sysinfo.element.ts index 47f4b24c34..929ffba7a1 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/sysinfo/components/sysinfo.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/sysinfo/components/sysinfo.element.ts @@ -105,10 +105,13 @@ export class UmbSysinfoElement extends UmbModalBaseElement { #copyToClipboard() { try { + const serverKeyValues = this._serverKeyValues + .map((serverKeyValue) => `${serverKeyValue.name}: ${serverKeyValue.data}`) + .join('\n'); const text = ` Umbraco system information\n --------------------------------\n -${this._serverKeyValues.map((serverKeyValue) => `${serverKeyValue.name}: ${serverKeyValue.data}`).join('\n')}`; +${serverKeyValues}`; navigator.clipboard.writeText(text); this.#notificationContext?.peek('positive', { From a6236313c96b2d76f364f658d7aee12d3c737643 Mon Sep 17 00:00:00 2001 From: Jacob Overgaard <752371+iOvergaard@users.noreply.github.com> Date: Mon, 9 Sep 2024 18:15:11 +0200 Subject: [PATCH 088/107] feat: add handler for troubleshooting --- .../src/mocks/browser-handlers.ts | 2 +- .../src/mocks/e2e-handlers.ts | 2 +- .../src/mocks/handlers/server.handlers.ts | 45 +++++++++++++------ 3 files changed, 34 insertions(+), 15 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/mocks/browser-handlers.ts b/src/Umbraco.Web.UI.Client/src/mocks/browser-handlers.ts index a525c153fa..c8847d1eef 100644 --- a/src/Umbraco.Web.UI.Client/src/mocks/browser-handlers.ts +++ b/src/Umbraco.Web.UI.Client/src/mocks/browser-handlers.ts @@ -72,7 +72,7 @@ const handlers = [ ...userGroupsHandlers, ...userHandlers, ...documentBlueprintHandlers, - serverHandlers.serverInformationHandler, + ...serverHandlers.serverInformationHandlers, ]; switch (import.meta.env.VITE_UMBRACO_INSTALL_STATUS) { diff --git a/src/Umbraco.Web.UI.Client/src/mocks/e2e-handlers.ts b/src/Umbraco.Web.UI.Client/src/mocks/e2e-handlers.ts index ab07ff2cc9..d63d6112b5 100644 --- a/src/Umbraco.Web.UI.Client/src/mocks/e2e-handlers.ts +++ b/src/Umbraco.Web.UI.Client/src/mocks/e2e-handlers.ts @@ -18,7 +18,7 @@ import { handlers as configHandlers } from './handlers/config.handlers.js'; export const handlers = [ serverHandlers.serverRunningHandler, - serverHandlers.serverInformationHandler, + ...serverHandlers.serverInformationHandlers, ...manifestsHandlers.manifestEmptyHandlers, ...installHandlers, ...upgradeHandlers, diff --git a/src/Umbraco.Web.UI.Client/src/mocks/handlers/server.handlers.ts b/src/Umbraco.Web.UI.Client/src/mocks/handlers/server.handlers.ts index 2be9975a71..0c40929f7b 100644 --- a/src/Umbraco.Web.UI.Client/src/mocks/handlers/server.handlers.ts +++ b/src/Umbraco.Web.UI.Client/src/mocks/handlers/server.handlers.ts @@ -3,7 +3,11 @@ import type { ServerStatusResponseModel, ServerInformationResponseModel, } from '@umbraco-cms/backoffice/external/backend-api'; -import { RuntimeLevelModel, RuntimeModeModel } from '@umbraco-cms/backoffice/external/backend-api'; +import { + RuntimeLevelModel, + RuntimeModeModel, + ServerTroubleshootingResponseModel, +} from '@umbraco-cms/backoffice/external/backend-api'; import { umbracoPath } from '@umbraco-cms/backoffice/utils'; export const serverRunningHandler = rest.get(umbracoPath('/server/status'), (_req, res, ctx) => { @@ -36,15 +40,30 @@ export const serverMustUpgradeHandler = rest.get(umbracoPath('/server/status'), ); }); -export const serverInformationHandler = rest.get(umbracoPath('/server/information'), (_req, res, ctx) => { - return res( - // Respond with a 200 status code - ctx.status(200), - ctx.json({ - version: '14.0.0-preview004', - assemblyVersion: '14.0.0-preview004', - baseUtcOffset: '01:00:00', - runtimeMode: RuntimeModeModel.BACKOFFICE_DEVELOPMENT, - }), - ); -}); +export const serverInformationHandlers = [ + rest.get(umbracoPath('/server/information'), (_req, res, ctx) => { + return res( + // Respond with a 200 status code + ctx.status(200), + ctx.json({ + version: '14.0.0-preview004', + assemblyVersion: '14.0.0-preview004', + baseUtcOffset: '01:00:00', + runtimeMode: RuntimeModeModel.BACKOFFICE_DEVELOPMENT, + }), + ); + }), + rest.get(umbracoPath('/server/troubleshooting'), (_req, res, ctx) => { + return res( + // Respond with a 200 status code + ctx.status(200), + ctx.json({ + items: [ + { name: 'Umbraco base url', data: location.origin }, + { name: 'Mocked server', data: 'true' }, + { name: 'Umbraco version', data: '14.0.0-preview004' }, + ], + }), + ); + }), +]; From c0ca65a05d5d1e956bb3588cf551f0ed7d136f6f Mon Sep 17 00:00:00 2001 From: Jacob Overgaard <752371+iOvergaard@users.noreply.github.com> Date: Mon, 9 Sep 2024 18:21:55 +0200 Subject: [PATCH 089/107] feat: add relevant browser information --- .../src/packages/sysinfo/components/sysinfo.element.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/Umbraco.Web.UI.Client/src/packages/sysinfo/components/sysinfo.element.ts b/src/Umbraco.Web.UI.Client/src/packages/sysinfo/components/sysinfo.element.ts index 929ffba7a1..c49214014c 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/sysinfo/components/sysinfo.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/sysinfo/components/sysinfo.element.ts @@ -49,6 +49,11 @@ export class UmbSysinfoElement extends UmbModalBaseElement { this._serverKeyValues.push({ name: 'Runtime mode', data: serverInformation.runtimeMode }); } + // Browser information + this._serverKeyValues.push({ name: 'Browser (user agent)', data: navigator.userAgent }); + this._serverKeyValues.push({ name: 'Browser language', data: navigator.language }); + this._serverKeyValues.push({ name: 'Browser location', data: location.href }); + this._loading = false; } From e7261efce9d10938c688cbc7db56dd1a436140c6 Mon Sep 17 00:00:00 2001 From: Jacob Overgaard <752371+iOvergaard@users.noreply.github.com> Date: Mon, 9 Sep 2024 18:22:05 +0200 Subject: [PATCH 090/107] feat: ensure data can stay within the cell --- .../src/packages/sysinfo/components/sysinfo.element.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/sysinfo/components/sysinfo.element.ts b/src/Umbraco.Web.UI.Client/src/packages/sysinfo/components/sysinfo.element.ts index c49214014c..f992595d49 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/sysinfo/components/sysinfo.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/sysinfo/components/sysinfo.element.ts @@ -62,7 +62,7 @@ export class UmbSysinfoElement extends UmbModalBaseElement { return html` ${serverKeyValue.name} - ${serverKeyValue.data} + ${serverKeyValue.data} `; }); @@ -144,6 +144,10 @@ ${serverKeyValues}`; max-height: 300px; overflow: auto; } + + .data-cell { + word-break: break-word; + } `, ]; } From 9be5bdd550f75c12d0ac051e3be3c676453d7c82 Mon Sep 17 00:00:00 2001 From: Jacob Overgaard <752371+iOvergaard@users.noreply.github.com> Date: Mon, 9 Sep 2024 18:24:17 +0200 Subject: [PATCH 091/107] fix: import from .js extension --- .../src/packages/sysinfo/components/sysinfo.element.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/sysinfo/components/sysinfo.element.ts b/src/Umbraco.Web.UI.Client/src/packages/sysinfo/components/sysinfo.element.ts index f992595d49..e853bdf750 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/sysinfo/components/sysinfo.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/sysinfo/components/sysinfo.element.ts @@ -1,5 +1,5 @@ import { css, customElement, html, state, when } from '@umbraco-cms/backoffice/external/lit'; -import { UmbSysinfoRepository } from '../repository/sysinfo.repository'; +import { UmbSysinfoRepository } from '../repository/sysinfo.repository.js'; import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; import { UmbModalBaseElement } from '@umbraco-cms/backoffice/modal'; import { UMB_NOTIFICATION_CONTEXT } from '@umbraco-cms/backoffice/notification'; From 3c8ae0ebc49c9d7d4ab28d1382463b4ef5737316 Mon Sep 17 00:00:00 2001 From: Jacob Overgaard <752371+iOvergaard@users.noreply.github.com> Date: Mon, 9 Sep 2024 18:24:24 +0200 Subject: [PATCH 092/107] feat: add all exports --- src/Umbraco.Web.UI.Client/src/packages/sysinfo/index.ts | 2 ++ .../src/packages/sysinfo/repository/index.ts | 1 + 2 files changed, 3 insertions(+) create mode 100644 src/Umbraco.Web.UI.Client/src/packages/sysinfo/repository/index.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/sysinfo/index.ts b/src/Umbraco.Web.UI.Client/src/packages/sysinfo/index.ts index 9e897c4aa4..6196778a18 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/sysinfo/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/sysinfo/index.ts @@ -1 +1,3 @@ +export * from './components/sysinfo.element.js'; export * from './modals/index.js'; +export * from './repository/index.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/sysinfo/repository/index.ts b/src/Umbraco.Web.UI.Client/src/packages/sysinfo/repository/index.ts new file mode 100644 index 0000000000..f13b59d5ac --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/sysinfo/repository/index.ts @@ -0,0 +1 @@ +export * from './sysinfo.repository.js'; From 64f711c9568075a35583f2a5acdb53ba93a2a98d Mon Sep 17 00:00:00 2001 From: Jacob Overgaard <752371+iOvergaard@users.noreply.github.com> Date: Mon, 9 Sep 2024 18:24:50 +0200 Subject: [PATCH 093/107] fix: convert to type import --- src/Umbraco.Web.UI.Client/src/mocks/handlers/server.handlers.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/mocks/handlers/server.handlers.ts b/src/Umbraco.Web.UI.Client/src/mocks/handlers/server.handlers.ts index 0c40929f7b..56455b1eb7 100644 --- a/src/Umbraco.Web.UI.Client/src/mocks/handlers/server.handlers.ts +++ b/src/Umbraco.Web.UI.Client/src/mocks/handlers/server.handlers.ts @@ -6,7 +6,7 @@ import type { import { RuntimeLevelModel, RuntimeModeModel, - ServerTroubleshootingResponseModel, + type ServerTroubleshootingResponseModel, } from '@umbraco-cms/backoffice/external/backend-api'; import { umbracoPath } from '@umbraco-cms/backoffice/utils'; From dbabe069e8dc18037d70a2a84cb7185f769294aa Mon Sep 17 00:00:00 2001 From: Jacob Overgaard <752371+iOvergaard@users.noreply.github.com> Date: Tue, 10 Sep 2024 09:34:38 +0200 Subject: [PATCH 094/107] chore: combine import statements --- .../src/mocks/handlers/server.handlers.ts | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/mocks/handlers/server.handlers.ts b/src/Umbraco.Web.UI.Client/src/mocks/handlers/server.handlers.ts index 56455b1eb7..6d4d62c268 100644 --- a/src/Umbraco.Web.UI.Client/src/mocks/handlers/server.handlers.ts +++ b/src/Umbraco.Web.UI.Client/src/mocks/handlers/server.handlers.ts @@ -1,12 +1,10 @@ const { rest } = window.MockServiceWorker; -import type { - ServerStatusResponseModel, - ServerInformationResponseModel, -} from '@umbraco-cms/backoffice/external/backend-api'; import { + type ServerStatusResponseModel, + type ServerInformationResponseModel, + type ServerTroubleshootingResponseModel, RuntimeLevelModel, RuntimeModeModel, - type ServerTroubleshootingResponseModel, } from '@umbraco-cms/backoffice/external/backend-api'; import { umbracoPath } from '@umbraco-cms/backoffice/utils'; From 5af10642449ce3178997d0d909ce8eb7094f6ce0 Mon Sep 17 00:00:00 2001 From: Jacob Overgaard <752371+iOvergaard@users.noreply.github.com> Date: Tue, 10 Sep 2024 10:04:22 +0200 Subject: [PATCH 095/107] feat: change color and look of buttons --- .../packages/sysinfo/components/sysinfo.element.ts | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/sysinfo/components/sysinfo.element.ts b/src/Umbraco.Web.UI.Client/src/packages/sysinfo/components/sysinfo.element.ts index e853bdf750..cbc092520d 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/sysinfo/components/sysinfo.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/sysinfo/components/sysinfo.element.ts @@ -92,17 +92,18 @@ export class UmbSysinfoElement extends UmbModalBaseElement { `, )} - - + +
`; From 5c5afe2427a090e218d937aaf1bbb3a8a7439384 Mon Sep 17 00:00:00 2001 From: Jacob Overgaard <752371+iOvergaard@users.noreply.github.com> Date: Tue, 10 Sep 2024 10:07:22 +0200 Subject: [PATCH 096/107] feat: use a uui-scroll-container for scroll --- .../sysinfo/components/sysinfo.element.ts | 27 ++++++++++--------- 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/sysinfo/components/sysinfo.element.ts b/src/Umbraco.Web.UI.Client/src/packages/sysinfo/components/sysinfo.element.ts index cbc092520d..6321ed32bb 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/sysinfo/components/sysinfo.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/sysinfo/components/sysinfo.element.ts @@ -77,17 +77,19 @@ export class UmbSysinfoElement extends UmbModalBaseElement { () => html``, () => html` - - - + + + + - - Name - Data - + + Name + Data + - ${this.#renderServerKeyValues()} - + ${this.#renderServerKeyValues()} + + `, )} @@ -139,11 +141,12 @@ ${serverKeyValues}`; static override readonly styles = [ UmbTextStyles, css` + #container { + max-height: 300px; + } + #sysinfo-table { --uui-box-default-padding: 0; - width: 100%; - max-height: 300px; - overflow: auto; } .data-cell { From 1751b127de646415a70d399d01a3e459a53b9d98 Mon Sep 17 00:00:00 2001 From: Jacob Overgaard <752371+iOvergaard@users.noreply.github.com> Date: Tue, 10 Sep 2024 10:10:03 +0200 Subject: [PATCH 097/107] feat: replace the uui-box entirely with a scroll container --- .../sysinfo/components/sysinfo.element.ts | 28 ++++++++----------- 1 file changed, 11 insertions(+), 17 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/sysinfo/components/sysinfo.element.ts b/src/Umbraco.Web.UI.Client/src/packages/sysinfo/components/sysinfo.element.ts index 6321ed32bb..1c8e890e84 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/sysinfo/components/sysinfo.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/sysinfo/components/sysinfo.element.ts @@ -76,21 +76,19 @@ export class UmbSysinfoElement extends UmbModalBaseElement { this._loading, () => html``, () => html` - - - - - + + + + - - Name - Data - + + Name + Data + - ${this.#renderServerKeyValues()} - - - + ${this.#renderServerKeyValues()} + + `, )} @@ -145,10 +143,6 @@ ${serverKeyValues}`; max-height: 300px; } - #sysinfo-table { - --uui-box-default-padding: 0; - } - .data-cell { word-break: break-word; } From 4229f2a2579384d6dbcca4f55565411ad7de8109 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Tue, 10 Sep 2024 10:51:30 +0200 Subject: [PATCH 098/107] style update --- .../user/user/components/user-avatar/user-avatar.element.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/components/user-avatar/user-avatar.element.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/components/user-avatar/user-avatar.element.ts index e36bf586a7..fb144b6a93 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/components/user-avatar/user-avatar.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/components/user-avatar/user-avatar.element.ts @@ -118,7 +118,7 @@ export class UmbUserAvatarElement extends UmbLitElement { css` uui-avatar { background-color: transparent; - border: 1.5px solid var(--uui-color-divider-standalone); + border: 1.5px solid var(--uui-color-border); color: inherit; } @@ -127,7 +127,7 @@ export class UmbUserAvatarElement extends UmbLitElement { } uui-avatar.api { - border-radius: var(--uui-border-radius); + border-radius: 9%; } `, ]; From 0135cfdea03a77f82b955f54894132b500e0a5ff Mon Sep 17 00:00:00 2001 From: Jacob Overgaard <752371+iOvergaard@users.noreply.github.com> Date: Tue, 10 Sep 2024 12:05:10 +0200 Subject: [PATCH 099/107] fix: removed misspelled attribute (button looks better not compact anyway) --- .../packages/core/components/code-block/code-block.element.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/components/code-block/code-block.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/components/code-block/code-block.element.ts index 5bfa206456..fd6f82c071 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/components/code-block/code-block.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/components/code-block/code-block.element.ts @@ -44,7 +44,7 @@ export class UmbCodeBlockElement extends LitElement { ${when( this.copy, () => html` - + ${when( this._copyState === 'idle', () => html` Copy`, From 3b967df4311176b26e84076f373972820e578187 Mon Sep 17 00:00:00 2001 From: Jacob Overgaard <752371+iOvergaard@users.noreply.github.com> Date: Tue, 10 Sep 2024 12:05:34 +0200 Subject: [PATCH 100/107] fix: use `pre-line` over `pre` for pesky whitespaces at the beginning --- .../packages/core/components/code-block/code-block.element.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/components/code-block/code-block.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/components/code-block/code-block.element.ts index fd6f82c071..fdb568d1f6 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/components/code-block/code-block.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/components/code-block/code-block.element.ts @@ -86,7 +86,7 @@ export class UmbCodeBlockElement extends LitElement { pre, code { word-wrap: normal; - white-space: pre; + white-space: pre-line; } #header { From 6ec304282b50722d0dec6165d5f9581f2f52a11f Mon Sep 17 00:00:00 2001 From: Jacob Overgaard <752371+iOvergaard@users.noreply.github.com> Date: Tue, 10 Sep 2024 12:10:12 +0200 Subject: [PATCH 101/107] feat: use the umb-code-block rather than coming up with a new view, but leave the copy functionality in place which allows us to copy as markdown --- .../sysinfo/components/sysinfo.element.ts | 88 +++++++++---------- 1 file changed, 40 insertions(+), 48 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/sysinfo/components/sysinfo.element.ts b/src/Umbraco.Web.UI.Client/src/packages/sysinfo/components/sysinfo.element.ts index 1c8e890e84..41bf9defbd 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/sysinfo/components/sysinfo.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/sysinfo/components/sysinfo.element.ts @@ -1,8 +1,9 @@ -import { css, customElement, html, state, when } from '@umbraco-cms/backoffice/external/lit'; import { UmbSysinfoRepository } from '../repository/sysinfo.repository.js'; +import { css, customElement, html, state, when } from '@umbraco-cms/backoffice/external/lit'; import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; import { UmbModalBaseElement } from '@umbraco-cms/backoffice/modal'; import { UMB_NOTIFICATION_CONTEXT } from '@umbraco-cms/backoffice/notification'; +import type { UUIButtonState } from '@umbraco-cms/backoffice/external/uui'; type ServerKeyValue = { name: string; @@ -12,11 +13,15 @@ type ServerKeyValue = { @customElement('umb-sysinfo') export class UmbSysinfoElement extends UmbModalBaseElement { @state() - private _serverKeyValues: Array = []; + private _systemInformation = ''; @state() private _loading = false; + @state() + private _buttonState?: UUIButtonState; + + #serverKeyValues: Array = []; #sysinfoRepository = new UmbSysinfoRepository(this); #notificationContext?: typeof UMB_NOTIFICATION_CONTEXT.TYPE; @@ -32,7 +37,7 @@ export class UmbSysinfoElement extends UmbModalBaseElement { async #populate() { this._loading = true; - this._serverKeyValues = []; + this.#serverKeyValues = []; const [serverTroubleshooting, serverInformation] = await Promise.all([ this.#sysinfoRepository.requestTroubleShooting(), @@ -40,32 +45,30 @@ export class UmbSysinfoElement extends UmbModalBaseElement { ]); if (serverTroubleshooting) { - this._serverKeyValues = [...this._serverKeyValues, ...serverTroubleshooting.items]; + this.#serverKeyValues = serverTroubleshooting.items; } if (serverInformation) { - this._serverKeyValues.push({ name: 'Umbraco build version', data: serverInformation.version }); - this._serverKeyValues.push({ name: 'Server time offset', data: serverInformation.baseUtcOffset }); - this._serverKeyValues.push({ name: 'Runtime mode', data: serverInformation.runtimeMode }); + this.#serverKeyValues.push({ name: 'Umbraco build version', data: serverInformation.version }); + this.#serverKeyValues.push({ name: 'Server time offset', data: serverInformation.baseUtcOffset }); + this.#serverKeyValues.push({ name: 'Runtime mode', data: serverInformation.runtimeMode }); } // Browser information - this._serverKeyValues.push({ name: 'Browser (user agent)', data: navigator.userAgent }); - this._serverKeyValues.push({ name: 'Browser language', data: navigator.language }); - this._serverKeyValues.push({ name: 'Browser location', data: location.href }); + this.#serverKeyValues.push({ name: 'Browser (user agent)', data: navigator.userAgent }); + this.#serverKeyValues.push({ name: 'Browser language', data: navigator.language }); + this.#serverKeyValues.push({ name: 'Browser location', data: location.href }); + this._systemInformation = this.#renderServerKeyValues(); this._loading = false; } #renderServerKeyValues() { - return this._serverKeyValues.map((serverKeyValue) => { - return html` - - ${serverKeyValue.name} - ${serverKeyValue.data} - - `; - }); + return this.#serverKeyValues + .map((serverKeyValue) => { + return `${serverKeyValue.name}: ${serverKeyValue.data}`; + }) + .join('\n'); } override render() { @@ -75,21 +78,7 @@ export class UmbSysinfoElement extends UmbModalBaseElement { ${when( this._loading, () => html``, - () => html` - - - - - - - Name - Data - - - ${this.#renderServerKeyValues()} - - - `, + () => html` ${this._systemInformation} `, )} `${serverKeyValue.name}: ${serverKeyValue.data}`) - .join('\n'); - const text = ` -Umbraco system information\n ---------------------------------\n -${serverKeyValues}`; - navigator.clipboard.writeText(text); + this._buttonState = 'waiting'; + const text = `Umbraco system information +-------------------------------- +${this._systemInformation}`; + const textAsCode = `\`\`\`\n${text}\n\`\`\`\n`; + await navigator.clipboard.writeText(textAsCode); - this.#notificationContext?.peek('positive', { - data: { - headline: 'System information', - message: this.localize.term('speechBubbles_copySuccessMessage'), - }, - }); + setTimeout(() => { + this.#notificationContext?.peek('positive', { + data: { + headline: 'System information', + message: this.localize.term('speechBubbles_copySuccessMessage'), + }, + }); + this._buttonState = 'success'; + }, 250); } catch { + this._buttonState = 'failed'; this.#notificationContext?.peek('danger', { data: { headline: 'System information', From 4c6cd0d1eadb8bb885637a5537aff642ca83d686 Mon Sep 17 00:00:00 2001 From: Jacob Overgaard <752371+iOvergaard@users.noreply.github.com> Date: Tue, 10 Sep 2024 12:14:52 +0200 Subject: [PATCH 102/107] chore: mark property as readonly (sonarlint) --- .../packages/core/components/code-block/code-block.element.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/components/code-block/code-block.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/components/code-block/code-block.element.ts index fdb568d1f6..7e6a7f87e8 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/components/code-block/code-block.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/components/code-block/code-block.element.ts @@ -58,7 +58,7 @@ export class UmbCodeBlockElement extends LitElement { `; } - static override styles = [ + static override readonly styles = [ UmbTextStyles, css` :host { From ae7a7323577979ee7788e711722ee49b3fb1a89e Mon Sep 17 00:00:00 2001 From: Jacob Overgaard <752371+iOvergaard@users.noreply.github.com> Date: Tue, 10 Sep 2024 12:16:04 +0200 Subject: [PATCH 103/107] docs: use correct jsdocs for @slot --- .../packages/core/components/code-block/code-block.element.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/components/code-block/code-block.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/components/code-block/code-block.element.ts index 7e6a7f87e8..b285a9d1d3 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/components/code-block/code-block.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/components/code-block/code-block.element.ts @@ -5,7 +5,7 @@ import { css, customElement, html, property, state, when, LitElement } from '@um /** * A simple styled box for showing code-based error messages or blocks od code. - * @slot the full message + * @slot - the default slot where the full message resides */ @customElement('umb-code-block') export class UmbCodeBlockElement extends LitElement { From f598dde7c7acd8408a9c9112764bea29cdac860e Mon Sep 17 00:00:00 2001 From: Jacob Overgaard <752371+iOvergaard@users.noreply.github.com> Date: Tue, 10 Sep 2024 12:17:33 +0200 Subject: [PATCH 104/107] feat: add max-height to code-block and cleanup css --- .../src/packages/sysinfo/components/sysinfo.element.ts | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/sysinfo/components/sysinfo.element.ts b/src/Umbraco.Web.UI.Client/src/packages/sysinfo/components/sysinfo.element.ts index 41bf9defbd..c2dc173622 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/sysinfo/components/sysinfo.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/sysinfo/components/sysinfo.element.ts @@ -78,7 +78,7 @@ export class UmbSysinfoElement extends UmbModalBaseElement { ${when( this._loading, () => html``, - () => html` ${this._systemInformation} `, + () => html` ${this._systemInformation} `, )} Date: Tue, 10 Sep 2024 12:33:45 +0200 Subject: [PATCH 105/107] chore: ensure pipelines run on new dev/* branches --- .../azure-static-web-apps-ambitious-stone-0033b3603.yml | 2 ++ src/Umbraco.Web.UI.Client/.github/workflows/build_test.yml | 2 ++ src/Umbraco.Web.UI.Client/.github/workflows/codeql.yml | 2 ++ 3 files changed, 6 insertions(+) diff --git a/src/Umbraco.Web.UI.Client/.github/workflows/azure-static-web-apps-ambitious-stone-0033b3603.yml b/src/Umbraco.Web.UI.Client/.github/workflows/azure-static-web-apps-ambitious-stone-0033b3603.yml index cce252608c..7b4792766b 100644 --- a/src/Umbraco.Web.UI.Client/.github/workflows/azure-static-web-apps-ambitious-stone-0033b3603.yml +++ b/src/Umbraco.Web.UI.Client/.github/workflows/azure-static-web-apps-ambitious-stone-0033b3603.yml @@ -5,11 +5,13 @@ on: branches: - main - release/* + - dev/* pull_request: types: [opened, synchronize, reopened, closed] branches: - main - release/* + - dev/* workflow_dispatch: inputs: issue_number: diff --git a/src/Umbraco.Web.UI.Client/.github/workflows/build_test.yml b/src/Umbraco.Web.UI.Client/.github/workflows/build_test.yml index b90c5f86d1..4be78a1eb2 100644 --- a/src/Umbraco.Web.UI.Client/.github/workflows/build_test.yml +++ b/src/Umbraco.Web.UI.Client/.github/workflows/build_test.yml @@ -8,10 +8,12 @@ on: branches: - main - release/* + - dev/* pull_request: branches: - main - release/* + - dev/* # Allows GitHub to use this workflow to validate the merge queue merge_group: diff --git a/src/Umbraco.Web.UI.Client/.github/workflows/codeql.yml b/src/Umbraco.Web.UI.Client/.github/workflows/codeql.yml index ac5f4990ff..5d8b9febed 100644 --- a/src/Umbraco.Web.UI.Client/.github/workflows/codeql.yml +++ b/src/Umbraco.Web.UI.Client/.github/workflows/codeql.yml @@ -16,10 +16,12 @@ on: branches: - main - release/* + - dev/* pull_request: branches: - main - release/* + - dev/* schedule: - cron: '33 2 * * 1' From 2c497cd84360f3e22d2c6995bea6ca64b2d354e7 Mon Sep 17 00:00:00 2001 From: Jacob Overgaard <752371+iOvergaard@users.noreply.github.com> Date: Tue, 10 Sep 2024 12:37:08 +0200 Subject: [PATCH 106/107] build: correct the branch pattern for dev branches --- .../azure-static-web-apps-ambitious-stone-0033b3603.yml | 4 ++-- src/Umbraco.Web.UI.Client/.github/workflows/build_test.yml | 4 ++-- src/Umbraco.Web.UI.Client/.github/workflows/codeql.yml | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/.github/workflows/azure-static-web-apps-ambitious-stone-0033b3603.yml b/src/Umbraco.Web.UI.Client/.github/workflows/azure-static-web-apps-ambitious-stone-0033b3603.yml index 7b4792766b..e618f4da80 100644 --- a/src/Umbraco.Web.UI.Client/.github/workflows/azure-static-web-apps-ambitious-stone-0033b3603.yml +++ b/src/Umbraco.Web.UI.Client/.github/workflows/azure-static-web-apps-ambitious-stone-0033b3603.yml @@ -5,13 +5,13 @@ on: branches: - main - release/* - - dev/* + - v*/dev pull_request: types: [opened, synchronize, reopened, closed] branches: - main - release/* - - dev/* + - v*/dev workflow_dispatch: inputs: issue_number: diff --git a/src/Umbraco.Web.UI.Client/.github/workflows/build_test.yml b/src/Umbraco.Web.UI.Client/.github/workflows/build_test.yml index 4be78a1eb2..8e70477ef8 100644 --- a/src/Umbraco.Web.UI.Client/.github/workflows/build_test.yml +++ b/src/Umbraco.Web.UI.Client/.github/workflows/build_test.yml @@ -8,12 +8,12 @@ on: branches: - main - release/* - - dev/* + - v*/dev pull_request: branches: - main - release/* - - dev/* + - v*/dev # Allows GitHub to use this workflow to validate the merge queue merge_group: diff --git a/src/Umbraco.Web.UI.Client/.github/workflows/codeql.yml b/src/Umbraco.Web.UI.Client/.github/workflows/codeql.yml index 5d8b9febed..f3f3a37812 100644 --- a/src/Umbraco.Web.UI.Client/.github/workflows/codeql.yml +++ b/src/Umbraco.Web.UI.Client/.github/workflows/codeql.yml @@ -16,12 +16,12 @@ on: branches: - main - release/* - - dev/* + - v*/dev pull_request: branches: - main - release/* - - dev/* + - v*/dev schedule: - cron: '33 2 * * 1' From 09fabc1c4fd2bd829c8d75128bbc22dab49bdaec Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 10 Sep 2024 12:40:27 +0200 Subject: [PATCH 107/107] fix lint errors --- .../views/info/document-workspace-view-info-history.element.ts | 2 +- .../views/info/media-workspace-view-info-history.element.ts | 2 +- .../user-group/workspace/user-group-workspace-editor.element.ts | 1 - .../user/user/components/user-avatar/user-avatar.element.ts | 1 - .../user/user/workspace/user-workspace-editor.element.ts | 1 - 5 files changed, 2 insertions(+), 5 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/workspace/views/info/document-workspace-view-info-history.element.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/workspace/views/info/document-workspace-view-info-history.element.ts index 9388014614..14802bbeca 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/workspace/views/info/document-workspace-view-info-history.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/workspace/views/info/document-workspace-view-info-history.element.ts @@ -3,7 +3,7 @@ import type { UmbDocumentAuditLogModel } from '../../../audit-log/types.js'; import { UmbDocumentAuditLogRepository } from '../../../audit-log/index.js'; import { UMB_DOCUMENT_WORKSPACE_CONTEXT } from '../../document-workspace.context-token.js'; import { TimeOptions, getDocumentHistoryTagStyleAndText } from './utils.js'; -import { css, html, customElement, state, nothing, repeat, ifDefined } from '@umbraco-cms/backoffice/external/lit'; +import { css, html, customElement, state, nothing, repeat } from '@umbraco-cms/backoffice/external/lit'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; import { UMB_MODAL_MANAGER_CONTEXT } from '@umbraco-cms/backoffice/modal'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media/workspace/views/info/media-workspace-view-info-history.element.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media/workspace/views/info/media-workspace-view-info-history.element.ts index f13d1de9ac..33ac9a609f 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/media/media/workspace/views/info/media-workspace-view-info-history.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/media/media/workspace/views/info/media-workspace-view-info-history.element.ts @@ -2,7 +2,7 @@ import type { UmbMediaAuditLogModel } from '../../../audit-log/types.js'; import { UmbMediaAuditLogRepository } from '../../../audit-log/index.js'; import { UMB_MEDIA_WORKSPACE_CONTEXT } from '../../media-workspace.context-token.js'; import { TimeOptions, getMediaHistoryTagStyleAndText } from './utils.js'; -import { css, html, customElement, state, nothing, repeat, ifDefined } from '@umbraco-cms/backoffice/external/lit'; +import { css, html, customElement, state, nothing, repeat } from '@umbraco-cms/backoffice/external/lit'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; import { UmbPaginationManager } from '@umbraco-cms/backoffice/utils'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user-group/workspace/user-group-workspace-editor.element.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user-group/workspace/user-group-workspace-editor.element.ts index 613d012475..9374872d2a 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user-group/workspace/user-group-workspace-editor.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user-group/workspace/user-group-workspace-editor.element.ts @@ -1,5 +1,4 @@ import type { UmbUserGroupDetailModel } from '../index.js'; -import { UMB_USER_GROUP_ENTITY_TYPE } from '../index.js'; import { UMB_USER_GROUP_WORKSPACE_CONTEXT } from './user-group-workspace.context-token.js'; import type { UUIBooleanInputEvent } from '@umbraco-cms/backoffice/external/uui'; import { css, html, nothing, customElement, state, ifDefined } from '@umbraco-cms/backoffice/external/lit'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/components/user-avatar/user-avatar.element.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/components/user-avatar/user-avatar.element.ts index fb144b6a93..44661991dc 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/components/user-avatar/user-avatar.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/components/user-avatar/user-avatar.element.ts @@ -1,7 +1,6 @@ import type { UmbUserKindType } from '../../utils/index.js'; import { UmbUserKind } from '../../utils/index.js'; import type { UUIAvatarElement } from '@umbraco-cms/backoffice/external/uui'; -import type { PropertyValues } from '@umbraco-cms/backoffice/external/lit'; import { css, html, diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/workspace/user-workspace-editor.element.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/workspace/user-workspace-editor.element.ts index 2526f44b14..c4e11d2175 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/workspace/user-workspace-editor.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/workspace/user-workspace-editor.element.ts @@ -1,5 +1,4 @@ import type { UmbUserDetailModel } from '../index.js'; -import { UMB_USER_ENTITY_TYPE } from '../entity.js'; import type { UmbUserWorkspaceContext } from './user-workspace.context.js'; import { UMB_USER_WORKSPACE_CONTEXT } from './user-workspace.context-token.js'; import type { UUIInputElement } from '@umbraco-cms/backoffice/external/uui';