diff --git a/Source/PlasticSourceControl/Private/PlasticSourceControlMenu.cpp b/Source/PlasticSourceControl/Private/PlasticSourceControlMenu.cpp index 5d74c4ad..c2475f29 100644 --- a/Source/PlasticSourceControl/Private/PlasticSourceControlMenu.cpp +++ b/Source/PlasticSourceControl/Private/PlasticSourceControlMenu.cpp @@ -516,11 +516,7 @@ void FPlasticSourceControlMenu::VisitSupportURLClicked() const void FPlasticSourceControlMenu::VisitLockRulesURLClicked(const FString InOrganizationName) const { - const FString OrganizationLockRulesURL = FString::Printf( - TEXT("https://dashboard.unity3d.com/devops/organizations/default/plastic-scm/organizations/%s/lock-rules"), - *InOrganizationName - ); - FPlatformProcess::LaunchURL(*OrganizationLockRulesURL, NULL, NULL); + PlasticSourceControlUtils::OpenLockRulesInCloudDashboard(InOrganizationName); } void FPlasticSourceControlMenu::OpenDeskoptApp() const diff --git a/Source/PlasticSourceControl/Private/PlasticSourceControlUtils.cpp b/Source/PlasticSourceControl/Private/PlasticSourceControlUtils.cpp index c9da7562..f971d6e3 100644 --- a/Source/PlasticSourceControl/Private/PlasticSourceControlUtils.cpp +++ b/Source/PlasticSourceControl/Private/PlasticSourceControlUtils.cpp @@ -93,6 +93,15 @@ FString FindDesktopApplicationPath() return DesktopAppPath; } +void OpenLockRulesInCloudDashboard(const FString& InOrganizationName) +{ + const FString OrganizationLockRulesURL = FString::Printf( + TEXT("https://dashboard.unity3d.com/devops/organizations/default/plastic-scm/organizations/%s/lock-rules"), + *InOrganizationName + ); + FPlatformProcess::LaunchURL(*OrganizationLockRulesURL, NULL, NULL); +} + // Find the root of the workspace, looking from the provided path and upward in its parent directories. bool GetWorkspacePath(const FString& InPath, FString& OutWorkspaceRoot) { diff --git a/Source/PlasticSourceControl/Private/PlasticSourceControlUtils.h b/Source/PlasticSourceControl/Private/PlasticSourceControlUtils.h index c902fcc9..d8457680 100644 --- a/Source/PlasticSourceControl/Private/PlasticSourceControlUtils.h +++ b/Source/PlasticSourceControl/Private/PlasticSourceControlUtils.h @@ -55,6 +55,13 @@ FString FindPlasticBinaryPath(); */ FString FindDesktopApplicationPath(); +/** + * Open the Unity Cloud Dashboard on the page to show and manage Lock Rules. + * + * @param InOrganizationName Name of the organization to use, from the server URL + */ +void OpenLockRulesInCloudDashboard(const FString& InOrganizationName); + /** * Find the root of the Plastic workspace, looking from the GameDir and upward in its parent directories * @param InPathToGameDir The path to the Game Directory diff --git a/Source/PlasticSourceControl/Private/SPlasticSourceControlLocksWidget.cpp b/Source/PlasticSourceControl/Private/SPlasticSourceControlLocksWidget.cpp index 9ffbd839..9c9ec36e 100644 --- a/Source/PlasticSourceControl/Private/SPlasticSourceControlLocksWidget.cpp +++ b/Source/PlasticSourceControl/Private/SPlasticSourceControlLocksWidget.cpp @@ -44,6 +44,8 @@ void SPlasticSourceControlLocksWidget::Construct(const FArguments& InArgs) CurrentBranchName = FPlasticSourceControlModule::Get().GetProvider().GetBranchName(); + const FString OrganizationName = FPlasticSourceControlModule::Get().GetProvider().GetCloudOrganization(); + SearchTextFilter = MakeShared>(TTextFilter::FItemToStringArray::CreateSP(this, &SPlasticSourceControlLocksWidget::PopulateItemSearchStrings)); SearchTextFilter->OnChanged().AddSP(this, &SPlasticSourceControlLocksWidget::OnRefreshUI); @@ -63,25 +65,77 @@ void SPlasticSourceControlLocksWidget::Construct(const FArguments& InArgs) [ SNew(SHorizontalBox) +SHorizontalBox::Slot() - .HAlign(HAlign_Left) - .VAlign(VAlign_Center) - .AutoWidth() + .FillWidth(1.0f) [ - CreateToolBar() - ] - +SHorizontalBox::Slot() - .MaxWidth(10.0f) - [ - SNew(SSpacer) + SNew(SHorizontalBox) + +SHorizontalBox::Slot() + .HAlign(HAlign_Left) + .VAlign(VAlign_Center) + .AutoWidth() + [ + CreateToolBar() + ] + +SHorizontalBox::Slot() + .MaxWidth(10.0f) + [ + SNew(SSpacer) + ] + +SHorizontalBox::Slot() + .VAlign(VAlign_Center) + .MaxWidth(300.0f) + [ + SAssignNew(FileSearchBox, SSearchBox) + .HintText(LOCTEXT("SearchLocks", "Search Locks")) + .ToolTipText(LOCTEXT("PlasticLocksSearch_Tooltip", "Filter the list of locks by keyword.")) + .OnTextChanged(this, &SPlasticSourceControlLocksWidget::OnSearchTextChanged) + ] ] +SHorizontalBox::Slot() + .HAlign(HAlign_Right) .VAlign(VAlign_Center) - .MaxWidth(300.0f) + .AutoWidth() [ - SAssignNew(FileSearchBox, SSearchBox) - .HintText(LOCTEXT("SearchLocks", "Search Locks")) - .ToolTipText(LOCTEXT("PlasticLocksSearch_Tooltip", "Filter the list of locks by keyword.")) - .OnTextChanged(this, &SPlasticSourceControlLocksWidget::OnSearchTextChanged) + // Button to Configure Lock Rules in the cloud (only enabled for a cloud repository) + SNew(SButton) + .ContentPadding(FMargin(6.0f, 0.0f)) + .IsEnabled(!OrganizationName.IsEmpty()) + .ToolTipText(OrganizationName.IsEmpty() ? + LOCTEXT("PlasticLockRulesURLTooltipDisabled", "Web link to the Unity Dashboard disabled. Only available for Cloud repositories.") : + LOCTEXT("PlasticLockRulesURLTooltipEnabled", "Navigate to lock rules configuration page in the Unity Dashboard.")) +#if ENGINE_MAJOR_VERSION == 5 && ENGINE_MINOR_VERSION >= 1 + .ButtonStyle(FAppStyle::Get(), "SimpleButton") +#else + .ButtonStyle(FEditorStyle::Get(), "SimpleButton") +#endif + .OnClicked(this, &SPlasticSourceControlLocksWidget::OnConfigureLockRulesClicked, OrganizationName) + [ + SNew(SHorizontalBox) + +SHorizontalBox::Slot() + .AutoWidth() + .VAlign(VAlign_Center) + .HAlign(HAlign_Center) + [ + SNew(SImage) +#if ENGINE_MAJOR_VERSION == 5 && ENGINE_MINOR_VERSION >= 1 + .Image(FAppStyle::GetBrush("PropertyWindow.Locked")) +#else + .Image(FEditorStyle::GetBrush("PropertyWindow.Locked")) +#endif + ] + +SHorizontalBox::Slot() + .AutoWidth() + .VAlign(VAlign_Center) + .Padding(5.0f, 0.0f, 0.0f, 0.0f) + [ + SNew(STextBlock) +#if ENGINE_MAJOR_VERSION == 5 && ENGINE_MINOR_VERSION >= 1 + .TextStyle(&FAppStyle::Get().GetWidgetStyle("NormalText")) +#else + .TextStyle(&FEditorStyle::Get().GetWidgetStyle("NormalText")) +#endif + .Text(LOCTEXT("ConfigureLockRules", "Configure rules")) + ] + ] ] ] ] @@ -591,6 +645,12 @@ TSharedPtr SPlasticSourceControlLocksWidget::OnOpenContextMenu() return ToolMenus->GenerateWidget(Menu); } +FReply SPlasticSourceControlLocksWidget::OnConfigureLockRulesClicked(const FString InOrganizationName) +{ + PlasticSourceControlUtils::OpenLockRulesInCloudDashboard(InOrganizationName); + return FReply::Handled(); +} + void SPlasticSourceControlLocksWidget::OnReleaseLocksClicked(TArray InSelectedLocks) { ExecuteUnlock(MoveTemp(InSelectedLocks), false); diff --git a/Source/PlasticSourceControl/Private/SPlasticSourceControlLocksWidget.h b/Source/PlasticSourceControl/Private/SPlasticSourceControlLocksWidget.h index f7869327..fe0555d5 100644 --- a/Source/PlasticSourceControl/Private/SPlasticSourceControlLocksWidget.h +++ b/Source/PlasticSourceControl/Private/SPlasticSourceControlLocksWidget.h @@ -48,6 +48,8 @@ class SPlasticSourceControlLocksWidget : public SCompoundWidget TSharedPtr OnOpenContextMenu(); + FReply OnConfigureLockRulesClicked(const FString InOrganizationName); + void OnReleaseLocksClicked(TArray InSelectedLocks); void OnRemoveLocksClicked(TArray InSelectedLocks); void ExecuteUnlock(TArray&& InSelectedLocks, const bool bInRemove);