Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SLVS-1729 Promote SQC free plan inside the IDE extensions #5940

Merged
merged 10 commits into from
Jan 9, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions src/ConnectedMode.UnitTests/UI/ConnectedModeServicesTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,26 +18,26 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/

using SonarLint.VisualStudio.Core;
using SonarLint.VisualStudio.TestInfrastructure;
using SonarLint.VisualStudio.ConnectedMode.UI;
using SonarLint.VisualStudio.Core;
using SonarLint.VisualStudio.Core.Binding;
using SonarLint.VisualStudio.Core.Telemetry;
using SonarLint.VisualStudio.TestInfrastructure;

namespace SonarLint.VisualStudio.ConnectedMode.UnitTests.UI;

[TestClass]
public class ConnectedModeServicesTests
{
[TestMethod]
public void MefCtor_CheckIsExported()
{
public void MefCtor_CheckIsExported() =>
MefTestHelpers.CheckTypeCanBeImported<ConnectedModeServices, IConnectedModeServices>(
MefTestHelpers.CreateExport<IBrowserService>(),
MefTestHelpers.CreateExport<IThreadHandling>(),
MefTestHelpers.CreateExport<ISlCoreConnectionAdapter>(),
MefTestHelpers.CreateExport<IConfigurationProvider>(),
MefTestHelpers.CreateExport<IServerConnectionsRepositoryAdapter>(),
MefTestHelpers.CreateExport<IMessageBox>(),
MefTestHelpers.CreateExport<ITelemetryManager>(),
MefTestHelpers.CreateExport<ILogger>());
}
}
7 changes: 5 additions & 2 deletions src/ConnectedMode/UI/ConnectedModeServices.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,9 @@
*/

using System.ComponentModel.Composition;
using SonarLint.VisualStudio.ConnectedMode.Shared;
using SonarLint.VisualStudio.Core;
using SonarLint.VisualStudio.Core.Binding;
using SonarLint.VisualStudio.Core.Telemetry;

namespace SonarLint.VisualStudio.ConnectedMode.UI;

Expand All @@ -34,6 +34,7 @@ public interface IConnectedModeServices
public IConfigurationProvider ConfigurationProvider { get; }
public IServerConnectionsRepositoryAdapter ServerConnectionsRepositoryAdapter { get; }
public IMessageBox MessageBox { get; }
public ITelemetryManager TelemetryManager { get; }
}

