diff --git a/e2e/Sandbox/DashboardCreators/PostgresqlDashboard.cs b/e2e/Sandbox/DashboardCreators/PostgresqlDashboard.cs new file mode 100644 index 00000000..4d2c01c1 --- /dev/null +++ b/e2e/Sandbox/DashboardCreators/PostgresqlDashboard.cs @@ -0,0 +1,61 @@ +using Reveal.Sdk.Dom; +using Reveal.Sdk.Dom.Data; +using Reveal.Sdk.Dom.Filters; +using Reveal.Sdk.Dom.Visualizations; +using System.Collections.Generic; + +namespace Sandbox.DashboardFactories +{ + internal class PostgresqlDashboard : IDashboardCreator + { + public string Name => "PostgresQL Data Source"; + + public RdashDocument CreateDashboard() + { + DataSource _postgresDataSource = new PostgreSQLDataSource() + { + Id = "Postgres", + Title = "Postgres Data Source", + Subtitle = "The Data Source for Postgres", + Host = "revealdb01.infragistics.local", + Database = "northwind", + Port = 5432 + }; + + var postgresDataSourceItem = new PostgreSqlDataSourceItem("Employees", _postgresDataSource) + { + Title = "Postgres Employee", + Subtitle = "Postgres DS Item for Employee", + Database = "northwind", + Table = "employees", + Fields = new List + { + new NumberField("ReportsTo"), + new NumberField("EmployeeID"), + new TextField("Country"), + } + }; + + var document = new RdashDocument() + { + Title = "PostgreSQL", + Description = "Example for Postgresql", + UseAutoLayout = false, + }; + + var dateFilter = new DashboardDateFilter("My Date Filter"); + document.Filters.Add(dateFilter); + + var countryFilter = new DashboardDataFilter("Country", postgresDataSourceItem); + document.Filters.Add(countryFilter); + + document.Visualizations.Add(new ColumnChartVisualization("Employees report", postgresDataSourceItem) + .SetLabel("ReportsTo") + .SetValue("EmployeeID") + .ConnectDashboardFilters(countryFilter) + .SetPosition(20, 11)); + + return document; + } + } +} diff --git a/e2e/Sandbox/MainWindow.xaml b/e2e/Sandbox/MainWindow.xaml index a81abd25..52631991 100644 --- a/e2e/Sandbox/MainWindow.xaml +++ b/e2e/Sandbox/MainWindow.xaml @@ -27,4 +27,4 @@ SaveDashboard="RevealView_SaveDashboard"/> - + \ No newline at end of file diff --git a/e2e/Sandbox/MainWindow.xaml.cs b/e2e/Sandbox/MainWindow.xaml.cs index ddd11bf5..fa48b06b 100644 --- a/e2e/Sandbox/MainWindow.xaml.cs +++ b/e2e/Sandbox/MainWindow.xaml.cs @@ -49,22 +49,22 @@ public partial class MainWindow : Window new HealthcareDashboard(), new ManufacturingDashboard(), new MarketingDashboard(), + new MySqlDataSourceDashboards(), + new PostgresqlDashboard(), new RestDataSourceDashboard(), new SalesDashboard(), new SqlServerDataSourceDashboards(), - new MySqlDataSourceDashboards() }; public MainWindow() { InitializeComponent(); - RevealSdkSettings.DataSourceProvider = new Sandbox.RevealSDK.DataSourceProvider(); + RevealSdkSettings.DataSourceProvider = new DataSourceProvider(); RevealSdkSettings.AuthenticationProvider = new AuthenticationProvider(); - RevealSdkSettings.DataSources.RegisterMicrosoftSqlServer().RegisterMicrosoftAnalysisServices(); + RevealSdkSettings.DataSources.RegisterMicrosoftSqlServer().RegisterMicrosoftAnalysisServices().RegisterPostgreSQL(); RevealSdkSettings.DataSources.RegisterMySql(); - LoadDashboards(); _revealView.LinkedDashboardProvider = (string dashboardId, string linkTitle) => @@ -162,6 +162,7 @@ private void RevealView_DataSourcesRequested(object sender, DataSourcesRequested sqlDSI.Table = "Customers"; dsi.Add(sqlDSI); + //var webDS = new RVWebResourceDataSource(); //webDS.UseAnonymousAuthentication = true; //webDS.Title = "Web Resource"; diff --git a/e2e/Sandbox/Properties/Settings.Designer.cs b/e2e/Sandbox/Properties/Settings.Designer.cs index 6ec3e987..67fdb056 100644 --- a/e2e/Sandbox/Properties/Settings.Designer.cs +++ b/e2e/Sandbox/Properties/Settings.Designer.cs @@ -1,38 +1,38 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by a tool. -// Runtime Version:4.0.30319.42000 -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -namespace Sandbox.Properties { - - - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "17.12.0.0")] - internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { - - private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); - - public static Settings Default { - get { - return defaultInstance; - } - } - - [global::System.Configuration.UserScopedSettingAttribute()] - [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - [global::System.Configuration.DefaultSettingValueAttribute("")] - public string LastSelectedDashboard { - get { - return ((string)(this["LastSelectedDashboard"])); - } - set { - this["LastSelectedDashboard"] = value; - } - } - } -} +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace Sandbox.Properties { + + + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "17.12.0.0")] + internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { + + private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); + + public static Settings Default { + get { + return defaultInstance; + } + } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("")] + public string LastSelectedDashboard { + get { + return ((string)(this["LastSelectedDashboard"])); + } + set { + this["LastSelectedDashboard"] = value; + } + } + } +} diff --git a/e2e/Sandbox/Reveal/AuthenticationProvider.cs b/e2e/Sandbox/Reveal/AuthenticationProvider.cs index b7c4385c..920faf30 100644 --- a/e2e/Sandbox/Reveal/AuthenticationProvider.cs +++ b/e2e/Sandbox/Reveal/AuthenticationProvider.cs @@ -1,4 +1,4 @@ -using Reveal.Sdk.Data; +using Reveal.Sdk.Data; using Reveal.Sdk.Data.Microsoft.AnalysisServices; using Reveal.Sdk.Data.Microsoft.SqlServer; using Reveal.Sdk.Data.MySql; @@ -24,6 +24,10 @@ public Task ResolveCredentialsAsync(RVDashboardDataSour { userCredential = new RVUsernamePasswordDataSourceCredential("username", "password"); } + else if (dataSource is RVPostgresDataSource) + { + userCredential = new RVUsernamePasswordDataSourceCredential("postgres", "postgres"); + } return Task.FromResult(userCredential); } } diff --git a/src/Reveal.Sdk.Dom.Tests/Data/DataSourceFixture.cs b/src/Reveal.Sdk.Dom.Tests/Data/DataSourceFixture.cs index e7485998..f7d8582d 100644 --- a/src/Reveal.Sdk.Dom.Tests/Data/DataSourceFixture.cs +++ b/src/Reveal.Sdk.Dom.Tests/Data/DataSourceFixture.cs @@ -93,7 +93,7 @@ public void GetDefaultRefreshRate_ReturnSameValue_WithSetValue() // Assert Assert.Equal(expectedValue, actualValue); - Assert.Equal(expectedValue, dataSource.Properties.GetValue("DefaultRefreshRate")); + Assert.Equal(expectedValue, dataSource.Settings.GetValue("DefaultRefreshRate")); } [Fact] diff --git a/src/Reveal.Sdk.Dom.Tests/Data/DataSourceItems/PostgreSqlDataSourceItemFixture.cs b/src/Reveal.Sdk.Dom.Tests/Data/DataSourceItems/PostgreSqlDataSourceItemFixture.cs index abff0791..228d9939 100644 --- a/src/Reveal.Sdk.Dom.Tests/Data/DataSourceItems/PostgreSqlDataSourceItemFixture.cs +++ b/src/Reveal.Sdk.Dom.Tests/Data/DataSourceItems/PostgreSqlDataSourceItemFixture.cs @@ -1,3 +1,4 @@ +using Newtonsoft.Json.Linq; using Reveal.Sdk.Dom.Core.Extensions; using Reveal.Sdk.Dom.Data; using Xunit; @@ -7,23 +8,91 @@ namespace Reveal.Sdk.Dom.Tests.Data.DataSourceItems public class PostgreSqlDataSourceItemFixture { [Theory] - [InlineData("Test Item")] - [InlineData(null)] - public void Constructor_SetsTitleAndDataSource_WhenCalled(string title) + [InlineData("DS Item Title", "DS Item Title", "DS Title", "DS Title")] + [InlineData("DS Item Title", "DS Item Title", null, "DS Item Title")] + public void Constructor_CreatePostgresDSItem_WithTitleAndPostgresDataSource(string dsItemTitle, string expectedDSItemTitle, string dsTitle, string expectedDSTitle) { // Arrange - var dataSource = new PostgreSQLDataSource(); + var dataSource = new PostgreSQLDataSource() { Title = dsTitle}; // Act - var item = new PostgreSqlDataSourceItem(title, dataSource); + var item = new PostgreSqlDataSourceItem(dsItemTitle, dataSource); // Assert - Assert.Equal(title, item.Title); - Assert.Equal(dataSource, item.DataSource); + Assert.Equal(expectedDSItemTitle, item.Title); + Assert.Equal(expectedDSTitle, item.DataSource.Title); + Assert.Equal(dataSource.Id, item.DataSource.Id); + Assert.Equal(dataSource.Id, item.DataSourceId); + Assert.Same(dataSource, item.DataSource); + } + + [Theory] + [InlineData("DS Item Title", "DS Item Title", "DS Title", "DS Title")] + [InlineData("DS Item Title", "DS Item Title", null, "DS Item Title")] + public void Constructor_CreatePostgresDSItem_WithTitleAndDataSource(string dsItemTitle, string expectedDSItemTitle, string dsTitle, string expectedDSTitle) + { + // Arrange + var dataSource = new DataSource() { Title = dsTitle }; + + // Act + var item = new PostgreSqlDataSourceItem(dsItemTitle, dataSource); + + // Assert + Assert.Equal(expectedDSItemTitle, item.Title); + Assert.Equal(expectedDSTitle, item.DataSource.Title); + Assert.Equal(dataSource.Id, item.DataSource.Id); + Assert.Equal(dataSource.Id, item.DataSourceId); + Assert.IsType(item.DataSource); + Assert.NotSame(dataSource, item.DataSource); + } + + [Theory] + [InlineData("DS Item Title", "DS Item Title", "DS Title", "DS Title")] + [InlineData("DS Item Title", "DS Item Title", null, "DS Item Title")] + public void Constructor_CreatePostgresDSItem_WithCustomTableAndPostgresDataSource(string dsItemTitle, string expectedDSItemTitle, string dsTitle, string expectedDSTitle) + { + // Arrange + var tableName = "Table"; + var dataSource = new PostgreSQLDataSource() { Title = dsTitle}; + + // Act + var postgresDSItem = new PostgreSqlDataSourceItem(dsItemTitle, tableName, dataSource); + + // Assert + Assert.Equal(expectedDSTitle, postgresDSItem.DataSource.Title); + Assert.Equal(expectedDSItemTitle, postgresDSItem.Title); + Assert.Equal(tableName, postgresDSItem.Table); + Assert.Equal(tableName, postgresDSItem.Properties.GetValue("Table")); + Assert.Equal(dataSource.Id, postgresDSItem.DataSource.Id); + Assert.Equal(dataSource.Id, postgresDSItem.DataSourceId); + Assert.Same(dataSource, postgresDSItem.DataSource); + } + + [Theory] + [InlineData("DS Item Title", "DS Item Title", "DS Title", "DS Title")] + [InlineData("DS Item Title", "DS Item Title", null, "DS Item Title")] + public void Constructor_CreatePostgresDSItem_WithCustomTableAndDataSource(string dsItemTitle, string expectedDSItemTitle, string dsTitle, string expectedDSTitle) + { + // Arrange + var tableName = "Table"; + var dataSource = new DataSource() { Title = dsTitle }; + + // Act + var postgresDSItem = new PostgreSqlDataSourceItem(dsItemTitle, tableName, dataSource); + + // Assert + Assert.Equal(expectedDSTitle, postgresDSItem.DataSource.Title); + Assert.Equal(expectedDSItemTitle, postgresDSItem.Title); + Assert.Equal(tableName, postgresDSItem.Table); + Assert.Equal(tableName, postgresDSItem.Properties.GetValue("Table")); + Assert.Equal(dataSource.Id, postgresDSItem.DataSource.Id); + Assert.Equal(dataSource.Id, postgresDSItem.DataSourceId); + Assert.IsType(postgresDSItem.DataSource); + Assert.NotSame(dataSource, postgresDSItem.DataSource); } [Fact] - public void ProcessDataOnServer_SetsAndGetsValue_WithInputs() + public void GetProcessDataOnServer_ReturnSameValue_WhenSetValue() { // Arrange var item = new PostgreSqlDataSourceItem("Test Item", new PostgreSQLDataSource()); @@ -35,5 +104,53 @@ public void ProcessDataOnServer_SetsAndGetsValue_WithInputs() Assert.True(item.ProcessDataOnServer); Assert.True(item.Properties.GetValue("ServerAggregation")); } + + [Fact] + public void ToJsonString_CreatesFormattedJson_NoConditions() + { + // Arrange + var expectedJson = @"{ + ""_type"": ""DataSourceItemType"", + ""Id"": ""pgSqlDSItemId"", + ""Title"": ""Postgres DSItem"", + ""Subtitle"": ""Northwind Employees For DS Item"", + ""DataSourceId"": ""pgSqlId"", + ""HasTabularData"": true, + ""HasAsset"": false, + ""Properties"": { + ""ServerAggregation"": true, + ""Database"": ""northwind"", + ""Table"": ""categories"", + ""Schema"": """" + }, + ""Parameters"": {} + }"; + + var dataSource = new PostgreSQLDataSource() + { + Id = "pgSqlId", + }; + + var dataSourceItem = new PostgreSqlDataSourceItem("Postgres DSItem", dataSource) + { + Id = "pgSqlDSItemId", + Subtitle = "Northwind Employees For DS Item", + HasTabularData = true, + HasAsset = false, + ProcessDataOnServer = true, + Database = "northwind", + Table = "categories", + Schema = "", + }; + + // Act + var json = dataSourceItem.ToJsonString(); + var expectedJObject = JObject.Parse(expectedJson); + var actualJObject = JObject.Parse(json); + + // Assert + Assert.Equal(expectedJObject, actualJObject); + + } } } \ No newline at end of file diff --git a/src/Reveal.Sdk.Dom.Tests/Data/DataSources/PostgreSQLDataSourceFixture.cs b/src/Reveal.Sdk.Dom.Tests/Data/DataSources/PostgreSQLDataSourceFixture.cs index 4f887052..1af1350b 100644 --- a/src/Reveal.Sdk.Dom.Tests/Data/DataSources/PostgreSQLDataSourceFixture.cs +++ b/src/Reveal.Sdk.Dom.Tests/Data/DataSources/PostgreSQLDataSourceFixture.cs @@ -1,5 +1,7 @@ +using Reveal.Sdk.Dom.Core.Serialization; using Reveal.Sdk.Dom.Data; using Xunit; +using Newtonsoft.Json.Linq; namespace Reveal.Sdk.Dom.Tests.Data.DataSources { @@ -14,5 +16,53 @@ public void Constructor_SetsProviderToPostgreSQL_WhenConstructed() // Assert Assert.Equal(DataSourceProvider.PostgreSQL, dataSource.Provider); } + + [Fact] + public void ToJsonString_CreatesFormattedJson_NoConditions() + { + // Arrange + var expectedJson = @"{ + ""_type"": ""DataSourceType"", + ""Id"": ""pgSqlId"", + ""Provider"": ""POSTGRES"", + ""Description"": ""Postgres DS"", + ""Subtitle"": ""Northwind Employees"", + ""Properties"": { + ""ServerAggregationDefault"": true, + ""ServerAggregationReadOnly"": true, + ""Host"": ""revealdb01.infragistics.local"", + ""Port"": 5432, + ""Database"": ""northwind"", + ""Schema"": ""public"" + }, + ""Settings"": { + ""DefaultRefreshRate"": 180 + } + }"; + + var dataSource = new PostgreSQLDataSource() + { + Id = "pgSqlId", + Title = "Postgres DS", + Subtitle = "Northwind Employees", + ProcessDataOnServerDefaultValue = true, + ProcessDataOnServerReadOnly = true, + Host = "revealdb01.infragistics.local", + Port = 5432, + Database = "northwind", + Schema = "public", + DefaultRefreshRate = "180", + + }; + + // Act + var json = dataSource.ToJsonString(); + var expectedJObject = JObject.Parse(expectedJson); + var actualJObject = JObject.Parse(json); + + // Assert + Assert.Equal(expectedJObject, actualJObject); + + } } } \ No newline at end of file diff --git a/src/Reveal.Sdk.Dom/Data/DataSource.cs b/src/Reveal.Sdk.Dom/Data/DataSource.cs index dbacee6b..bdca5df3 100644 --- a/src/Reveal.Sdk.Dom/Data/DataSource.cs +++ b/src/Reveal.Sdk.Dom/Data/DataSource.cs @@ -16,6 +16,7 @@ public DataSource() { SchemaTypeName = SchemaTypeNames.DataSourceType; Properties = new Dictionary(); + Settings = new Dictionary(); } public string Id @@ -33,15 +34,19 @@ public string Id public string Subtitle { get; set; } + [JsonIgnore] public string DefaultRefreshRate { - get => Properties.GetValue("DefaultRefreshRate"); - set => Properties.SetItem("DefaultRefreshRate", value); + get => Settings.GetValue("DefaultRefreshRate"); + set => Settings.SetItem("DefaultRefreshRate", value); } [JsonProperty] internal Dictionary Properties { get; set; } + [JsonProperty] + internal Dictionary Settings { get; set; } + public override bool Equals(object obj) { return Equals(obj as DataSource); diff --git a/src/Reveal.Sdk.Dom/Data/DataSourceItemFactory.cs b/src/Reveal.Sdk.Dom/Data/DataSourceItemFactory.cs index 7433ab18..1489c0df 100644 --- a/src/Reveal.Sdk.Dom/Data/DataSourceItemFactory.cs +++ b/src/Reveal.Sdk.Dom/Data/DataSourceItemFactory.cs @@ -1,4 +1,4 @@ -using System; +using System; namespace Reveal.Sdk.Dom.Data { @@ -26,6 +26,7 @@ public DataSourceItem Create(DataSourceType type, string id, string title, strin DataSourceType.MicrosoftSqlServer => new MicrosoftSqlServerDataSourceItem(title, dataSource), DataSourceType.REST => new RestDataSourceItem(title, dataSource), DataSourceType.MySql => new MySqlDataSourceItem(title, dataSource), + DataSourceType.PostgreSQL => new PostgreSqlDataSourceItem(title, dataSource), _ => throw new NotImplementedException($"No builder implemented for provider: {type}") }; diff --git a/src/Reveal.Sdk.Dom/Data/DataSourceItems/PostgreSqlDataSourceItem.cs b/src/Reveal.Sdk.Dom/Data/DataSourceItems/PostgreSqlDataSourceItem.cs index 47968036..5f9d8369 100644 --- a/src/Reveal.Sdk.Dom/Data/DataSourceItems/PostgreSqlDataSourceItem.cs +++ b/src/Reveal.Sdk.Dom/Data/DataSourceItems/PostgreSqlDataSourceItem.cs @@ -5,15 +5,36 @@ namespace Reveal.Sdk.Dom.Data { public class PostgreSqlDataSourceItem : FunctionDataSourceItem, IProcessDataOnServer { - public PostgreSqlDataSourceItem(string title, DataSource dataSource) : + public PostgreSqlDataSourceItem(string title, PostgreSQLDataSource dataSource) : base(title, dataSource) { } + public PostgreSqlDataSourceItem(string title, DataSource dataSource) : + base(title, dataSource) + { } + + public PostgreSqlDataSourceItem(string title, string table, PostgreSQLDataSource dataSource) : + this(title, dataSource) + { + Table = table; + } + + public PostgreSqlDataSourceItem(string title, string table, DataSource dataSource) : + this(title, dataSource) + { + Table = table; + } + [JsonIgnore] public bool ProcessDataOnServer { get => Properties.GetValue("ServerAggregation"); set => Properties.SetItem("ServerAggregation", value); } + + protected override DataSource CreateDataSourceInstance(DataSource dataSource) + { + return Create(dataSource); + } } } diff --git a/src/Reveal.Sdk.Dom/Data/DataSources/PostgreSQLDataSource.cs b/src/Reveal.Sdk.Dom/Data/DataSources/PostgreSQLDataSource.cs index 4a98e8c0..0a07dbdb 100644 --- a/src/Reveal.Sdk.Dom/Data/DataSources/PostgreSQLDataSource.cs +++ b/src/Reveal.Sdk.Dom/Data/DataSources/PostgreSQLDataSource.cs @@ -1,6 +1,6 @@ namespace Reveal.Sdk.Dom.Data { - internal class PostgreSQLDataSource : SchemaDataSource + public class PostgreSQLDataSource : SchemaDataSource { public PostgreSQLDataSource() { diff --git a/src/Reveal.Sdk.Dom/Data/Enums/DataSourceType.cs b/src/Reveal.Sdk.Dom/Data/Enums/DataSourceType.cs index 8cd24f56..b4007327 100644 --- a/src/Reveal.Sdk.Dom/Data/Enums/DataSourceType.cs +++ b/src/Reveal.Sdk.Dom/Data/Enums/DataSourceType.cs @@ -1,9 +1,10 @@ -namespace Reveal.Sdk.Dom.Data +namespace Reveal.Sdk.Dom.Data { public enum DataSourceType { REST, MicrosoftSqlServer, - MySql + MySql, + PostgreSQL, } }