From bc8c8c12da9514d7085c87bbe14b290a6556ef44 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Fri, 30 Aug 2024 20:36:10 +0200 Subject: [PATCH 001/134] 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/134] 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/134] 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/134] 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/134] 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/134] 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/134] 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/134] 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/134] 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/134] 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/134] 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/134] 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/134] 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/134] 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/134] 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/134] 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/134] 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/134] 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/134] 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/134] 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/134] 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/134] 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/134] 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/134] 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/134] 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/134] 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/134] 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/134] 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/134] 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/134] 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/134] 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/134] 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/134] 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/134] 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/134] 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/134] 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/134] 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/134] 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/134] 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/134] 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/134] 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/134] 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/134] 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/134] 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/134] 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/134] 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/134] 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/134] 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/134] 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/134] 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/134] 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/134] 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/134] 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/134] 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/134] 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/134] 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/134] 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/134] 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/134] 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/134] 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/134] 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/134] 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/134] 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/134] 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/134] 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/134] 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/134] 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/134] 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/134] 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/134] 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/134] 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/134] 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/134] 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/134] 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/134] 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/134] 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/134] 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/134] 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/134] 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/134] 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/134] 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/134] 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/134] 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/134] 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/134] 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/134] 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/134] 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/134] 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/134] 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/134] 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/134] 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/134] 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/134] 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/134] 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/134] 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 22f7b2f8ba6d6426618f921ce6bbbfbf41de1ed3 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 10 Sep 2024 10:04:55 +0200 Subject: [PATCH 096/134] add translations for kind --- src/Umbraco.Web.UI.Client/src/assets/lang/da-dk.ts | 3 +++ src/Umbraco.Web.UI.Client/src/assets/lang/en-us.ts | 3 +++ 2 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 d60320fb16..9e700003cf 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 @@ -357,6 +357,7 @@ export default { member: { createNewMember: 'Opret et nyt medlem', allMembers: 'Alle medlemmer', + kind: 'Slags', memberGroupNoProperties: 'Medlemgrupper har ingen yderligere egenskaber til redigering.', '2fa': 'Totrinsbekræftelse', duplicateMemberLogin: 'A member with this login already exists', @@ -364,6 +365,8 @@ export default { memberHasPassword: 'The member already has a password set', memberLockoutNotEnabled: 'Lockout is not enabled for this member', memberNotInGroup: "The member is not in group '%0%'", + memberKindDefault: 'Bruger', + memberKindApi: 'API Bruger', }, contentType: { copyFailed: 'Kopiering af indholdstypen fejlede', 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..ab6f2027bf 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 @@ -364,12 +364,15 @@ export default { createNewMember: 'Create a new member', allMembers: 'All Members', duplicateMemberLogin: 'A member with this login already exists', + kind: 'Kind', memberGroupNoProperties: 'Member groups have no additional properties for editing.', memberHasGroup: "The member is already in group '%0%'", memberHasPassword: 'The member already has a password set', memberLockoutNotEnabled: 'Lockout is not enabled for this member', memberNotInGroup: "The member is not in group '%0%'", '2fa': 'Two-Factor Authentication', + memberKindDefault: 'Member', + memberKindApi: 'API Member', }, contentType: { copyFailed: 'Failed to copy content type', From f317d011e9cc3a04e1ec5183211dd8143344bf27 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 10 Sep 2024 10:05:04 +0200 Subject: [PATCH 097/134] add kind util --- .../src/packages/members/member/utils/index.ts | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 src/Umbraco.Web.UI.Client/src/packages/members/member/utils/index.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/members/member/utils/index.ts b/src/Umbraco.Web.UI.Client/src/packages/members/member/utils/index.ts new file mode 100644 index 0000000000..9b691b0035 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/members/member/utils/index.ts @@ -0,0 +1,6 @@ +export type UmbMemberKindType = 'Default' | 'Api'; + +export const UmbMemberKind = Object.freeze({ + DEFAULT: 'Default', + API: 'Api', +}); From f971c70285cac3b48ce62e24548e95a98009eb9e Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 10 Sep 2024 10:05:18 +0200 Subject: [PATCH 098/134] add kind to types --- .../src/packages/members/member/collection/types.ts | 2 ++ .../src/packages/members/member/repository/item/types.ts | 2 ++ src/Umbraco.Web.UI.Client/src/packages/members/member/types.ts | 2 ++ 3 files changed, 6 insertions(+) diff --git a/src/Umbraco.Web.UI.Client/src/packages/members/member/collection/types.ts b/src/Umbraco.Web.UI.Client/src/packages/members/member/collection/types.ts index bb3b83cc3b..46b1c95102 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/members/member/collection/types.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/members/member/collection/types.ts @@ -1,4 +1,5 @@ import type { UmbMemberEntityType } from '../entity.js'; +import type { UmbMemberKindType } from '../utils/index.js'; export interface UmbMemberCollectionFilterModel { skip?: number; @@ -11,4 +12,5 @@ export interface UmbMemberCollectionModel { unique: string; entityType: UmbMemberEntityType; variants: Array; + kind: UmbMemberKindType; } diff --git a/src/Umbraco.Web.UI.Client/src/packages/members/member/repository/item/types.ts b/src/Umbraco.Web.UI.Client/src/packages/members/member/repository/item/types.ts index 9b58f77ef6..660b7d84fc 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/members/member/repository/item/types.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/members/member/repository/item/types.ts @@ -1,4 +1,5 @@ import type { UmbMemberEntityType } from '../../entity.js'; +import type { UmbMemberKindType } from '../../utils/index.js'; import type { UmbReferenceByUnique } from '@umbraco-cms/backoffice/models'; export interface UmbMemberItemModel { @@ -11,6 +12,7 @@ export interface UmbMemberItemModel { collection: UmbReferenceByUnique | null; }; variants: Array; + kind: UmbMemberKindType; } export interface UmbMemberVariantItemModel { diff --git a/src/Umbraco.Web.UI.Client/src/packages/members/member/types.ts b/src/Umbraco.Web.UI.Client/src/packages/members/member/types.ts index 0e6c4bfb12..d2c1f1dcaf 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/members/member/types.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/members/member/types.ts @@ -1,4 +1,5 @@ import type { UmbMemberEntityType } from './entity.js'; +import type { UmbMemberKindType } from './utils/index.js'; import type { UmbVariantModel, UmbVariantOptionModel } from '@umbraco-cms/backoffice/variant'; export interface UmbMemberDetailModel { @@ -9,6 +10,7 @@ export interface UmbMemberDetailModel { isApproved: boolean; isLockedOut: boolean; isTwoFactorEnabled: boolean; + kind: UmbMemberKindType; lastLockoutDate: string | null; lastLoginDate: string | null; lastPasswordChangeDate: string | null; From ddc635958d8b19f86663e630cb1b0a5be0a14735 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 10 Sep 2024 10:05:28 +0200 Subject: [PATCH 099/134] map kind --- .../repository/member-collection.server.data-source.ts | 1 + .../repository/detail/member-detail.server.data-source.ts | 3 +++ .../member/repository/item/member-item.server.data-source.ts | 1 + .../members/member/search/member-search.server.data-source.ts | 1 + 4 files changed, 6 insertions(+) diff --git a/src/Umbraco.Web.UI.Client/src/packages/members/member/collection/repository/member-collection.server.data-source.ts b/src/Umbraco.Web.UI.Client/src/packages/members/member/collection/repository/member-collection.server.data-source.ts index 3bfb088260..42376a93c3 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/members/member/collection/repository/member-collection.server.data-source.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/members/member/collection/repository/member-collection.server.data-source.ts @@ -50,6 +50,7 @@ export class UmbMemberCollectionServerDataSource implements UmbCollectionDataSou email: item.email, variants: item.variants as UmbVariantModel[], unique: item.id, + kind: item.kind, lastLoginDate: item.lastLoginDate || null, lastLockoutDate: item.lastLockoutDate || null, lastPasswordChangeDate: item.lastPasswordChangeDate || null, diff --git a/src/Umbraco.Web.UI.Client/src/packages/members/member/repository/detail/member-detail.server.data-source.ts b/src/Umbraco.Web.UI.Client/src/packages/members/member/repository/detail/member-detail.server.data-source.ts index 37303524ae..169e8e65fd 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/members/member/repository/detail/member-detail.server.data-source.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/members/member/repository/detail/member-detail.server.data-source.ts @@ -6,6 +6,7 @@ import type { CreateMemberRequestModel, UpdateMemberRequestModel } from '@umbrac import { MemberService } from '@umbraco-cms/backoffice/external/backend-api'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources'; +import { UmbMemberKind } from '../../utils/index.js'; /** * A data source for the Member that fetches data from the server @@ -42,6 +43,7 @@ export class UmbMemberServerDataSource implements UmbDetailDataSource { entityType: UMB_MEMBER_ENTITY_TYPE, unique: item.id, name: item.variants[0].name || '', + kind: item.kind, memberType: { unique: item.memberType.id, icon: item.memberType.icon, diff --git a/src/Umbraco.Web.UI.Client/src/packages/members/member/search/member-search.server.data-source.ts b/src/Umbraco.Web.UI.Client/src/packages/members/member/search/member-search.server.data-source.ts index 4c8d4acdaf..febcdd024c 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/members/member/search/member-search.server.data-source.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/members/member/search/member-search.server.data-source.ts @@ -43,6 +43,7 @@ export class UmbMemberSearchServerDataSource implements UmbSearchDataSource Date: Tue, 10 Sep 2024 10:06:45 +0200 Subject: [PATCH 100/134] show kind in table --- .../table/member-table-collection-view.element.ts | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/Umbraco.Web.UI.Client/src/packages/members/member/collection/views/table/member-table-collection-view.element.ts b/src/Umbraco.Web.UI.Client/src/packages/members/member/collection/views/table/member-table-collection-view.element.ts index ea755050bc..bc81f76e4e 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/members/member/collection/views/table/member-table-collection-view.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/members/member/collection/views/table/member-table-collection-view.element.ts @@ -1,6 +1,7 @@ import type { UmbMemberCollectionModel } from '../../types.js'; import { UMB_MEMBER_COLLECTION_CONTEXT } from '../../member-collection.context-token.js'; import type { UmbMemberCollectionContext } from '../../member-collection.context.js'; +import { UmbMemberKind } from '../../../utils/index.js'; import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; import type { UmbTableColumn, UmbTableConfig, UmbTableItem } from '@umbraco-cms/backoffice/components'; import { css, html, customElement, state } from '@umbraco-cms/backoffice/external/lit'; @@ -19,6 +20,10 @@ export class UmbMemberTableCollectionViewElement extends UmbLitElement { name: this.localize.term('general_name'), alias: 'memberName', }, + { + name: this.localize.term('member_kind'), + alias: 'memberKind', + }, ]; @state() @@ -44,6 +49,10 @@ export class UmbMemberTableCollectionViewElement extends UmbLitElement { this._tableItems = members.map((member) => { // TODO: get correct variant name const name = member.variants[0].name; + const kind = + member.kind === UmbMemberKind.API + ? this.localize.term('member_memberKindApi') + : this.localize.term('member_memberKindDefault'); return { id: member.unique, @@ -53,6 +62,10 @@ export class UmbMemberTableCollectionViewElement extends UmbLitElement { columnAlias: 'memberName', value: html`${name}`, }, + { + columnAlias: 'memberKind', + value: kind, + }, ], }; }); 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 101/134] 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 102/134] 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 103/134] 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 104/134] 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 105/134] 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 106/134] 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 107/134] 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 108/134] 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 5939b97b295fdba4242471fad54eff96aa140dd3 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 10 Sep 2024 12:16:48 +0200 Subject: [PATCH 109/134] show username and email in table --- .../packages/members/member/collection/types.ts | 11 +++-------- .../member-table-collection-view.element.ts | 17 +++++++++++++++++ 2 files changed, 20 insertions(+), 8 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/members/member/collection/types.ts b/src/Umbraco.Web.UI.Client/src/packages/members/member/collection/types.ts index 46b1c95102..76018d2a04 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/members/member/collection/types.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/members/member/collection/types.ts @@ -1,5 +1,4 @@ -import type { UmbMemberEntityType } from '../entity.js'; -import type { UmbMemberKindType } from '../utils/index.js'; +import type { UmbMemberDetailModel } from '../types.js'; export interface UmbMemberCollectionFilterModel { skip?: number; @@ -8,9 +7,5 @@ export interface UmbMemberCollectionFilterModel { filter?: string; } -export interface UmbMemberCollectionModel { - unique: string; - entityType: UmbMemberEntityType; - variants: Array; - kind: UmbMemberKindType; -} +// eslint-disable-next-line @typescript-eslint/no-empty-object-type +export interface UmbMemberCollectionModel extends UmbMemberDetailModel {} diff --git a/src/Umbraco.Web.UI.Client/src/packages/members/member/collection/views/table/member-table-collection-view.element.ts b/src/Umbraco.Web.UI.Client/src/packages/members/member/collection/views/table/member-table-collection-view.element.ts index bc81f76e4e..04578cacd3 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/members/member/collection/views/table/member-table-collection-view.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/members/member/collection/views/table/member-table-collection-view.element.ts @@ -20,6 +20,14 @@ export class UmbMemberTableCollectionViewElement extends UmbLitElement { name: this.localize.term('general_name'), alias: 'memberName', }, + { + name: this.localize.term('general_username'), + alias: 'memberUsername', + }, + { + name: this.localize.term('general_email'), + alias: 'memberEmail', + }, { name: this.localize.term('member_kind'), alias: 'memberKind', @@ -46,6 +54,7 @@ export class UmbMemberTableCollectionViewElement extends UmbLitElement { } #createTableItems(members: Array) { + console.log('members', members); this._tableItems = members.map((member) => { // TODO: get correct variant name const name = member.variants[0].name; @@ -62,6 +71,14 @@ export class UmbMemberTableCollectionViewElement extends UmbLitElement { columnAlias: 'memberName', value: html`${name}`, }, + { + columnAlias: 'memberUsername', + value: member.username, + }, + { + columnAlias: 'memberEmail', + value: member.email, + }, { columnAlias: 'memberKind', value: kind, 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 110/134] 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 111/134] 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 112/134] 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 113/134] 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'; From 0460a355038da3c34816c0e7521d02ef7b0cccaa Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 10 Sep 2024 13:13:52 +0200 Subject: [PATCH 114/134] align sidebar spacing --- ...mber-workspace-view-member-info.element.ts | 54 +++++++-------- .../member-workspace-view-member.element.ts | 68 +++++++++---------- .../user-workspace-info.element.ts | 26 +++---- 3 files changed, 70 insertions(+), 78 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/members/member/workspace/views/member/member-workspace-view-member-info.element.ts b/src/Umbraco.Web.UI.Client/src/packages/members/member/workspace/views/member/member-workspace-view-member-info.element.ts index 2a8b77ddb3..fd5ac87c02 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/members/member/workspace/views/member/member-workspace-view-member-info.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/members/member/workspace/views/member/member-workspace-view-member-info.element.ts @@ -70,41 +70,37 @@ export class UmbMemberWorkspaceViewMemberInfoElement extends UmbLitElement imple #renderGeneralSection() { return html` -
- Created - ${this._createDate} -
-
- Last edited - ${this._updateDate} -
-
- Member Type - - - -
-
- Id - ${this._unique} -
+ +
+

Created

+ ${this._createDate} +
+
+

Last edited

+ ${this._updateDate} +
+
+

Member Type

+ + + +
+
+

Id

+ ${this._unique} +
+
`; } static override styles = [ UmbTextStyles, css` - .general-item { - display: flex; - flex-direction: column; - gap: var(--uui-size-space-1); - } - - .general-item:not(:last-child) { - margin-bottom: var(--uui-size-space-6); + h4 { + margin: 0; } `, ]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/members/member/workspace/views/member/member-workspace-view-member.element.ts b/src/Umbraco.Web.UI.Client/src/packages/members/member/workspace/views/member/member-workspace-view-member.element.ts index bb33e453b8..8573a9b9c4 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/members/member/workspace/views/member/member-workspace-view-member.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/members/member/workspace/views/member/member-workspace-view-member.element.ts @@ -208,34 +208,36 @@ export class UmbMemberWorkspaceViewMemberElement extends UmbLitElement implement return html`
-
- Failed login attempts - ${this._workspaceContext.failedPasswordAttempts} -
-
- Last lockout date - - ${this._workspaceContext.lastLockOutDate - ? this.localize.date(this._workspaceContext.lastLockOutDate, TimeFormatOptions) - : this.localize.term('general_never')} - -
-
- Last login - - ${this._workspaceContext.lastLoginDate - ? this.localize.date(this._workspaceContext.lastLoginDate, TimeFormatOptions) - : this.localize.term('general_never')} - -
-
- Password changed - - ${this._workspaceContext.lastPasswordChangeDate - ? this.localize.date(this._workspaceContext.lastPasswordChangeDate, TimeFormatOptions) - : this.localize.term('general_never')} - -
+ +
+

Failed login attempts

+ ${this._workspaceContext.failedPasswordAttempts} +
+
+

Last lockout date

+ + ${this._workspaceContext.lastLockOutDate + ? this.localize.date(this._workspaceContext.lastLockOutDate, TimeFormatOptions) + : this.localize.term('general_never')} + +
+
+

Last login

+ + ${this._workspaceContext.lastLoginDate + ? this.localize.date(this._workspaceContext.lastLoginDate, TimeFormatOptions) + : this.localize.term('general_never')} + +
+
+

Password changed

+ + ${this._workspaceContext.lastPasswordChangeDate + ? this.localize.date(this._workspaceContext.lastPasswordChangeDate, TimeFormatOptions) + : this.localize.term('general_never')} + +
+
@@ -291,14 +293,8 @@ export class UmbMemberWorkspaceViewMemberElement extends UmbLitElement implement color: var(--uui-color-danger); } - .general-item { - display: flex; - flex-direction: column; - gap: var(--uui-size-space-1); - } - - .general-item:not(:last-child) { - margin-bottom: var(--uui-size-space-6); + h4 { + margin: 0; } `, ]; 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 3be3786c98..898bea5823 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 @@ -97,18 +97,20 @@ export class UmbUserWorkspaceInfoElement extends UmbLitElement { #renderInfoList() { return html` - ${repeat( - this._userInfo, - (item) => item.labelKey, - (item) => this.#renderInfoItem(item.labelKey, item.value), - )} + + ${repeat( + this._userInfo, + (item) => item.labelKey, + (item) => this.#renderInfoItem(item.labelKey, item.value), + )} + `; } #renderInfoItem(labelKey: string, value?: string | number) { return html` - +
+

+ ${this._memberKind === UmbMemberKind.API + ? this.localize.term('member_memberKindApi') + : this.localize.term('member_memberKindDefault')} +

Id

${this._unique} From b97cecff25099d4f227d3697cad56c9d0c978ff5 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 10 Sep 2024 13:51:22 +0200 Subject: [PATCH 117/134] show member type + correct member type icon --- .../member-table-collection-view.element.ts | 21 ++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/members/member/collection/views/table/member-table-collection-view.element.ts b/src/Umbraco.Web.UI.Client/src/packages/members/member/collection/views/table/member-table-collection-view.element.ts index 04578cacd3..2c66f2df9f 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/members/member/collection/views/table/member-table-collection-view.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/members/member/collection/views/table/member-table-collection-view.element.ts @@ -6,6 +6,8 @@ import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; import type { UmbTableColumn, UmbTableConfig, UmbTableItem } from '@umbraco-cms/backoffice/components'; import { css, html, customElement, state } from '@umbraco-cms/backoffice/external/lit'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; +import { UmbMemberItemRepository } from '../../../repository/index.js'; +import { UmbMemberTypeItemRepository } from '@umbraco-cms/backoffice/member-type'; @customElement('umb-member-table-collection-view') export class UmbMemberTableCollectionViewElement extends UmbLitElement { @@ -28,6 +30,10 @@ export class UmbMemberTableCollectionViewElement extends UmbLitElement { name: this.localize.term('general_email'), alias: 'memberEmail', }, + { + name: this.localize.term('content_membertype'), + alias: 'memberType', + }, { name: this.localize.term('member_kind'), alias: 'memberKind', @@ -38,6 +44,7 @@ export class UmbMemberTableCollectionViewElement extends UmbLitElement { private _tableItems: Array = []; #collectionContext?: UmbMemberCollectionContext; + #memberTypeItemRepository = new UmbMemberTypeItemRepository(this); constructor() { super(); @@ -53,8 +60,10 @@ export class UmbMemberTableCollectionViewElement extends UmbLitElement { this.observe(this.#collectionContext.items, (items) => this.#createTableItems(items), 'umbCollectionItemsObserver'); } - #createTableItems(members: Array) { - console.log('members', members); + async #createTableItems(members: Array) { + const memberTypeUniques = members.map((member) => member.memberType.unique); + const { data: memberTypes } = await this.#memberTypeItemRepository.requestItems(memberTypeUniques); + this._tableItems = members.map((member) => { // TODO: get correct variant name const name = member.variants[0].name; @@ -63,9 +72,11 @@ export class UmbMemberTableCollectionViewElement extends UmbLitElement { ? this.localize.term('member_memberKindApi') : this.localize.term('member_memberKindDefault'); + const memberType = memberTypes?.find((type) => type.unique === member.memberType.unique); + return { id: member.unique, - icon: 'icon-user', + icon: memberType?.icon, data: [ { columnAlias: 'memberName', @@ -79,6 +90,10 @@ export class UmbMemberTableCollectionViewElement extends UmbLitElement { columnAlias: 'memberEmail', value: member.email, }, + { + columnAlias: 'memberType', + value: memberType?.name, + }, { columnAlias: 'memberKind', value: kind, From 87a4120a4ae081b8a4ca5f01704a030dd44e534e Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 10 Sep 2024 14:20:19 +0200 Subject: [PATCH 118/134] fix lint errors --- .../views/table/member-table-collection-view.element.ts | 1 - .../views/member/member-workspace-view-member-info.element.ts | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/members/member/collection/views/table/member-table-collection-view.element.ts b/src/Umbraco.Web.UI.Client/src/packages/members/member/collection/views/table/member-table-collection-view.element.ts index 2c66f2df9f..ed4398313a 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/members/member/collection/views/table/member-table-collection-view.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/members/member/collection/views/table/member-table-collection-view.element.ts @@ -6,7 +6,6 @@ import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; import type { UmbTableColumn, UmbTableConfig, UmbTableItem } from '@umbraco-cms/backoffice/components'; import { css, html, customElement, state } from '@umbraco-cms/backoffice/external/lit'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; -import { UmbMemberItemRepository } from '../../../repository/index.js'; import { UmbMemberTypeItemRepository } from '@umbraco-cms/backoffice/member-type'; @customElement('umb-member-table-collection-view') diff --git a/src/Umbraco.Web.UI.Client/src/packages/members/member/workspace/views/member/member-workspace-view-member-info.element.ts b/src/Umbraco.Web.UI.Client/src/packages/members/member/workspace/views/member/member-workspace-view-member-info.element.ts index ddd470dba7..10c8d46ee2 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/members/member/workspace/views/member/member-workspace-view-member-info.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/members/member/workspace/views/member/member-workspace-view-member-info.element.ts @@ -1,5 +1,6 @@ // import { UMB_COMPOSITION_PICKER_MODAL, type UmbCompositionPickerModalData } from '../../../modals/index.js'; import { UMB_MEMBER_WORKSPACE_CONTEXT } from '../../member-workspace.context-token.js'; +import type { UmbMemberKindType } from '../../../utils/index.js'; import { TimeFormatOptions } from './utils.js'; import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; import { css, html, customElement, state } from '@umbraco-cms/backoffice/external/lit'; @@ -8,7 +9,6 @@ import type { UmbWorkspaceViewElement } from '@umbraco-cms/backoffice/extension- import { UMB_WORKSPACE_MODAL } from '@umbraco-cms/backoffice/modal'; import { UmbModalRouteRegistrationController } from '@umbraco-cms/backoffice/router'; import { UmbMemberTypeItemRepository } from '@umbraco-cms/backoffice/member-type'; -import { UmbMemberKind, UmbMemberKindType } from '../../../utils/index.js'; @customElement('umb-member-workspace-view-member-info') export class UmbMemberWorkspaceViewMemberInfoElement extends UmbLitElement implements UmbWorkspaceViewElement { From 41a28300aba9a7da6847a57b17d9a799a52ff0dd Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 10 Sep 2024 14:31:06 +0200 Subject: [PATCH 119/134] Bump version number --- src/Umbraco.Web.UI.Client/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/package.json b/src/Umbraco.Web.UI.Client/package.json index ac79713592..075d0e1d0a 100644 --- a/src/Umbraco.Web.UI.Client/package.json +++ b/src/Umbraco.Web.UI.Client/package.json @@ -1,7 +1,7 @@ { "name": "@umbraco-cms/backoffice", "license": "MIT", - "version": "14.3.0", + "version": "15.0.0", "type": "module", "exports": { ".": null, From d6f76889789d1dce39204b6110bc35f943aaf968 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 10 Sep 2024 14:31:25 +0200 Subject: [PATCH 120/134] Update member-workspace-view-member-info.element.ts --- .../views/member/member-workspace-view-member-info.element.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/members/member/workspace/views/member/member-workspace-view-member-info.element.ts b/src/Umbraco.Web.UI.Client/src/packages/members/member/workspace/views/member/member-workspace-view-member-info.element.ts index 10c8d46ee2..4c3d0414c1 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/members/member/workspace/views/member/member-workspace-view-member-info.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/members/member/workspace/views/member/member-workspace-view-member-info.element.ts @@ -1,6 +1,6 @@ // import { UMB_COMPOSITION_PICKER_MODAL, type UmbCompositionPickerModalData } from '../../../modals/index.js'; import { UMB_MEMBER_WORKSPACE_CONTEXT } from '../../member-workspace.context-token.js'; -import type { UmbMemberKindType } from '../../../utils/index.js'; +import { UmbMemberKind, type UmbMemberKindType } from '../../../utils/index.js'; import { TimeFormatOptions } from './utils.js'; import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; import { css, html, customElement, state } from '@umbraco-cms/backoffice/external/lit'; From 859276680f5f9e8923691f2de8012e5bc67e6fad Mon Sep 17 00:00:00 2001 From: Jacob Overgaard <752371+iOvergaard@users.noreply.github.com> Date: Tue, 10 Sep 2024 17:15:44 +0200 Subject: [PATCH 121/134] fix: adds the UmbBlockRteEntriesContext to the tinymce property editor ui so the routes can be calculated --- .../tiny-mce/property-editor-ui-tiny-mce.element.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Umbraco.Web.UI.Client/src/packages/tiny-mce/property-editors/tiny-mce/property-editor-ui-tiny-mce.element.ts b/src/Umbraco.Web.UI.Client/src/packages/tiny-mce/property-editors/tiny-mce/property-editor-ui-tiny-mce.element.ts index a548388d19..1134ca8653 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/tiny-mce/property-editors/tiny-mce/property-editor-ui-tiny-mce.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/tiny-mce/property-editors/tiny-mce/property-editor-ui-tiny-mce.element.ts @@ -6,6 +6,7 @@ import type { UmbPropertyEditorUiElement } from '@umbraco-cms/backoffice/extensi import '../../components/input-tiny-mce/input-tiny-mce.element.js'; import { + UmbBlockRteEntriesContext, type UmbBlockRteLayoutModel, UmbBlockRteManagerContext, type UmbBlockRteTypeModel, @@ -83,6 +84,7 @@ export class UmbPropertyEditorUITinyMceElement extends UmbLitElement implements private _latestMarkup = ''; // The latest value gotten from the TinyMCE editor. #managerContext = new UmbBlockRteManagerContext(this); + #entriesContext = new UmbBlockRteEntriesContext(this); constructor() { super(); From e96e1ff2b4c5b2e0f29e6acae6eebbc5cd5b6fc4 Mon Sep 17 00:00:00 2001 From: Jacob Overgaard <752371+iOvergaard@users.noreply.github.com> Date: Tue, 10 Sep 2024 17:16:27 +0200 Subject: [PATCH 122/134] fix: adds a check in the tinymce blockpicker plugin to ensure the entries context is available and if not to warn about it, since the whole plugin does not work without it --- .../tiny-mce-plugin/tiny-mce-block-picker.plugin.ts | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-rte/tiny-mce-plugin/tiny-mce-block-picker.plugin.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-rte/tiny-mce-plugin/tiny-mce-block-picker.plugin.ts index 66fbd90b8c..380b62b1b1 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-rte/tiny-mce-plugin/tiny-mce-block-picker.plugin.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-rte/tiny-mce-plugin/tiny-mce-block-picker.plugin.ts @@ -59,14 +59,19 @@ export default class UmbTinyMceMultiUrlPickerPlugin extends UmbTinyMcePluginBase } #createBlock() { + if (!this.#entriesContext) { + console.error('[Block Picker] No entries context available.'); + return; + } + // TODO: Missing solution to skip catalogue if only one type available. [NL] let createPath: string | undefined = undefined; if (this._blocks?.length === 1) { const elementKey = this._blocks[0].contentElementTypeKey; - createPath = this.#entriesContext?.getPathForCreateBlock() + 'modal/umb-modal-workspace/create/' + elementKey; + createPath = this.#entriesContext.getPathForCreateBlock() + 'modal/umb-modal-workspace/create/' + elementKey; } else { - createPath = this.#entriesContext?.getPathForCreateBlock(); + createPath = this.#entriesContext.getPathForCreateBlock(); } if (createPath) { From 8b934c9efa490fb3f2538a654ee9bd7438d80e75 Mon Sep 17 00:00:00 2001 From: Jacob Overgaard <752371+iOvergaard@users.noreply.github.com> Date: Tue, 10 Sep 2024 17:39:01 +0200 Subject: [PATCH 123/134] chore: re-order imports --- .../tiny-mce/property-editor-ui-tiny-mce.element.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/tiny-mce/property-editors/tiny-mce/property-editor-ui-tiny-mce.element.ts b/src/Umbraco.Web.UI.Client/src/packages/tiny-mce/property-editors/tiny-mce/property-editor-ui-tiny-mce.element.ts index 1134ca8653..8839980d23 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/tiny-mce/property-editors/tiny-mce/property-editor-ui-tiny-mce.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/tiny-mce/property-editors/tiny-mce/property-editor-ui-tiny-mce.element.ts @@ -3,8 +3,6 @@ import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; import { UmbPropertyValueChangeEvent } from '@umbraco-cms/backoffice/property-editor'; import type { UmbPropertyEditorConfigCollection } from '@umbraco-cms/backoffice/property-editor'; import type { UmbPropertyEditorUiElement } from '@umbraco-cms/backoffice/extension-registry'; - -import '../../components/input-tiny-mce/input-tiny-mce.element.js'; import { UmbBlockRteEntriesContext, type UmbBlockRteLayoutModel, @@ -13,6 +11,8 @@ import { } from '@umbraco-cms/backoffice/block-rte'; import type { UmbBlockValueType } from '@umbraco-cms/backoffice/block'; +import '../../components/input-tiny-mce/input-tiny-mce.element.js'; + export interface UmbRichTextEditorValueType { markup: string; blocks: UmbBlockValueType; From f6b93de1235e4dca9f5afb50a77e0473bcefa90a Mon Sep 17 00:00:00 2001 From: Jacob Overgaard <752371+iOvergaard@users.noreply.github.com> Date: Tue, 10 Sep 2024 17:39:15 +0200 Subject: [PATCH 124/134] fix: listen for layoutEntries and set them on the manager --- .../tiny-mce/property-editor-ui-tiny-mce.element.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/Umbraco.Web.UI.Client/src/packages/tiny-mce/property-editors/tiny-mce/property-editor-ui-tiny-mce.element.ts b/src/Umbraco.Web.UI.Client/src/packages/tiny-mce/property-editors/tiny-mce/property-editor-ui-tiny-mce.element.ts index 8839980d23..d40071b228 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/tiny-mce/property-editors/tiny-mce/property-editor-ui-tiny-mce.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/tiny-mce/property-editors/tiny-mce/property-editor-ui-tiny-mce.element.ts @@ -89,6 +89,11 @@ export class UmbPropertyEditorUITinyMceElement extends UmbLitElement implements constructor() { super(); + this.observe(this.#entriesContext.layoutEntries, (layouts) => { + // Update manager: + this.#managerContext.setLayouts(layouts); + }); + this.observe(this.#managerContext.layouts, (layouts) => { this._value = { ...this._value, From ccb9eeb08b7b8fcd5aa824efd487e6c30ac0ed93 Mon Sep 17 00:00:00 2001 From: Lee Kelleher Date: Wed, 11 Sep 2024 08:20:18 +0100 Subject: [PATCH 125/134] Feature: UFM component filters (#2246) * UFM feature additions + refactor - Re-structures "ufm-components" folder - Adds `ufmFilter` extension type - Adds `UmbUfmElementBase` to support reusing filters * Code tidy-up * Adds test for `{~contentPicker}` "ufm-content-name" syntax * Exports `UfmPlugin` and `UfmToken` types * Adds UFM filter extensions/functions - Fallback - Lowercase - Strip HTML - Title Case - Truncate - Uppercase - Word Limit --- .../core/extension-registry/models/index.ts | 3 + .../models/ufm-filter.model.ts | 14 +++ .../content-name/content-name.component.ts | 15 +++ .../content-name/content-name.element.ts | 74 ++++++++++++++ .../src/packages/ufm/components/index.ts | 3 + .../label-value/label-value.component.ts | 15 +++ .../label-value}/label-value.element.ts | 19 ++-- .../components/localize/localize.component.ts | 15 +++ .../components/localize/localize.element.ts | 26 +++++ .../src/packages/ufm/components/manifests.ts | 25 +++++ .../ufm/components/ufm-component-base.ts | 25 +++++ .../ufm/components/ufm-element-base.ts | 54 +++++++++++ .../ufm-render/ufm-render.context.ts | 2 +- .../ufm-render/ufm-render.element.ts | 62 ++---------- .../src/packages/ufm/contexts/index.ts | 1 + .../src/packages/ufm/contexts/manifest.ts | 8 ++ .../src/packages/ufm/contexts/ufm.context.ts | 96 +++++++++++++++++++ .../packages/ufm/filters/fallback.filter.ts | 9 ++ .../packages/ufm/filters/lowercase.filter.ts | 9 ++ .../src/packages/ufm/filters/manifests.ts | 53 ++++++++++ .../packages/ufm/filters/strip-html.filter.ts | 15 +++ .../packages/ufm/filters/title-case.filter.ts | 9 ++ .../packages/ufm/filters/truncate.filter.ts | 14 +++ .../packages/ufm/filters/uppercase.filter.ts | 9 ++ .../packages/ufm/filters/word-limit.filter.ts | 10 ++ .../src/packages/ufm/index.ts | 7 +- .../src/packages/ufm/manifests.ts | 22 +---- .../src/packages/ufm/plugins/index.ts | 2 + .../packages/ufm/plugins/marked-ufm.plugin.ts | 3 +- .../packages/ufm/plugins/marked-ufm.test.ts | 15 ++- .../src/packages/ufm/types.ts | 6 ++ .../ufm-components/document-name.component.ts | 12 --- .../ufm-components/document-name.element.ts | 54 ----------- .../ufm-components/label-value.component.ts | 13 --- .../ufm/ufm-components/localize.component.ts | 11 --- .../ufm/ufm-components/ufm-component-base.ts | 7 -- 36 files changed, 546 insertions(+), 191 deletions(-) create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/models/ufm-filter.model.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/ufm/components/content-name/content-name.component.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/ufm/components/content-name/content-name.element.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/ufm/components/index.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/ufm/components/label-value/label-value.component.ts rename src/Umbraco.Web.UI.Client/src/packages/ufm/{ufm-components => components/label-value}/label-value.element.ts (51%) create mode 100644 src/Umbraco.Web.UI.Client/src/packages/ufm/components/localize/localize.component.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/ufm/components/localize/localize.element.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/ufm/components/manifests.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/ufm/components/ufm-component-base.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/ufm/components/ufm-element-base.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/ufm/contexts/index.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/ufm/contexts/manifest.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/ufm/contexts/ufm.context.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/ufm/filters/fallback.filter.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/ufm/filters/lowercase.filter.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/ufm/filters/manifests.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/ufm/filters/strip-html.filter.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/ufm/filters/title-case.filter.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/ufm/filters/truncate.filter.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/ufm/filters/uppercase.filter.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/ufm/filters/word-limit.filter.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/ufm/plugins/index.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/ufm/types.ts delete mode 100644 src/Umbraco.Web.UI.Client/src/packages/ufm/ufm-components/document-name.component.ts delete mode 100644 src/Umbraco.Web.UI.Client/src/packages/ufm/ufm-components/document-name.element.ts delete mode 100644 src/Umbraco.Web.UI.Client/src/packages/ufm/ufm-components/label-value.component.ts delete mode 100644 src/Umbraco.Web.UI.Client/src/packages/ufm/ufm-components/localize.component.ts delete mode 100644 src/Umbraco.Web.UI.Client/src/packages/ufm/ufm-components/ufm-component-base.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/models/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/models/index.ts index adc53de04c..bcec4417ea 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/models/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/models/index.ts @@ -46,6 +46,7 @@ import type { ManifestTinyMcePlugin } from './tinymce-plugin.model.js'; import type { ManifestTree } from './tree.model.js'; import type { ManifestTreeItem } from './tree-item.model.js'; import type { ManifestUfmComponent } from './ufm-component.model.js'; +import type { ManifestUfmFilter } from './ufm-filter.model.js'; import type { ManifestUserProfileApp } from './user-profile-app.model.js'; import type { ManifestWorkspace, ManifestWorkspaceRoutableKind } from './workspace.model.js'; import type { ManifestWorkspaceAction, ManifestWorkspaceActionDefaultKind } from './workspace-action.model.js'; @@ -117,6 +118,7 @@ export type * from './tinymce-plugin.model.js'; export type * from './tree-item.model.js'; export type * from './tree.model.js'; export type * from './ufm-component.model.js'; +export type * from './ufm-filter.model.js'; export type * from './user-granular-permission.model.js'; export type * from './user-profile-app.model.js'; export type * from './workspace-action-menu-item.model.js'; @@ -210,6 +212,7 @@ export type ManifestTypes = | ManifestTreeItem | ManifestTreeStore | ManifestUfmComponent + | ManifestUfmFilter | ManifestUserProfileApp | ManifestWorkspaceActionMenuItem | ManifestWorkspaceActions diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/models/ufm-filter.model.ts b/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/models/ufm-filter.model.ts new file mode 100644 index 0000000000..8144601021 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/models/ufm-filter.model.ts @@ -0,0 +1,14 @@ +import type { ManifestApi, UmbApi } from '@umbraco-cms/backoffice/extension-api'; + +export interface UmbUfmFilterApi extends UmbApi { + filter(...args: Array): string | undefined | null; +} + +export interface MetaUfmFilter { + alias: string; +} + +export interface ManifestUfmFilter extends ManifestApi { + type: 'ufmFilter'; + meta: MetaUfmFilter; +} diff --git a/src/Umbraco.Web.UI.Client/src/packages/ufm/components/content-name/content-name.component.ts b/src/Umbraco.Web.UI.Client/src/packages/ufm/components/content-name/content-name.component.ts new file mode 100644 index 0000000000..dfcd5c6e2b --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/ufm/components/content-name/content-name.component.ts @@ -0,0 +1,15 @@ +import type { UfmToken } from '../../plugins/marked-ufm.plugin.js'; +import { UmbUfmComponentBase } from '../ufm-component-base.js'; + +import './content-name.element.js'; + +export class UmbUfmContentNameComponent extends UmbUfmComponentBase { + render(token: UfmToken) { + if (!token.text) return; + + const attributes = super.getAttributes(token.text); + return ``; + } +} + +export { UmbUfmContentNameComponent as api }; diff --git a/src/Umbraco.Web.UI.Client/src/packages/ufm/components/content-name/content-name.element.ts b/src/Umbraco.Web.UI.Client/src/packages/ufm/components/content-name/content-name.element.ts new file mode 100644 index 0000000000..4335c2bb28 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/ufm/components/content-name/content-name.element.ts @@ -0,0 +1,74 @@ +import { UmbUfmElementBase } from '../ufm-element-base.js'; +import { UMB_UFM_RENDER_CONTEXT } from '../ufm-render/ufm-render.context.js'; +import { customElement, property } from '@umbraco-cms/backoffice/external/lit'; +import { UmbDocumentItemRepository } from '@umbraco-cms/backoffice/document'; +import { UmbMediaItemRepository } from '@umbraco-cms/backoffice/media'; +import { UmbMemberItemRepository } from '@umbraco-cms/backoffice/member'; + +const elementName = 'ufm-content-name'; + +@customElement(elementName) +export class UmbUfmContentNameElement extends UmbUfmElementBase { + @property() + alias?: string; + + #documentRepository?: UmbDocumentItemRepository; + #mediaRepository?: UmbMediaItemRepository; + #memberRepository?: UmbMemberItemRepository; + + constructor() { + super(); + + this.consumeContext(UMB_UFM_RENDER_CONTEXT, (context) => { + this.observe( + context.value, + async (value) => { + const temp = + this.alias && typeof value === 'object' + ? ((value as Record)[this.alias] as string) + : (value as string); + + const entityType = Array.isArray(temp) && temp.length > 0 ? temp[0].type : null; + const uniques = Array.isArray(temp) ? temp.map((x) => x.unique) : temp ? [temp] : []; + + if (uniques?.length) { + const repository = this.#getRepository(entityType); + if (repository) { + const { data } = await repository.requestItems(uniques); + this.value = data ? data.map((item) => item.name).join(', ') : ''; + return; + } + } + + this.value = ''; + }, + 'observeValue', + ); + }); + } + + #getRepository(entityType?: string | null) { + switch (entityType) { + case 'media': + if (!this.#mediaRepository) this.#mediaRepository = new UmbMediaItemRepository(this); + return this.#mediaRepository; + + case 'member': + if (!this.#memberRepository) this.#memberRepository = new UmbMemberItemRepository(this); + return this.#memberRepository; + + case 'document': + default: + if (!this.#documentRepository) this.#documentRepository = new UmbDocumentItemRepository(this); + return this.#documentRepository; + } + } +} + +export { UmbUfmContentNameElement as element }; + +declare global { + interface HTMLElementTagNameMap { + [elementName]: UmbUfmContentNameElement; + } +} diff --git a/src/Umbraco.Web.UI.Client/src/packages/ufm/components/index.ts b/src/Umbraco.Web.UI.Client/src/packages/ufm/components/index.ts new file mode 100644 index 0000000000..7f1f30e709 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/ufm/components/index.ts @@ -0,0 +1,3 @@ +export * from './ufm-render/index.js'; +export * from './ufm-component-base.js'; +export * from './ufm-element-base.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/ufm/components/label-value/label-value.component.ts b/src/Umbraco.Web.UI.Client/src/packages/ufm/components/label-value/label-value.component.ts new file mode 100644 index 0000000000..bbadd36dc5 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/ufm/components/label-value/label-value.component.ts @@ -0,0 +1,15 @@ +import type { UfmToken } from '../../plugins/marked-ufm.plugin.js'; +import { UmbUfmComponentBase } from '../ufm-component-base.js'; + +import './label-value.element.js'; + +export class UmbUfmLabelValueComponent extends UmbUfmComponentBase { + render(token: UfmToken) { + if (!token.text) return; + + const attributes = super.getAttributes(token.text); + return ``; + } +} + +export { UmbUfmLabelValueComponent as api }; diff --git a/src/Umbraco.Web.UI.Client/src/packages/ufm/ufm-components/label-value.element.ts b/src/Umbraco.Web.UI.Client/src/packages/ufm/components/label-value/label-value.element.ts similarity index 51% rename from src/Umbraco.Web.UI.Client/src/packages/ufm/ufm-components/label-value.element.ts rename to src/Umbraco.Web.UI.Client/src/packages/ufm/components/label-value/label-value.element.ts index cb28e01989..64081048ac 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/ufm/ufm-components/label-value.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/ufm/components/label-value/label-value.element.ts @@ -1,17 +1,14 @@ -import { UMB_UFM_RENDER_CONTEXT } from '../components/ufm-render/index.js'; -import { customElement, nothing, property, state } from '@umbraco-cms/backoffice/external/lit'; -import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; +import { UMB_UFM_RENDER_CONTEXT } from '../ufm-render/ufm-render.context.js'; +import { UmbUfmElementBase } from '../ufm-element-base.js'; +import { customElement, property } from '@umbraco-cms/backoffice/external/lit'; const elementName = 'ufm-label-value'; @customElement(elementName) -export class UmbUfmLabelValueElement extends UmbLitElement { +export class UmbUfmLabelValueElement extends UmbUfmElementBase { @property() alias?: string; - @state() - private _value?: unknown; - constructor() { super(); @@ -20,19 +17,15 @@ export class UmbUfmLabelValueElement extends UmbLitElement { context.value, (value) => { if (this.alias !== undefined && value !== undefined && typeof value === 'object') { - this._value = (value as Record)[this.alias]; + this.value = (value as Record)[this.alias]; } else { - this._value = value; + this.value = value; } }, 'observeValue', ); }); } - - override render() { - return this._value !== undefined ? this._value : nothing; - } } export { UmbUfmLabelValueElement as element }; diff --git a/src/Umbraco.Web.UI.Client/src/packages/ufm/components/localize/localize.component.ts b/src/Umbraco.Web.UI.Client/src/packages/ufm/components/localize/localize.component.ts new file mode 100644 index 0000000000..8789e05455 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/ufm/components/localize/localize.component.ts @@ -0,0 +1,15 @@ +import type { UfmToken } from '../../plugins/marked-ufm.plugin.js'; +import { UmbUfmComponentBase } from '../ufm-component-base.js'; + +import './localize.element.js'; + +export class UmbUfmLocalizeComponent extends UmbUfmComponentBase { + render(token: UfmToken) { + if (!token.text) return; + + const attributes = super.getAttributes(token.text); + return ``; + } +} + +export { UmbUfmLocalizeComponent as api }; diff --git a/src/Umbraco.Web.UI.Client/src/packages/ufm/components/localize/localize.element.ts b/src/Umbraco.Web.UI.Client/src/packages/ufm/components/localize/localize.element.ts new file mode 100644 index 0000000000..9f440de11a --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/ufm/components/localize/localize.element.ts @@ -0,0 +1,26 @@ +import { UmbUfmElementBase } from '../ufm-element-base.js'; +import { customElement, property } from '@umbraco-cms/backoffice/external/lit'; + +const elementName = 'ufm-localize'; + +@customElement(elementName) +export class UmbUfmLocalizeElement extends UmbUfmElementBase { + @property() + public set alias(value: string | undefined) { + if (!value) return; + this.#alias = value; + this.value = this.localize.term(value); + } + public get alias(): string | undefined { + return this.#alias; + } + #alias?: string; +} + +export { UmbUfmLocalizeElement as element }; + +declare global { + interface HTMLElementTagNameMap { + [elementName]: UmbUfmLocalizeElement; + } +} diff --git a/src/Umbraco.Web.UI.Client/src/packages/ufm/components/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/ufm/components/manifests.ts new file mode 100644 index 0000000000..a1120024a0 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/ufm/components/manifests.ts @@ -0,0 +1,25 @@ +import type { ManifestUfmComponent } from '@umbraco-cms/backoffice/extension-registry'; + +export const manifests: Array = [ + { + type: 'ufmComponent', + alias: 'Umb.Markdown.LabelValue', + name: 'Label Value UFM Component', + api: () => import('./label-value/label-value.component.js'), + meta: { marker: '=' }, + }, + { + type: 'ufmComponent', + alias: 'Umb.Markdown.Localize', + name: 'Localize UFM Component', + api: () => import('./localize/localize.component.js'), + meta: { marker: '#' }, + }, + { + type: 'ufmComponent', + alias: 'Umb.Markdown.ContentName', + name: 'Content Name UFM Component', + api: () => import('./content-name/content-name.component.js'), + meta: { marker: '~' }, + }, +]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/ufm/components/ufm-component-base.ts b/src/Umbraco.Web.UI.Client/src/packages/ufm/components/ufm-component-base.ts new file mode 100644 index 0000000000..6b1d35217d --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/ufm/components/ufm-component-base.ts @@ -0,0 +1,25 @@ +import type { UfmToken } from '../plugins/marked-ufm.plugin.js'; +import type { UmbUfmComponentApi } from '@umbraco-cms/backoffice/extension-registry'; + +export abstract class UmbUfmComponentBase implements UmbUfmComponentApi { + protected getAttributes(text: string): string | null { + if (!text) return null; + + const pipeIndex = text.indexOf('|'); + + if (pipeIndex === -1) { + return `alias="${text.trim()}"`; + } + + const alias = text.substring(0, pipeIndex).trim(); + const filters = text.substring(pipeIndex + 1).trim(); + + return Object.entries({ alias, filters }) + .map(([key, value]) => (value ? `${key}="${value.trim()}"` : null)) + .join(' '); + } + + abstract render(token: UfmToken): string | undefined; + + destroy() {} +} diff --git a/src/Umbraco.Web.UI.Client/src/packages/ufm/components/ufm-element-base.ts b/src/Umbraco.Web.UI.Client/src/packages/ufm/components/ufm-element-base.ts new file mode 100644 index 0000000000..524d281f81 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/ufm/components/ufm-element-base.ts @@ -0,0 +1,54 @@ +import { UMB_UFM_CONTEXT } from '../contexts/ufm.context.js'; +import { nothing, property, state } from '@umbraco-cms/backoffice/external/lit'; +import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; + +// eslint-disable-next-line local-rules/enforce-element-suffix-on-element-class-name +export abstract class UmbUfmElementBase extends UmbLitElement { + #filterFuncArgs?: Array<{ alias: string; args: Array }>; + + @property() + public set filters(value: string | undefined) { + this.#filters = value; + + this.#filterFuncArgs = value + ?.split('|') + .filter((item) => item) + .map((item) => { + const [alias, ...args] = item.split(':').map((x) => x.trim()); + return { alias, args }; + }); + } + public get filters(): string | undefined { + return this.#filters; + } + #filters?: string; + + @state() + value?: unknown; + + #ufmContext?: typeof UMB_UFM_CONTEXT.TYPE; + + constructor() { + super(); + + this.consumeContext(UMB_UFM_CONTEXT, (ufmContext) => { + this.#ufmContext = ufmContext; + }); + } + + override render() { + if (!this.#ufmContext) return nothing; + + let values = Array.isArray(this.value) ? this.value : [this.value]; + if (this.#filterFuncArgs) { + for (const item of this.#filterFuncArgs) { + const filter = this.#ufmContext.getFilterByAlias(item.alias); + if (filter) { + values = values.map((value) => filter(value, ...item.args)); + } + } + } + + return values.join(', '); + } +} diff --git a/src/Umbraco.Web.UI.Client/src/packages/ufm/components/ufm-render/ufm-render.context.ts b/src/Umbraco.Web.UI.Client/src/packages/ufm/components/ufm-render/ufm-render.context.ts index 1ba6e4fe14..77de0e84a0 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/ufm/components/ufm-render/ufm-render.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/ufm/components/ufm-render/ufm-render.context.ts @@ -1,7 +1,7 @@ import { UmbContextBase } from '@umbraco-cms/backoffice/class-api'; import { UmbContextToken } from '@umbraco-cms/backoffice/context-api'; -import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; import { UmbObjectState } from '@umbraco-cms/backoffice/observable-api'; +import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; export class UmbUfmRenderContext extends UmbContextBase { #value = new UmbObjectState(undefined); diff --git a/src/Umbraco.Web.UI.Client/src/packages/ufm/components/ufm-render/ufm-render.element.ts b/src/Umbraco.Web.UI.Client/src/packages/ufm/components/ufm-render/ufm-render.element.ts index 56173caf27..6bf24160e5 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/ufm/components/ufm-render/ufm-render.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/ufm/components/ufm-render/ufm-render.element.ts @@ -1,43 +1,8 @@ -import type { UfmPlugin } from '../../plugins/marked-ufm.plugin.js'; -import { ufm } from '../../plugins/marked-ufm.plugin.js'; +import { UMB_UFM_CONTEXT } from '../../contexts/ufm.context.js'; import { UmbUfmRenderContext } from './ufm-render.context.js'; import { css, customElement, nothing, property, unsafeHTML, until } from '@umbraco-cms/backoffice/external/lit'; -import { DOMPurify } from '@umbraco-cms/backoffice/external/dompurify'; -import { Marked } from '@umbraco-cms/backoffice/external/marked'; -import type { UmbExtensionApiInitializer } from '@umbraco-cms/backoffice/extension-api'; -import { UmbExtensionsApiInitializer } from '@umbraco-cms/backoffice/extension-api'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; -import { umbExtensionsRegistry } from '@umbraco-cms/backoffice/extension-registry'; -import type { ManifestUfmComponent } from '@umbraco-cms/backoffice/extension-registry'; - -const UmbDomPurify = DOMPurify(window); -const UmbDomPurifyConfig: DOMPurify.Config = { - USE_PROFILES: { html: true }, - CUSTOM_ELEMENT_HANDLING: { - tagNameCheck: /^(?:ufm|umb|uui)-.*$/, - attributeNameCheck: /.+/, - allowCustomizedBuiltInElements: false, - }, -}; - -UmbDomPurify.addHook('afterSanitizeAttributes', function (node) { - // set all elements owning target to target=_blank - if ('target' in node) { - node.setAttribute('target', '_blank'); - } -}); - -export const UmbMarked = new Marked({ - async: true, - gfm: true, - breaks: true, - hooks: { - postprocess: (markup) => { - return UmbDomPurify.sanitize(markup, UmbDomPurifyConfig) as string; - }, - }, -}); const elementName = 'umb-ufm-render'; @@ -59,26 +24,13 @@ export class UmbUfmRenderElement extends UmbLitElement { return this.#context.getValue(); } + #ufmContext?: typeof UMB_UFM_CONTEXT.TYPE; + constructor() { super(); - new UmbExtensionsApiInitializer(this, umbExtensionsRegistry, 'ufmComponent', [], undefined, (controllers) => { - UmbMarked.use( - ufm( - controllers - .map((controller) => { - const ctrl = controller as unknown as UmbExtensionApiInitializer; - if (!ctrl.manifest || !ctrl.api) return; - return { - alias: ctrl.manifest.alias, - marker: ctrl.manifest.meta.marker, - render: ctrl.api.render, - }; - }) - .filter((x) => x) as Array, - ), - ); - this.requestUpdate('markdown'); + this.consumeContext(UMB_UFM_CONTEXT, (ufmContext) => { + this.#ufmContext = ufmContext; }); } @@ -87,8 +39,8 @@ export class UmbUfmRenderElement extends UmbLitElement { } async #renderMarkdown() { - if (!this.markdown) return null; - const markup = !this.inline ? await UmbMarked.parse(this.markdown) : await UmbMarked.parseInline(this.markdown); + if (!this.#ufmContext || !this.markdown) return null; + const markup = await this.#ufmContext.parse(this.markdown, this.inline); return markup ? unsafeHTML(markup) : nothing; } diff --git a/src/Umbraco.Web.UI.Client/src/packages/ufm/contexts/index.ts b/src/Umbraco.Web.UI.Client/src/packages/ufm/contexts/index.ts new file mode 100644 index 0000000000..dcc7961ddc --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/ufm/contexts/index.ts @@ -0,0 +1 @@ +export * from './ufm.context.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/ufm/contexts/manifest.ts b/src/Umbraco.Web.UI.Client/src/packages/ufm/contexts/manifest.ts new file mode 100644 index 0000000000..98c747273f --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/ufm/contexts/manifest.ts @@ -0,0 +1,8 @@ +import type { ManifestGlobalContext } from '@umbraco-cms/backoffice/extension-registry'; + +export const manifest: ManifestGlobalContext = { + type: 'globalContext', + alias: 'Umb.GlobalContext.Ufm', + name: 'UFM Context', + api: () => import('./ufm.context.js'), +}; diff --git a/src/Umbraco.Web.UI.Client/src/packages/ufm/contexts/ufm.context.ts b/src/Umbraco.Web.UI.Client/src/packages/ufm/contexts/ufm.context.ts new file mode 100644 index 0000000000..4a8512fc41 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/ufm/contexts/ufm.context.ts @@ -0,0 +1,96 @@ +import { ufm } from '../plugins/marked-ufm.plugin.js'; +import type { UfmPlugin } from '../plugins/marked-ufm.plugin.js'; +import { DOMPurify } from '@umbraco-cms/backoffice/external/dompurify'; +import { Marked } from '@umbraco-cms/backoffice/external/marked'; +import { UmbArrayState } from '@umbraco-cms/backoffice/observable-api'; +import { UmbContextBase } from '@umbraco-cms/backoffice/class-api'; +import { UmbContextToken } from '@umbraco-cms/backoffice/context-api'; +import { UmbExtensionsApiInitializer } from '@umbraco-cms/backoffice/extension-api'; +import { umbExtensionsRegistry } from '@umbraco-cms/backoffice/extension-registry'; +import type { ManifestUfmFilter, ManifestUfmComponent } from '@umbraco-cms/backoffice/extension-registry'; +import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; +import type { UmbExtensionApiInitializer } from '@umbraco-cms/backoffice/extension-api'; + +const UmbDomPurify = DOMPurify(window); +const UmbDomPurifyConfig: DOMPurify.Config = { + USE_PROFILES: { html: true }, + CUSTOM_ELEMENT_HANDLING: { + tagNameCheck: /^(?:ufm|umb|uui)-.*$/, + attributeNameCheck: /.+/, + allowCustomizedBuiltInElements: false, + }, +}; + +UmbDomPurify.addHook('afterSanitizeAttributes', function (node) { + // set all elements owning target to target=_blank + if ('target' in node) { + node.setAttribute('target', '_blank'); + } +}); + +export const UmbMarked = new Marked({ + async: true, + gfm: true, + breaks: true, + hooks: { + postprocess: (markup) => { + return UmbDomPurify.sanitize(markup, UmbDomPurifyConfig) as string; + }, + }, +}); + +type UmbUfmFilterType = { + alias: string; + filter: ((...args: Array) => string | undefined | null) | undefined; +}; + +export class UmbUfmContext extends UmbContextBase { + #filters = new UmbArrayState([], (x) => x.alias); + public readonly filters = this.#filters.asObservable(); + + constructor(host: UmbControllerHost) { + super(host, UMB_UFM_CONTEXT); + + new UmbExtensionsApiInitializer(this, umbExtensionsRegistry, 'ufmComponent', [], undefined, (controllers) => { + UmbMarked.use( + ufm( + controllers + .map((controller) => { + const ctrl = controller as unknown as UmbExtensionApiInitializer; + if (!ctrl.manifest || !ctrl.api) return; + return { + alias: ctrl.manifest.alias, + marker: ctrl.manifest.meta.marker, + render: ctrl.api.render, + }; + }) + .filter((x) => x) as Array, + ), + ); + }); + + new UmbExtensionsApiInitializer(this, umbExtensionsRegistry, 'ufmFilter', [], undefined, (controllers) => { + const filters = controllers + .map((controller) => { + const ctrl = controller as unknown as UmbExtensionApiInitializer; + if (!ctrl.manifest || !ctrl.api) return null; + return { alias: ctrl.manifest.meta.alias, filter: ctrl.api.filter }; + }) + .filter((x) => x) as Array; + + this.#filters.setValue(filters); + }); + } + + public getFilterByAlias(alias: string) { + return this.#filters.getValue().find((x) => x.alias === alias)?.filter; + } + + public async parse(markdown: string, inline: boolean) { + return !inline ? await UmbMarked.parse(markdown) : await UmbMarked.parseInline(markdown); + } +} + +export const UMB_UFM_CONTEXT = new UmbContextToken('UmbUfmContext'); + +export { UmbUfmContext as api }; diff --git a/src/Umbraco.Web.UI.Client/src/packages/ufm/filters/fallback.filter.ts b/src/Umbraco.Web.UI.Client/src/packages/ufm/filters/fallback.filter.ts new file mode 100644 index 0000000000..ceb8001754 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/ufm/filters/fallback.filter.ts @@ -0,0 +1,9 @@ +import { UmbUfmFilterBase } from '../types.js'; + +class UmbUfmFallbackFilterApi extends UmbUfmFilterBase { + filter(str: string, fallback: string) { + return typeof str !== 'string' || str ? str : fallback; + } +} + +export { UmbUfmFallbackFilterApi as api }; diff --git a/src/Umbraco.Web.UI.Client/src/packages/ufm/filters/lowercase.filter.ts b/src/Umbraco.Web.UI.Client/src/packages/ufm/filters/lowercase.filter.ts new file mode 100644 index 0000000000..bf175a2a65 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/ufm/filters/lowercase.filter.ts @@ -0,0 +1,9 @@ +import { UmbUfmFilterBase } from '../types.js'; + +class UmbUfmLowercaseFilterApi extends UmbUfmFilterBase { + filter(str?: string) { + return str?.toLocaleLowerCase(); + } +} + +export { UmbUfmLowercaseFilterApi as api }; diff --git a/src/Umbraco.Web.UI.Client/src/packages/ufm/filters/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/ufm/filters/manifests.ts new file mode 100644 index 0000000000..c80c5ffd35 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/ufm/filters/manifests.ts @@ -0,0 +1,53 @@ +import type { ManifestUfmFilter } from '@umbraco-cms/backoffice/extension-registry'; + +export const manifests: Array = [ + { + type: 'ufmFilter', + alias: 'Umb.Filter.Fallback', + name: 'Fallback UFM Filter', + api: () => import('./fallback.filter.js'), + meta: { alias: 'fallback' }, + }, + { + type: 'ufmFilter', + alias: 'Umb.Filter.Lowercase', + name: 'Lowercase UFM Filter', + api: () => import('./lowercase.filter.js'), + meta: { alias: 'lowercase' }, + }, + { + type: 'ufmFilter', + alias: 'Umb.Filter.StripHtml', + name: 'Strip HTML UFM Filter', + api: () => import('./strip-html.filter.js'), + meta: { alias: 'strip-html' }, + }, + { + type: 'ufmFilter', + alias: 'Umb.Filter.TitleCase', + name: 'Title Case UFM Filter', + api: () => import('./title-case.filter.js'), + meta: { alias: 'title-case' }, + }, + { + type: 'ufmFilter', + alias: 'Umb.Filter.Truncate', + name: 'Truncate UFM Filter', + api: () => import('./truncate.filter.js'), + meta: { alias: 'truncate' }, + }, + { + type: 'ufmFilter', + alias: 'Umb.Filter.Uppercase', + name: 'Uppercase UFM Filter', + api: () => import('./uppercase.filter.js'), + meta: { alias: 'uppercase' }, + }, + { + type: 'ufmFilter', + alias: 'Umb.Filter.WordLimit', + name: 'Word Limit UFM Filter', + api: () => import('./word-limit.filter.js'), + meta: { alias: 'word-limit' }, + }, +]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/ufm/filters/strip-html.filter.ts b/src/Umbraco.Web.UI.Client/src/packages/ufm/filters/strip-html.filter.ts new file mode 100644 index 0000000000..6d19708e59 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/ufm/filters/strip-html.filter.ts @@ -0,0 +1,15 @@ +import { UmbUfmFilterBase } from '../types.js'; + +class UmbUfmStripHtmlFilterApi extends UmbUfmFilterBase { + filter(value: string | { markup: string } | undefined | null) { + if (!value) return ''; + + const markup = typeof value === 'object' && Object.hasOwn(value, 'markup') ? value.markup : (value as string); + const parser = new DOMParser(); + const doc = parser.parseFromString(markup, 'text/html'); + + return doc.body.textContent ?? ''; + } +} + +export { UmbUfmStripHtmlFilterApi as api }; diff --git a/src/Umbraco.Web.UI.Client/src/packages/ufm/filters/title-case.filter.ts b/src/Umbraco.Web.UI.Client/src/packages/ufm/filters/title-case.filter.ts new file mode 100644 index 0000000000..ab546b7ee3 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/ufm/filters/title-case.filter.ts @@ -0,0 +1,9 @@ +import { UmbUfmFilterBase } from '../types.js'; + +class UmbUfmTitleCaseFilterApi extends UmbUfmFilterBase { + filter(str?: string) { + return str?.replace(/\w\S*/g, (txt) => txt.charAt(0).toUpperCase() + txt.substring(1).toLowerCase()); + } +} + +export { UmbUfmTitleCaseFilterApi as api }; diff --git a/src/Umbraco.Web.UI.Client/src/packages/ufm/filters/truncate.filter.ts b/src/Umbraco.Web.UI.Client/src/packages/ufm/filters/truncate.filter.ts new file mode 100644 index 0000000000..34360ae41d --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/ufm/filters/truncate.filter.ts @@ -0,0 +1,14 @@ +import { UmbUfmFilterBase } from '../types.js'; + +class UmbUfmTruncateFilterApi extends UmbUfmFilterBase { + filter(str: string, length: number, tail?: string) { + if (typeof str !== 'string' || !str.length) return str; + if (tail === 'false') tail = ''; + if (tail === 'true') tail = '…'; + tail = !tail && tail !== '' ? '…' : tail; + + return str.slice(0, length).trim() + tail; + } +} + +export { UmbUfmTruncateFilterApi as api }; diff --git a/src/Umbraco.Web.UI.Client/src/packages/ufm/filters/uppercase.filter.ts b/src/Umbraco.Web.UI.Client/src/packages/ufm/filters/uppercase.filter.ts new file mode 100644 index 0000000000..76af187aa9 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/ufm/filters/uppercase.filter.ts @@ -0,0 +1,9 @@ +import { UmbUfmFilterBase } from '../types.js'; + +class UmbUfmUppercaseFilterApi extends UmbUfmFilterBase { + filter(str?: string) { + return str?.toLocaleUpperCase(); + } +} + +export { UmbUfmUppercaseFilterApi as api }; diff --git a/src/Umbraco.Web.UI.Client/src/packages/ufm/filters/word-limit.filter.ts b/src/Umbraco.Web.UI.Client/src/packages/ufm/filters/word-limit.filter.ts new file mode 100644 index 0000000000..8924386638 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/ufm/filters/word-limit.filter.ts @@ -0,0 +1,10 @@ +import { UmbUfmFilterBase } from '../types.js'; + +class UmbUfmWordLimitFilterApi extends UmbUfmFilterBase { + filter(str: string, limit: number) { + const words = str?.split(/\s+/) ?? []; + return limit && words.length > limit ? words.slice(0, limit).join(' ') : str; + } +} + +export { UmbUfmWordLimitFilterApi as api }; diff --git a/src/Umbraco.Web.UI.Client/src/packages/ufm/index.ts b/src/Umbraco.Web.UI.Client/src/packages/ufm/index.ts index 6ef5cd49bd..56ba93470c 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/ufm/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/ufm/index.ts @@ -1,3 +1,4 @@ -export * from './components/ufm-render/index.js'; -export * from './plugins/marked-ufm.plugin.js'; -export * from './ufm-components/ufm-component-base.js'; +export * from './types.js'; +export * from './components/index.js'; +export * from './contexts/index.js'; +export * from './plugins/index.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/ufm/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/ufm/manifests.ts index ec604e0842..930ae37b3a 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/ufm/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/ufm/manifests.ts @@ -1,18 +1,6 @@ -import type { ManifestUfmComponent } from '@umbraco-cms/backoffice/extension-registry'; +import { manifest as ufmContext } from './contexts/manifest.js'; +import { manifests as ufmComponents } from './components/manifests.js'; +import { manifests as ufmFilters } from './filters/manifests.js'; +import type { ManifestTypes } from '@umbraco-cms/backoffice/extension-registry'; -export const manifests: Array = [ - { - type: 'ufmComponent', - alias: 'Umb.Markdown.LabelValue', - name: 'Label Value UFM Component', - api: () => import('./ufm-components/label-value.component.js'), - meta: { marker: '=' }, - }, - { - type: 'ufmComponent', - alias: 'Umb.Markdown.Localize', - name: 'Localize UFM Component', - api: () => import('./ufm-components/localize.component.js'), - meta: { marker: '#' }, - }, -]; +export const manifests: Array = [ufmContext, ...ufmComponents, ...ufmFilters]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/ufm/plugins/index.ts b/src/Umbraco.Web.UI.Client/src/packages/ufm/plugins/index.ts new file mode 100644 index 0000000000..09836813d3 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/ufm/plugins/index.ts @@ -0,0 +1,2 @@ +export { ufm } from './marked-ufm.plugin.js'; +export type { UfmPlugin, UfmToken } from './marked-ufm.plugin.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/ufm/plugins/marked-ufm.plugin.ts b/src/Umbraco.Web.UI.Client/src/packages/ufm/plugins/marked-ufm.plugin.ts index 65b57912a0..edebdefcca 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/ufm/plugins/marked-ufm.plugin.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/ufm/plugins/marked-ufm.plugin.ts @@ -12,7 +12,8 @@ export interface UfmToken extends Tokens.Generic { /** * - * @param plugins + * @param {Array} plugins - An array of UFM plugins. + * @returns {MarkedExtension} A Marked extension object. */ export function ufm(plugins: Array = []): MarkedExtension { return { diff --git a/src/Umbraco.Web.UI.Client/src/packages/ufm/plugins/marked-ufm.test.ts b/src/Umbraco.Web.UI.Client/src/packages/ufm/plugins/marked-ufm.test.ts index ef01944675..71a2177ddb 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/ufm/plugins/marked-ufm.test.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/ufm/plugins/marked-ufm.test.ts @@ -1,8 +1,9 @@ import { expect } from '@open-wc/testing'; import { ufm } from './marked-ufm.plugin.js'; -import { UmbMarked } from '../index.js'; -import { UmbUfmLabelValueComponent } from '../ufm-components/label-value.component.js'; -import { UmbUfmLocalizeComponent } from '../ufm-components/localize.component.js'; +import { UmbMarked } from '../contexts/ufm.context.js'; +import { UmbUfmContentNameComponent } from '../components/content-name/content-name.component.js'; +import { UmbUfmLabelValueComponent } from '../components/label-value/label-value.component.js'; +import { UmbUfmLocalizeComponent } from '../components/localize/localize.component.js'; describe('UmbMarkedUfm', () => { describe('UFM parsing', () => { @@ -11,12 +12,18 @@ describe('UmbMarkedUfm', () => { { ufm: '{= prop1}', expected: '' }, { ufm: '{= prop1 }', expected: '' }, { ufm: '{{=prop1}}', expected: '{}' }, - { ufm: '{#general_add}', expected: '' }, + { + ufm: '{= prop1 | strip-html | truncate:30}', + expected: '', + }, + { ufm: '{#general_add}', expected: '' }, + { ufm: '{~contentPicker}', expected: '' }, ]; // Manually configuring the UFM components for testing. UmbMarked.use( ufm([ + { alias: 'Umb.Markdown.ContentName', marker: '~', render: new UmbUfmContentNameComponent().render }, { alias: 'Umb.Markdown.LabelValue', marker: '=', render: new UmbUfmLabelValueComponent().render }, { alias: 'Umb.Markdown.Localize', marker: '#', render: new UmbUfmLocalizeComponent().render }, ]), diff --git a/src/Umbraco.Web.UI.Client/src/packages/ufm/types.ts b/src/Umbraco.Web.UI.Client/src/packages/ufm/types.ts new file mode 100644 index 0000000000..94c6966cc1 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/ufm/types.ts @@ -0,0 +1,6 @@ +import type { UmbUfmFilterApi } from '@umbraco-cms/backoffice/extension-registry'; + +export abstract class UmbUfmFilterBase implements UmbUfmFilterApi { + abstract filter(...args: Array): string | undefined | null; + destroy() {} +} diff --git a/src/Umbraco.Web.UI.Client/src/packages/ufm/ufm-components/document-name.component.ts b/src/Umbraco.Web.UI.Client/src/packages/ufm/ufm-components/document-name.component.ts deleted file mode 100644 index 8b7e5ec47e..0000000000 --- a/src/Umbraco.Web.UI.Client/src/packages/ufm/ufm-components/document-name.component.ts +++ /dev/null @@ -1,12 +0,0 @@ -// import { UmbUfmComponentBase } from './ufm-component-base.js'; -// import type { Tokens } from '@umbraco-cms/backoffice/external/marked'; - -// import './document-name.element.js'; - -// export class UmbUfmDocumentNameComponent extends UmbUfmComponentBase { -// render(token: Tokens.Generic) { -// return ``; -// } -// } - -// export { UmbUfmDocumentNameComponent as api }; diff --git a/src/Umbraco.Web.UI.Client/src/packages/ufm/ufm-components/document-name.element.ts b/src/Umbraco.Web.UI.Client/src/packages/ufm/ufm-components/document-name.element.ts deleted file mode 100644 index d4f59d15cc..0000000000 --- a/src/Umbraco.Web.UI.Client/src/packages/ufm/ufm-components/document-name.element.ts +++ /dev/null @@ -1,54 +0,0 @@ -// import { UMB_UFM_RENDER_CONTEXT } from '@umbraco-cms/backoffice/components'; -// import { UmbDocumentItemRepository } from '@umbraco-cms/backoffice/document'; -// import { customElement, property, state } from '@umbraco-cms/backoffice/external/lit'; -// import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; - -// const elementName = 'ufm-document-name'; - -// @customElement(elementName) -// export class UmbUfmDocumentNameElement extends UmbLitElement { -// @property() -// alias?: string; - -// @state() -// private _value?: unknown; - -// #documentRepository = new UmbDocumentItemRepository(this); - -// constructor() { -// super(); - -// this.consumeContext(UMB_UFM_RENDER_CONTEXT, (context) => { -// this.observe( -// context.value, -// async (value) => { -// if (!value) return; - -// const unique = -// this.alias && typeof value === 'object' -// ? ((value as Record)[this.alias] as string) -// : (value as string); - -// if (!unique) return; - -// const { data } = await this.#documentRepository.requestItems([unique]); - -// this._value = data?.[0]?.name; -// }, -// 'observeValue', -// ); -// }); -// } - -// override render() { -// return this._value ?? this.alias; -// } -// } - -// export { UmbUfmDocumentNameElement as element }; - -// declare global { -// interface HTMLElementTagNameMap { -// [elementName]: UmbUfmDocumentNameElement; -// } -// } diff --git a/src/Umbraco.Web.UI.Client/src/packages/ufm/ufm-components/label-value.component.ts b/src/Umbraco.Web.UI.Client/src/packages/ufm/ufm-components/label-value.component.ts deleted file mode 100644 index 7fa6b5d815..0000000000 --- a/src/Umbraco.Web.UI.Client/src/packages/ufm/ufm-components/label-value.component.ts +++ /dev/null @@ -1,13 +0,0 @@ -import type { UfmToken } from '../plugins/marked-ufm.plugin.js'; -import { UmbUfmComponentBase } from './ufm-component-base.js'; - -import './label-value.element.js'; - -export class UmbUfmLabelValueComponent extends UmbUfmComponentBase { - render(token: UfmToken) { - if (!token.text) return; - return ``; - } -} - -export { UmbUfmLabelValueComponent as api }; diff --git a/src/Umbraco.Web.UI.Client/src/packages/ufm/ufm-components/localize.component.ts b/src/Umbraco.Web.UI.Client/src/packages/ufm/ufm-components/localize.component.ts deleted file mode 100644 index 79890f75f5..0000000000 --- a/src/Umbraco.Web.UI.Client/src/packages/ufm/ufm-components/localize.component.ts +++ /dev/null @@ -1,11 +0,0 @@ -import type { UfmToken } from '../plugins/marked-ufm.plugin.js'; -import { UmbUfmComponentBase } from './ufm-component-base.js'; - -export class UmbUfmLocalizeComponent extends UmbUfmComponentBase { - render(token: UfmToken) { - if (!token.text) return; - return ``; - } -} - -export { UmbUfmLocalizeComponent as api }; diff --git a/src/Umbraco.Web.UI.Client/src/packages/ufm/ufm-components/ufm-component-base.ts b/src/Umbraco.Web.UI.Client/src/packages/ufm/ufm-components/ufm-component-base.ts deleted file mode 100644 index 71f552363e..0000000000 --- a/src/Umbraco.Web.UI.Client/src/packages/ufm/ufm-components/ufm-component-base.ts +++ /dev/null @@ -1,7 +0,0 @@ -import type { UfmToken } from '../plugins/marked-ufm.plugin.js'; -import type { UmbUfmComponentApi } from '@umbraco-cms/backoffice/extension-registry'; - -export abstract class UmbUfmComponentBase implements UmbUfmComponentApi { - abstract render(token: UfmToken): string | undefined; - destroy() {} -} From a69c7f460985c7104d8a2c766ecb85cf1e77b724 Mon Sep 17 00:00:00 2001 From: Jacob Overgaard <752371+iOvergaard@users.noreply.github.com> Date: Wed, 11 Sep 2024 11:23:11 +0200 Subject: [PATCH 126/134] feat: add all src/packages/* as workspaces since they have all been converted successfully --- src/Umbraco.Web.UI.Client/package-lock.json | 35 ++++----------------- src/Umbraco.Web.UI.Client/package.json | 30 +----------------- 2 files changed, 7 insertions(+), 58 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/package-lock.json b/src/Umbraco.Web.UI.Client/package-lock.json index 826baef473..9632640fa9 100644 --- a/src/Umbraco.Web.UI.Client/package-lock.json +++ b/src/Umbraco.Web.UI.Client/package-lock.json @@ -9,35 +9,7 @@ "version": "14.3.0", "license": "MIT", "workspaces": [ - "./src/packages/block", - "./src/packages/code-editor", - "./src/packages/core", - "./src/packages/data-type", - "./src/packages/dictionary", - "./src/packages/documents", - "./src/packages/health-check", - "./src/packages/language", - "./src/packages/log-viewer", - "./src/packages/markdown-editor", - "./src/packages/media", - "./src/packages/members", - "./src/packages/models-builder", - "./src/packages/multi-url-picker", - "./src/packages/packages", - "./src/packages/performance-profiling", - "./src/packages/property-editors", - "./src/packages/publish-cache", - "./src/packages/relations", - "./src/packages/search", - "./src/packages/static-file", - "./src/packages/tags", - "./src/packages/telemetry", - "./src/packages/templating", - "./src/packages/tiny-mce", - "./src/packages/ufm", - "./src/packages/umbraco-news", - "./src/packages/user", - "./src/packages/webhook" + "./src/packages/*" ], "dependencies": { "@types/diff": "^5.2.1", @@ -7895,6 +7867,10 @@ "resolved": "src/packages/static-file", "link": true }, + "node_modules/@umbraco-backoffice/sysinfo": { + "resolved": "src/packages/sysinfo", + "link": true + }, "node_modules/@umbraco-backoffice/tag": { "resolved": "src/packages/tags", "link": true @@ -23144,6 +23120,7 @@ "src/packages/static-file": { "name": "@umbraco-backoffice/static-file" }, + "src/packages/sysinfo": {}, "src/packages/tags": { "name": "@umbraco-backoffice/tag" }, diff --git a/src/Umbraco.Web.UI.Client/package.json b/src/Umbraco.Web.UI.Client/package.json index ac79713592..954ca87fe5 100644 --- a/src/Umbraco.Web.UI.Client/package.json +++ b/src/Umbraco.Web.UI.Client/package.json @@ -131,35 +131,7 @@ "url": "https://umbraco.com" }, "workspaces": [ - "./src/packages/block", - "./src/packages/code-editor", - "./src/packages/core", - "./src/packages/data-type", - "./src/packages/dictionary", - "./src/packages/documents", - "./src/packages/health-check", - "./src/packages/language", - "./src/packages/log-viewer", - "./src/packages/markdown-editor", - "./src/packages/media", - "./src/packages/members", - "./src/packages/models-builder", - "./src/packages/multi-url-picker", - "./src/packages/packages", - "./src/packages/performance-profiling", - "./src/packages/property-editors", - "./src/packages/publish-cache", - "./src/packages/relations", - "./src/packages/search", - "./src/packages/static-file", - "./src/packages/tags", - "./src/packages/telemetry", - "./src/packages/templating", - "./src/packages/tiny-mce", - "./src/packages/ufm", - "./src/packages/umbraco-news", - "./src/packages/user", - "./src/packages/webhook" + "./src/packages/*" ], "scripts": { "backoffice:test:e2e": "npx playwright test", From 734be670949714f93ee2bbc9bd7dc9a244ae7367 Mon Sep 17 00:00:00 2001 From: Jacob Overgaard <752371+iOvergaard@users.noreply.github.com> Date: Wed, 11 Sep 2024 11:23:38 +0200 Subject: [PATCH 127/134] feat: improve the loading of sysinfo to accommodate bundling --- .../src/packages/sysinfo/components/sysinfo.element.ts | 2 +- src/Umbraco.Web.UI.Client/src/packages/sysinfo/index.ts | 1 - src/Umbraco.Web.UI.Client/src/packages/sysinfo/manifests.ts | 4 +--- .../src/packages/sysinfo/modals/sysinfo-modal.token.ts | 3 +-- 4 files changed, 3 insertions(+), 7 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 c2dc173622..50295c8b3b 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,4 +1,4 @@ -import { UmbSysinfoRepository } from '../repository/sysinfo.repository.js'; +import { UmbSysinfoRepository } from '../repository/index.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'; 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 6196778a18..736a54915b 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/sysinfo/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/sysinfo/index.ts @@ -1,3 +1,2 @@ -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/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/sysinfo/manifests.ts index fa57d5b840..8d6d1cec1a 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/sysinfo/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/sysinfo/manifests.ts @@ -1,10 +1,8 @@ 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, + alias: 'Umb.Modal.Sysinfo', name: 'Sysinfo Modal', js: () => import('./components/sysinfo.element.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 index d68114a4e3..5d54b75c3c 100644 --- 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 @@ -1,7 +1,6 @@ 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, { +export const UMB_SYSINFO_MODAL = new UmbModalToken('Umb.Modal.Sysinfo', { modal: { type: 'dialog', size: 'medium', From a19f6f9bbfc286a87389389066d2b5fb7b601ab7 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Thu, 12 Sep 2024 11:34:40 +0200 Subject: [PATCH 128/134] more explicit identifier name --- .../language/permissions/language-access.workspace-context.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/language/permissions/language-access.workspace-context.ts b/src/Umbraco.Web.UI.Client/src/packages/language/permissions/language-access.workspace-context.ts index 6264e78f50..656d0377ce 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/language/permissions/language-access.workspace-context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/language/permissions/language-access.workspace-context.ts @@ -56,7 +56,7 @@ export class UmbLanguageAccessWorkspaceContext extends UmbContextBase new UmbVariantId(variant.culture, variant.segment)) || []; // create a list of states for the disallowed languages - const identifier = 'UMB_CULTURE_'; + const identifier = 'UMB_LANGUAGE_PERMISSION_'; const readOnlyStates = variantIds.map((variantId) => { return { unique: identifier + variantId.culture, From 752cbe1c82b3d1e2c2ef868f971b9d8e2234df7e Mon Sep 17 00:00:00 2001 From: Jacob Overgaard <752371+iOvergaard@users.noreply.github.com> Date: Thu, 12 Sep 2024 12:02:13 +0200 Subject: [PATCH 129/134] build: sonarlint connected mode --- src/Umbraco.Web.UI.Client/.sonarlint/connectedMode.json | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 src/Umbraco.Web.UI.Client/.sonarlint/connectedMode.json diff --git a/src/Umbraco.Web.UI.Client/.sonarlint/connectedMode.json b/src/Umbraco.Web.UI.Client/.sonarlint/connectedMode.json new file mode 100644 index 0000000000..e9cefa00a5 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/.sonarlint/connectedMode.json @@ -0,0 +1,4 @@ +{ + "sonarCloudOrganization": "umbraco", + "projectKey": "umbraco_Umbraco.CMS.Backoffice" +} \ No newline at end of file From d80b1ccae51c265dbc427313f24f4881f18c959d Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Thu, 12 Sep 2024 12:25:48 +0200 Subject: [PATCH 130/134] only check variant id --- .../content-property-dataset.context.ts | 5 +---- .../workspace-split-view-variant-selector.element.ts | 8 +------- 2 files changed, 2 insertions(+), 11 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/content/property-dataset-context/content-property-dataset.context.ts b/src/Umbraco.Web.UI.Client/src/packages/core/content/property-dataset-context/content-property-dataset.context.ts index ed41ea70d2..b5b997153c 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/content/property-dataset-context/content-property-dataset.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/content/property-dataset-context/content-property-dataset.context.ts @@ -75,10 +75,7 @@ export class UmbContentPropertyDatasetContext< this.observe( this.#workspace.readOnlyState.states, (states) => { - const isReadOnly = states.some( - (state) => state.unique.startsWith('UMB_CULTURE_') && state.variantId.equal(this.#variantId), - ); - + const isReadOnly = states.some((state) => state.variantId.equal(this.#variantId)); this.#currentVariantCultureIsReadOnly.setValue(isReadOnly); }, 'umbObserveReadOnlyStates', diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/components/workspace-split-view/workspace-split-view-variant-selector.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/components/workspace-split-view/workspace-split-view-variant-selector.element.ts index d5d9766a6b..bd59b6085b 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/components/workspace-split-view/workspace-split-view-variant-selector.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/components/workspace-split-view/workspace-split-view-variant-selector.element.ts @@ -186,13 +186,7 @@ export class UmbWorkspaceSplitViewVariantSelectorElement extends UmbLitElement { #setReadOnlyCultures() { this._readOnlyCultures = this._variantOptions - .filter((variant) => { - const isReadOnly = this._readOnlyStates.some((state) => { - return state.unique.startsWith('UMB_CULTURE_') && state.variantId.compare(variant); - }); - - return isReadOnly; - }) + .filter((variant) => this._readOnlyStates.some((state) => state.variantId.compare(variant))) .map((variant) => variant.culture) .filter((item) => item !== null) as string[]; } From 2b18fe72e259bf4852de35709acdf1400d995f71 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Thu, 12 Sep 2024 13:16:51 +0200 Subject: [PATCH 131/134] rename --- .../block-grid-inline-property-dataset.context.ts | 8 ++++---- .../block-element-property-dataset.context.ts | 10 +++++----- .../content-property-dataset.context.ts | 10 +++++----- .../property-dataset/property-dataset-base-context.ts | 8 ++++---- .../property-dataset-context.interface.ts | 4 ++-- .../core/property/property/property.context.ts | 2 +- .../invariant-workspace-property-dataset-context.ts | 8 ++++---- 7 files changed, 25 insertions(+), 25 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/components/block-grid-block-inline/block-grid-inline-property-dataset.context.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/components/block-grid-block-inline/block-grid-inline-property-dataset.context.ts index e8fdc7c13e..a320f9914a 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/components/block-grid-block-inline/block-grid-inline-property-dataset.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/components/block-grid-block-inline/block-grid-inline-property-dataset.context.ts @@ -11,8 +11,8 @@ import { UmbBooleanState } from '@umbraco-cms/backoffice/observable-api'; export class UmbBlockGridInlinePropertyDatasetContext extends UmbControllerBase implements UmbPropertyDatasetContext { #entryContext: UmbBlockGridEntryContext; - #currentVariantCultureIsReadOnly = new UmbBooleanState(false); - public currentVariantCultureIsReadOnly = this.#currentVariantCultureIsReadOnly.asObservable(); + #readOnly = new UmbBooleanState(false); + public readOnly = this.#readOnly.asObservable(); // default data: @@ -67,7 +67,7 @@ export class UmbBlockGridInlinePropertyDatasetContext extends UmbControllerBase * @returns {*} {boolean} * @memberof UmbBlockGridInlinePropertyDatasetContext */ - getCurrentVariantCultureIsReadOnly(): boolean { - return this.#currentVariantCultureIsReadOnly.getValue(); + getReadOnly(): boolean { + return this.#readOnly.getValue(); } } diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block/workspace/block-element-property-dataset.context.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block/workspace/block-element-property-dataset.context.ts index 4db36b5497..c6e72bcf0c 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block/workspace/block-element-property-dataset.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block/workspace/block-element-property-dataset.context.ts @@ -12,8 +12,8 @@ import { UmbBooleanState } from '@umbraco-cms/backoffice/observable-api'; export class UmbBlockElementPropertyDatasetContext extends UmbControllerBase implements UmbPropertyDatasetContext { #elementManager: UmbBlockElementManager; - #currentVariantCultureIsReadOnly = new UmbBooleanState(false); - public currentVariantCultureIsReadOnly = this.#currentVariantCultureIsReadOnly.asObservable(); + #readOnly = new UmbBooleanState(false); + public readOnly = this.#readOnly.asObservable(); // default data: @@ -41,7 +41,7 @@ export class UmbBlockElementPropertyDatasetContext extends UmbControllerBase imp this.observe( workspace.readOnlyState.isOn, (value) => { - this.#currentVariantCultureIsReadOnly.setValue(value); + this.#readOnly.setValue(value); }, 'umbObserveReadOnlyStates', ); @@ -80,7 +80,7 @@ export class UmbBlockElementPropertyDatasetContext extends UmbControllerBase imp * @returns {*} {boolean} * @memberof UmbBlockGridInlinePropertyDatasetContext */ - getCurrentVariantCultureIsReadOnly(): boolean { - return this.#currentVariantCultureIsReadOnly.getValue(); + getReadOnly(): boolean { + return this.#readOnly.getValue(); } } diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/content/property-dataset-context/content-property-dataset.context.ts b/src/Umbraco.Web.UI.Client/src/packages/core/content/property-dataset-context/content-property-dataset.context.ts index b5b997153c..bbd9cb460d 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/content/property-dataset-context/content-property-dataset.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/content/property-dataset-context/content-property-dataset.context.ts @@ -30,8 +30,8 @@ export class UmbContentPropertyDatasetContext< culture = this.#currentVariant.asObservablePart((x) => x?.culture); segment = this.#currentVariant.asObservablePart((x) => x?.segment); - #currentVariantCultureIsReadOnly = new UmbBooleanState(false); - public currentVariantCultureIsReadOnly = this.#currentVariantCultureIsReadOnly.asObservable(); + #readOnly = new UmbBooleanState(false); + public readOnly = this.#readOnly.asObservable(); getEntityType(): string { return this.#workspace.getEntityType(); @@ -49,8 +49,8 @@ export class UmbContentPropertyDatasetContext< return this.#workspace.getVariant(this.#variantId); } - getCurrentVariantCultureIsReadOnly() { - return this.#currentVariantCultureIsReadOnly.getValue(); + getReadOnly() { + return this.#readOnly.getValue(); } constructor( @@ -76,7 +76,7 @@ export class UmbContentPropertyDatasetContext< this.#workspace.readOnlyState.states, (states) => { const isReadOnly = states.some((state) => state.variantId.equal(this.#variantId)); - this.#currentVariantCultureIsReadOnly.setValue(isReadOnly); + this.#readOnly.setValue(isReadOnly); }, 'umbObserveReadOnlyStates', ); diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/property/property-dataset/property-dataset-base-context.ts b/src/Umbraco.Web.UI.Client/src/packages/core/property/property-dataset/property-dataset-base-context.ts index b3309398d8..b48d71fd3d 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/property/property-dataset/property-dataset-base-context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/property/property-dataset/property-dataset-base-context.ts @@ -24,8 +24,8 @@ export class UmbPropertyDatasetContextBase private _entityType!: string; private _unique!: string; - #currentVariantCultureIsReadOnly = new UmbBooleanState(false); - public currentVariantCultureIsReadOnly = this.#currentVariantCultureIsReadOnly.asObservable(); + #readOnly = new UmbBooleanState(false); + public readOnly = this.#readOnly.asObservable(); getEntityType() { return this._entityType; @@ -85,7 +85,7 @@ export class UmbPropertyDatasetContextBase * @return {*} {boolean} * @memberof UmbBlockGridInlinePropertyDatasetContext */ - getCurrentVariantCultureIsReadOnly(): boolean { - return this.#currentVariantCultureIsReadOnly.getValue(); + getReadOnly(): boolean { + return this.#readOnly.getValue(); } } diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/property/property-dataset/property-dataset-context.interface.ts b/src/Umbraco.Web.UI.Client/src/packages/core/property/property-dataset/property-dataset-context.interface.ts index eea0074e45..c33b0896ed 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/property/property-dataset/property-dataset-context.interface.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/property/property-dataset/property-dataset-context.interface.ts @@ -25,8 +25,8 @@ export interface UmbPropertyDatasetContext extends UmbContext { getName(): string | undefined; readonly name: Observable; - getCurrentVariantCultureIsReadOnly(): boolean; - readonly currentVariantCultureIsReadOnly: Observable; + getReadOnly(): boolean; + readonly readOnly: Observable; // Should it be possible to get the properties as a list of property aliases? //readonly properties: Observable>; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/property/property/property.context.ts b/src/Umbraco.Web.UI.Client/src/packages/core/property/property/property.context.ts index 7ab44fcb52..7454dad43e 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/property/property/property.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/property/property/property.context.ts @@ -128,7 +128,7 @@ export class UmbPropertyContext extends UmbContextBase { + this.observe(this.#datasetContext.readOnly, (value) => { this.#isReadOnly.setValue(value); }); } diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/workspace-property-dataset/invariant-workspace-property-dataset-context.ts b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/workspace-property-dataset/invariant-workspace-property-dataset-context.ts index 224bab9cef..8039e78632 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/workspace-property-dataset/invariant-workspace-property-dataset-context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/workspace-property-dataset/invariant-workspace-property-dataset-context.ts @@ -15,8 +15,8 @@ export class UmbInvariantWorkspacePropertyDatasetContext< extends UmbContextBase implements UmbPropertyDatasetContext, UmbNameablePropertyDatasetContext { - #currentVariantCultureIsReadOnly = new UmbBooleanState(false); - public currentVariantCultureIsReadOnly = this.#currentVariantCultureIsReadOnly.asObservable(); + #readOnly = new UmbBooleanState(false); + public readOnly = this.#readOnly.asObservable(); #workspace: WorkspaceType; @@ -66,7 +66,7 @@ export class UmbInvariantWorkspacePropertyDatasetContext< return this.#workspace.setPropertyValue(propertyAlias, value); } - getCurrentVariantCultureIsReadOnly() { - return this.#currentVariantCultureIsReadOnly.getValue(); + getReadOnly() { + return this.#readOnly.getValue(); } } From 7366f36d8af6ae65e6a6b624832bece05469f137 Mon Sep 17 00:00:00 2001 From: Jacob Overgaard <752371+iOvergaard@users.noreply.github.com> Date: Thu, 12 Sep 2024 13:37:20 +0200 Subject: [PATCH 132/134] chore: update lockfile --- src/Umbraco.Web.UI.Client/package-lock.json | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/package-lock.json b/src/Umbraco.Web.UI.Client/package-lock.json index 9632640fa9..fe1f0406ca 100644 --- a/src/Umbraco.Web.UI.Client/package-lock.json +++ b/src/Umbraco.Web.UI.Client/package-lock.json @@ -23120,7 +23120,9 @@ "src/packages/static-file": { "name": "@umbraco-backoffice/static-file" }, - "src/packages/sysinfo": {}, + "src/packages/sysinfo": { + "name": "@umbraco-backoffice/sysinfo" + }, "src/packages/tags": { "name": "@umbraco-backoffice/tag" }, From b32f524d33159bbda2033e0a15b7445e2000581c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 11 Sep 2024 10:15:22 +0000 Subject: [PATCH 133/134] build(deps): bump serve-static and express Bumps [serve-static](https://github.com/expressjs/serve-static) and [express](https://github.com/expressjs/express). These dependencies needed to be updated together. Updates `serve-static` from 1.15.0 to 1.16.0 - [Release notes](https://github.com/expressjs/serve-static/releases) - [Changelog](https://github.com/expressjs/serve-static/blob/master/HISTORY.md) - [Commits](https://github.com/expressjs/serve-static/compare/v1.15.0...1.16.0) Updates `express` from 4.19.2 to 4.20.0 - [Release notes](https://github.com/expressjs/express/releases) - [Changelog](https://github.com/expressjs/express/blob/master/History.md) - [Commits](https://github.com/expressjs/express/compare/4.19.2...4.20.0) --- updated-dependencies: - dependency-name: serve-static dependency-type: indirect - dependency-name: express dependency-type: indirect ... Signed-off-by: dependabot[bot] --- src/Umbraco.Web.UI.Client/package-lock.json | 124 +++++++++++++------- 1 file changed, 83 insertions(+), 41 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/package-lock.json b/src/Umbraco.Web.UI.Client/package-lock.json index fe1f0406ca..079c57fdc4 100644 --- a/src/Umbraco.Web.UI.Client/package-lock.json +++ b/src/Umbraco.Web.UI.Client/package-lock.json @@ -10421,9 +10421,9 @@ } }, "node_modules/body-parser": { - "version": "1.20.2", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz", - "integrity": "sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==", + "version": "1.20.3", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz", + "integrity": "sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==", "dev": true, "dependencies": { "bytes": "3.1.2", @@ -10434,7 +10434,7 @@ "http-errors": "2.0.0", "iconv-lite": "0.4.24", "on-finished": "2.4.1", - "qs": "6.11.0", + "qs": "6.13.0", "raw-body": "2.5.2", "type-is": "~1.6.18", "unpipe": "1.0.0" @@ -10468,21 +10468,6 @@ "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", "dev": true }, - "node_modules/body-parser/node_modules/qs": { - "version": "6.11.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", - "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", - "dev": true, - "dependencies": { - "side-channel": "^1.0.4" - }, - "engines": { - "node": ">=0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/bplist-parser": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/bplist-parser/-/bplist-parser-0.2.0.tgz", @@ -12978,37 +12963,37 @@ } }, "node_modules/express": { - "version": "4.19.2", - "resolved": "https://registry.npmjs.org/express/-/express-4.19.2.tgz", - "integrity": "sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q==", + "version": "4.20.0", + "resolved": "https://registry.npmjs.org/express/-/express-4.20.0.tgz", + "integrity": "sha512-pLdae7I6QqShF5PnNTCVn4hI91Dx0Grkn2+IAsMTgMIKuQVte2dN9PeGSSAME2FR8anOhVA62QDIUaWVfEXVLw==", "dev": true, "dependencies": { "accepts": "~1.3.8", "array-flatten": "1.1.1", - "body-parser": "1.20.2", + "body-parser": "1.20.3", "content-disposition": "0.5.4", "content-type": "~1.0.4", "cookie": "0.6.0", "cookie-signature": "1.0.6", "debug": "2.6.9", "depd": "2.0.0", - "encodeurl": "~1.0.2", + "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "etag": "~1.8.1", "finalhandler": "1.2.0", "fresh": "0.5.2", "http-errors": "2.0.0", - "merge-descriptors": "1.0.1", + "merge-descriptors": "1.0.3", "methods": "~1.1.2", "on-finished": "2.4.1", "parseurl": "~1.3.3", - "path-to-regexp": "0.1.7", + "path-to-regexp": "0.1.10", "proxy-addr": "~2.0.7", "qs": "6.11.0", "range-parser": "~1.2.1", "safe-buffer": "5.2.1", - "send": "0.18.0", - "serve-static": "1.15.0", + "send": "0.19.0", + "serve-static": "1.16.0", "setprototypeof": "1.2.0", "statuses": "2.0.1", "type-is": "~1.6.18", @@ -13028,6 +13013,15 @@ "ms": "2.0.0" } }, + "node_modules/express/node_modules/encodeurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", + "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, "node_modules/express/node_modules/ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", @@ -16661,10 +16655,13 @@ } }, "node_modules/merge-descriptors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", - "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==", - "dev": true + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz", + "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } }, "node_modules/merge-stream": { "version": "2.0.0", @@ -18521,9 +18518,9 @@ } }, "node_modules/path-to-regexp": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", - "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==", + "version": "0.1.10", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.10.tgz", + "integrity": "sha512-7lf7qcQidTku0Gu3YDPc8DJ1q7OOucfa/BSsIwjuh56VU7katFvuM8hULfkwB3Fns/rsVF7PwPKVw1sl5KQS9w==", "dev": true }, "node_modules/path-type": { @@ -20097,9 +20094,9 @@ } }, "node_modules/send": { - "version": "0.18.0", - "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", - "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", + "version": "0.19.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz", + "integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==", "dev": true, "dependencies": { "debug": "2.6.9", @@ -20142,9 +20139,9 @@ "dev": true }, "node_modules/serve-static": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", - "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", + "version": "1.16.0", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.0.tgz", + "integrity": "sha512-pDLK8zwl2eKaYrs8mrPZBJua4hMplRWJ1tIFksVC3FtBEBnl8dxgeHtsaMS8DhS9i4fLObaon6ABoc4/hQGdPA==", "dev": true, "dependencies": { "encodeurl": "~1.0.2", @@ -20156,6 +20153,51 @@ "node": ">= 0.8.0" } }, + "node_modules/serve-static/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/serve-static/node_modules/debug/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true + }, + "node_modules/serve-static/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true + }, + "node_modules/serve-static/node_modules/send": { + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", + "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", + "dev": true, + "dependencies": { + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "mime": "1.6.0", + "ms": "2.1.3", + "on-finished": "2.4.1", + "range-parser": "~1.2.1", + "statuses": "2.0.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, "node_modules/set-cookie-parser": { "version": "2.7.0", "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.7.0.tgz", From 7d5ef8039b1f27399464be5491dd22c08a191ae4 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 12 Sep 2024 11:39:39 +0000 Subject: [PATCH 134/134] build(deps): bump send and express Bumps [send](https://github.com/pillarjs/send) and [express](https://github.com/expressjs/express). These dependencies needed to be updated together. Updates `send` from 0.18.0 to 0.19.0 - [Release notes](https://github.com/pillarjs/send/releases) - [Changelog](https://github.com/pillarjs/send/blob/master/HISTORY.md) - [Commits](https://github.com/pillarjs/send/compare/0.18.0...0.19.0) Updates `express` from 4.20.0 to 4.21.0 - [Release notes](https://github.com/expressjs/express/releases) - [Changelog](https://github.com/expressjs/express/blob/4.21.0/History.md) - [Commits](https://github.com/expressjs/express/compare/4.20.0...4.21.0) --- updated-dependencies: - dependency-name: send dependency-type: indirect - dependency-name: express dependency-type: indirect ... Signed-off-by: dependabot[bot] --- src/Umbraco.Web.UI.Client/package-lock.json | 98 ++++++--------------- 1 file changed, 28 insertions(+), 70 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/package-lock.json b/src/Umbraco.Web.UI.Client/package-lock.json index 079c57fdc4..32788a9b07 100644 --- a/src/Umbraco.Web.UI.Client/package-lock.json +++ b/src/Umbraco.Web.UI.Client/package-lock.json @@ -12963,9 +12963,9 @@ } }, "node_modules/express": { - "version": "4.20.0", - "resolved": "https://registry.npmjs.org/express/-/express-4.20.0.tgz", - "integrity": "sha512-pLdae7I6QqShF5PnNTCVn4hI91Dx0Grkn2+IAsMTgMIKuQVte2dN9PeGSSAME2FR8anOhVA62QDIUaWVfEXVLw==", + "version": "4.21.0", + "resolved": "https://registry.npmjs.org/express/-/express-4.21.0.tgz", + "integrity": "sha512-VqcNGcj/Id5ZT1LZ/cfihi3ttTn+NJmkli2eZADigjq29qTlWi/hAQ43t/VLPq8+UX06FCEx3ByOYet6ZFblng==", "dev": true, "dependencies": { "accepts": "~1.3.8", @@ -12980,7 +12980,7 @@ "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "etag": "~1.8.1", - "finalhandler": "1.2.0", + "finalhandler": "1.3.1", "fresh": "0.5.2", "http-errors": "2.0.0", "merge-descriptors": "1.0.3", @@ -12989,11 +12989,11 @@ "parseurl": "~1.3.3", "path-to-regexp": "0.1.10", "proxy-addr": "~2.0.7", - "qs": "6.11.0", + "qs": "6.13.0", "range-parser": "~1.2.1", "safe-buffer": "5.2.1", "send": "0.19.0", - "serve-static": "1.16.0", + "serve-static": "1.16.2", "setprototypeof": "1.2.0", "statuses": "2.0.1", "type-is": "~1.6.18", @@ -13028,21 +13028,6 @@ "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", "dev": true }, - "node_modules/express/node_modules/qs": { - "version": "6.11.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", - "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", - "dev": true, - "dependencies": { - "side-channel": "^1.0.4" - }, - "engines": { - "node": ">=0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/express/node_modules/safe-buffer": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", @@ -13336,13 +13321,13 @@ } }, "node_modules/finalhandler": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", - "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.1.tgz", + "integrity": "sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==", "dev": true, "dependencies": { "debug": "2.6.9", - "encodeurl": "~1.0.2", + "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "on-finished": "2.4.1", "parseurl": "~1.3.3", @@ -13362,6 +13347,15 @@ "ms": "2.0.0" } }, + "node_modules/finalhandler/node_modules/encodeurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", + "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, "node_modules/finalhandler/node_modules/ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", @@ -20139,63 +20133,27 @@ "dev": true }, "node_modules/serve-static": { - "version": "1.16.0", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.0.tgz", - "integrity": "sha512-pDLK8zwl2eKaYrs8mrPZBJua4hMplRWJ1tIFksVC3FtBEBnl8dxgeHtsaMS8DhS9i4fLObaon6ABoc4/hQGdPA==", + "version": "1.16.2", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.2.tgz", + "integrity": "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==", "dev": true, "dependencies": { - "encodeurl": "~1.0.2", + "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "parseurl": "~1.3.3", - "send": "0.18.0" + "send": "0.19.0" }, "engines": { "node": ">= 0.8.0" } }, - "node_modules/serve-static/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/serve-static/node_modules/debug/node_modules/ms": { + "node_modules/serve-static/node_modules/encodeurl": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "dev": true - }, - "node_modules/serve-static/node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true - }, - "node_modules/serve-static/node_modules/send": { - "version": "0.18.0", - "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", - "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", + "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", "dev": true, - "dependencies": { - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "1.2.0", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "fresh": "0.5.2", - "http-errors": "2.0.0", - "mime": "1.6.0", - "ms": "2.1.3", - "on-finished": "2.4.1", - "range-parser": "~1.2.1", - "statuses": "2.0.1" - }, "engines": { - "node": ">= 0.8.0" + "node": ">= 0.8" } }, "node_modules/set-cookie-parser": {