[Export(typeof(IConnectedModeServices))]
Expand All @@ -46,11 +47,13 @@ public class ConnectedModeServices(
IConfigurationProvider configurationProvider,
IServerConnectionsRepositoryAdapter serverConnectionsRepositoryAdapter,
IMessageBox messageBox,
ILogger logger)
ILogger logger,
ITelemetryManager telemetryManager)
: IConnectedModeServices
{
public IServerConnectionsRepositoryAdapter ServerConnectionsRepositoryAdapter { get; } = serverConnectionsRepositoryAdapter;
public IMessageBox MessageBox { get; } = messageBox;
public ITelemetryManager TelemetryManager { get; } = telemetryManager;
public IBrowserService BrowserService { get; } = browserService;
public IThreadHandling ThreadHandling { get; } = threadHandling;
public ILogger Logger { get; } = logger;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ private async void NewConnection_Clicked(object sender, RoutedEventArgs e)

private ConnectionInfo GetTransientConnection()
{
var serverSelectionDialog = new ServerSelectionDialog(connectedModeServices.BrowserService);
var serverSelectionDialog = new ServerSelectionDialog(connectedModeServices.BrowserService, connectedModeServices.TelemetryManager);
return serverSelectionDialog.ShowDialog(this) != true ? null : serverSelectionDialog.ViewModel.CreateTransientConnectionInfo();
}

Expand Down
20 changes: 1 addition & 19 deletions src/ConnectedMode/UI/Resources/UiResources.Designer.cs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 1 addition & 7 deletions src/ConnectedMode/UI/Resources/UiResources.resx
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@
<value>Choose a connection type</value>
</data>
<data name="ConnectionDiscoveringText" xml:space="preserve">
<value>Discover which connection is best for your team </value>
<value>Explore SonarQube Cloud with our </value>
</data>
<data name="CredentialsLabel" xml:space="preserve">
<value>Credentials</value>
Expand Down Expand Up @@ -183,12 +183,6 @@
<data name="SonarCloudDescription" xml:space="preserve">
<value>A Software-as-a-Service (Saas) tool that easily integrates into the cloud DevOps platforms and extends the CI/CD workflow to systematically help developers and organizations deliver CleanCode.</value>
</data>
<data name="FreeSonarCloudOfferDescription" xml:space="preserve">
<value>is entirely free for open source projects</value>
</data>
<data name="FreeSonarQubeOfferDescription" xml:space="preserve">
<value>SonarQube Server offers a free</value>
</data>
<data name="SonarQubeAccountSecurityUrl" xml:space="preserve">
<value>account/security</value>
</data>
Expand Down
16 changes: 4 additions & 12 deletions src/ConnectedMode/UI/ServerSelection/ServerSelectionDialog.xaml
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
<Window x:Class="SonarLint.VisualStudio.ConnectedMode.UI.ServerSelection.ServerSelectionDialog"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:links="clr-namespace:SonarLint.VisualStudio.Core;assembly=SonarLint.VisualStudio.Core"
xmlns:res="clr-namespace:SonarLint.VisualStudio.ConnectedMode.UI.Resources"
xmlns:ui="clr-namespace:SonarLint.VisualStudio.ConnectedMode.UI"
xmlns:wpf="clr-namespace:SonarLint.VisualStudio.Core.WPF;assembly=SonarLint.VisualStudio.Core"
Expand Down Expand Up @@ -35,7 +34,7 @@
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>

<Grid Grid.Row="0" Margin="10, 0">
<Grid Grid.Row="0" Margin="10">
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
Expand All @@ -48,13 +47,9 @@
</RadioButton>
</StackPanel>
<TextBlock Grid.Row="1" Text="{x:Static res:UiResources.SonarCloudDescription}" Margin="10, 0"/>
<TextBlock Grid.Row="2" Margin="10,10,10,0">
<Hyperlink NavigateUri="https://www.sonarsource.com/products/sonarcloud/" RequestNavigate="ViewWebsite">SonarQube Cloud</Hyperlink>
<Run Text="{x:Static res:UiResources.FreeSonarCloudOfferDescription}"></Run>
</TextBlock>
</Grid>

<Grid Grid.Row="1" Margin="10, 0">
<Grid Grid.Row="1" Margin="10">
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
Expand All @@ -68,10 +63,6 @@
</RadioButton>
</StackPanel>
<TextBlock Grid.Row="1" Text="{x:Static res:UiResources.SonarQubeDescription}" Margin="10, 0"/>
<TextBlock Grid.Row="2" Margin="10,10,10,0">
<Run Text="{x:Static res:UiResources.FreeSonarQubeOfferDescription}"></Run>
<Hyperlink NavigateUri="https://www.sonarsource.com/plans-and-pricing/sonarqube/" RequestNavigate="ViewWebsite">Community Build</Hyperlink>
</TextBlock>

<Grid x:Name="QubeUrlGrid" Grid.Row="3" Margin="10" IsEnabled="{Binding Path=IsSonarQubeSelected}">
<Grid.RowDefinitions>
Expand Down Expand Up @@ -117,7 +108,8 @@
</GroupBox>

<TextBlock Grid.Row="1" Text="{x:Static res:UiResources.ConnectionDiscoveringText}" Margin="0,20">
<Hyperlink NavigateUri="{x:Static links:DocumentationLinks.ConnectedModeUri}" RequestNavigate="ViewWebsite">here</Hyperlink>
<!-- NavigateUri has to be filled, otherwise the RequestNavigate won't be triggered. The real Uri is calculated in the event handler -->
<Hyperlink NavigateUri="https://www.sonarsource.com" RequestNavigate="FreeSonaQubeCloudFreeTier_OnRequestNavigate">free tier</Hyperlink>
</TextBlock>

<Grid HorizontalAlignment="Right" Grid.Row="2">
Expand Down
44 changes: 24 additions & 20 deletions src/ConnectedMode/UI/ServerSelection/ServerSelectionDialog.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,31 +22,35 @@
using System.Windows;
using System.Windows.Navigation;
using SonarLint.VisualStudio.Core;
using SonarLint.VisualStudio.Core.Telemetry;

namespace SonarLint.VisualStudio.ConnectedMode.UI.ServerSelection
namespace SonarLint.VisualStudio.ConnectedMode.UI.ServerSelection;

[ExcludeFromCodeCoverage] // UI, not really unit-testable
public partial class ServerSelectionDialog : Window
{
[ExcludeFromCodeCoverage] // UI, not really unit-testable
public partial class ServerSelectionDialog : Window
{
private readonly IBrowserService browserService;
private readonly IBrowserService browserService;
private readonly ITelemetryManager telemetryManager;

public ServerSelectionDialog(IBrowserService browserService)
{
this.browserService = browserService;
InitializeComponent();
}
public ServerSelectionViewModel ViewModel { get; } = new();

public ServerSelectionViewModel ViewModel { get; } = new();
public ServerSelectionDialog(IBrowserService browserService, ITelemetryManager telemetryManager)
{
this.browserService = browserService;
this.telemetryManager = telemetryManager;
InitializeComponent();
}

private void ViewWebsite(object sender, RequestNavigateEventArgs e)
{
browserService.Navigate(e.Uri.AbsoluteUri);
}
private void FreeSonaQubeCloudFreeTier_OnRequestNavigate(object sender, RequestNavigateEventArgs e)
{
var telemetryLinkId = TelemetryLinks.SonarQubeCloudFreeSignUpId;
browserService.Navigate(TelemetryLinks.LinkIdToUrls[telemetryLinkId]);
telemetryManager.LinkClicked(telemetryLinkId);
}

private void OkButton_OnClick(object sender, RoutedEventArgs e)
{
DialogResult = true;
Close();
}
private void OkButton_OnClick(object sender, RoutedEventArgs e)
{
DialogResult = true;
Close();
}
}
26 changes: 16 additions & 10 deletions src/Core/Telemetry/ITelemetryManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,21 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/

namespace SonarLint.VisualStudio.Core.Telemetry
namespace SonarLint.VisualStudio.Core.Telemetry;

public interface ITelemetryManager
{
public interface ITelemetryManager
{
SlCoreTelemetryStatus GetStatus();
void OptOut();
void OptIn();
void LanguageAnalyzed(string languageKey, TimeSpan analysisTime);
void TaintIssueInvestigatedLocally();
void TaintIssueInvestigatedRemotely();
}
SlCoreTelemetryStatus GetStatus();

void OptOut();

void OptIn();

void LanguageAnalyzed(string languageKey, TimeSpan analysisTime);

void TaintIssueInvestigatedLocally();

void TaintIssueInvestigatedRemotely();

void LinkClicked(string linkId);
}
28 changes: 28 additions & 0 deletions src/Core/Telemetry/TelemetryLinks.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/*
* SonarLint for Visual Studio
* Copyright (C) 2016-2025 SonarSource SA
* mailto:info AT sonarsource DOT com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/

namespace SonarLint.VisualStudio.Core.Telemetry;

public static class TelemetryLinks
{
public const string SonarQubeCloudFreeSignUpId = "sonarqubeCloudFreeSignUp";

public static Dictionary<string, string> LinkIdToUrls { get; } = new() { { SonarQubeCloudFreeSignUpId, "https://www.sonarsource.com/products/sonarcloud/signup-free/" } };
}
Loading
Loading