diff --git a/e2e/Sandbox/DashboardCreators/MongoDashboard.cs b/e2e/Sandbox/DashboardCreators/MongoDashboard.cs index 27256a45..c6b4cfc3 100644 --- a/e2e/Sandbox/DashboardCreators/MongoDashboard.cs +++ b/e2e/Sandbox/DashboardCreators/MongoDashboard.cs @@ -1,4 +1,6 @@ using Reveal.Sdk.Dom; +using Reveal.Sdk.Dom.Data; +using Reveal.Sdk.Dom.Visualizations; using System; using System.Collections.Generic; using System.Linq; @@ -13,7 +15,68 @@ internal class MongoDashboard : IDashboardCreator public RdashDocument CreateDashboard() { - throw new NotImplementedException(); + var mongoDbDs = new MongoDBDataSource() + { + Id = "MyMongoDatasource", + Title = "MyMongoDatasource", + Subtitle = "My MongoDB", + ProcessDataOnServerDefaultValue = true, + ProcessDataOnServerReadOnly = false, + ConnectionString = "mongodb+srv://cluster0.ta2xrrt.mongodb.net", + Database = "test" + }; + + var testCollection = new MongoDbDataSourceItem("DB Test", mongoDbDs) + { + Id = "MyMongoDatasourceItem", + Title = "MyMongoDatasourceItem", + Subtitle = "Test Collection", + Collection = "data", + Fields = new List + { + new TextField("_id"), + new TextField("name"), + new NumberField("price"), + new DateTimeField("available_since"), + new TextField("category"), + new NumberField("year_value"), + new NumberField("month_value"), + new NumberField("day_value"), + new NumberField("hour_value"), + new NumberField("minutes_value"), + new NumberField("seconds_value"), + new NumberField("milliseconds_value"), + new NumberField("numeric_value1"), + new NumberField("numeric_value2"), + new NumberField("numeric_value3"), + new TextField("image_url") + + } + }; + + var document = new RdashDocument("My Dashboard"); + + document.Visualizations.Add(new GridVisualization("Test List", testCollection).SetColumns("name", "category", "price")); + + var jsonData = document.ToJsonString(); + + // var filePath = "test.rdash"; + + // try + // { + + // if (File.Exists(filePath)) + // File.Delete(filePath); + + // document.Save(filePath); + // } + // catch + // { + // throw; + // } + + + return document; } } } diff --git a/e2e/Sandbox/Reveal/AuthenticationProvider.cs b/e2e/Sandbox/Reveal/AuthenticationProvider.cs index cf83f9ab..492e34c7 100644 --- a/e2e/Sandbox/Reveal/AuthenticationProvider.cs +++ b/e2e/Sandbox/Reveal/AuthenticationProvider.cs @@ -7,6 +7,7 @@ using Reveal.Sdk.Data.MySql; using Reveal.Sdk.Data.PostgreSQL; using Reveal.Sdk.Data.Oracle; +using Reveal.Sdk.Data.MongoDB; using System.Threading.Tasks; using Reveal.Sdk.Data.Amazon.Redshift; using Reveal.Sdk.Data.Google.Analytics4; @@ -17,11 +18,14 @@ using Reveal.Sdk.Data.MySql; using Reveal.Sdk.Data.OData; using Reveal.Sdk.Data.Oracle; +using Reveal.Sdk.Data.Snowflake; +using Reveal.Sdk.Data.PostgreSQL; using Reveal.Sdk.Data.Microsoft.SynapseAnalytics; using Google.Apis.Auth.OAuth2; using System.IO; using System.Text; + namespace Sandbox.RevealSDK { internal class AuthenticationProvider : IRVAuthenticationProvider @@ -51,6 +55,10 @@ public Task ResolveCredentialsAsync(RVDashboardDataSour userCredential = new RVBearerTokenDataSourceCredential(_token, null); } + else if (dataSource is RVMongoDBDataSource) + { + userCredential = new RVUsernamePasswordDataSourceCredential("user01", "*****", "admin"); + } else if (dataSource is RVSnowflakeDataSource) { userCredential = new RVUsernamePasswordDataSourceCredential("snow-flake-username", "snow-flake-password"); diff --git a/e2e/Sandbox/Reveal/DataSourceProvider.cs b/e2e/Sandbox/Reveal/DataSourceProvider.cs index 765f5518..3a985542 100644 --- a/e2e/Sandbox/Reveal/DataSourceProvider.cs +++ b/e2e/Sandbox/Reveal/DataSourceProvider.cs @@ -5,6 +5,7 @@ using System.Threading.Tasks; using Reveal.Sdk.Data.Excel; using Reveal.Sdk.Data.Microsoft.AnalysisServices; +using Reveal.Sdk.Data.MongoDB; namespace Sandbox.RevealSDK { @@ -60,6 +61,16 @@ public Task ChangeDataSourceItemAsync(RVDataSourceItem dataSou // ds.Database = "Northwind"; //} + //if (dataSourceItem is RVMongoDBDataSourceItem mongoDbDataSourceItem) + //{ + // mongoDbDataSourceItem.Collection = "data"; + + // var ds = mongoDbDataSourceItem.DataSource as RVMongoDBDataSource; + + // ds.ConnectionString = "mongodb+srv://user01:*******@cluster0.ta2xrrt.mongodb.net/"; + // ds.Database = "test"; + //} + return Task.FromResult(dataSourceItem); } } diff --git a/src/Reveal.Sdk.Dom.Tests/Dashboards/TestMongoDb.rdash b/src/Reveal.Sdk.Dom.Tests/Dashboards/TestMongoDb.rdash new file mode 100644 index 00000000..ff3e4492 Binary files /dev/null and b/src/Reveal.Sdk.Dom.Tests/Dashboards/TestMongoDb.rdash differ diff --git a/src/Reveal.Sdk.Dom.Tests/Data/DataSourceItems/MongoDbDataSourceItemFixture.cs b/src/Reveal.Sdk.Dom.Tests/Data/DataSourceItems/MongoDbDataSourceItemFixture.cs index 9f34a02c..0cb0dd1b 100644 --- a/src/Reveal.Sdk.Dom.Tests/Data/DataSourceItems/MongoDbDataSourceItemFixture.cs +++ b/src/Reveal.Sdk.Dom.Tests/Data/DataSourceItems/MongoDbDataSourceItemFixture.cs @@ -1,6 +1,11 @@ using Reveal.Sdk.Dom.Core.Extensions; using Reveal.Sdk.Dom.Data; +using System.IO; +using System; using Xunit; +using Newtonsoft.Json.Linq; +using System.Collections.Generic; +using Reveal.Sdk.Dom.Visualizations; namespace Reveal.Sdk.Dom.Tests.Data.DataSourceItems { @@ -33,7 +38,7 @@ public void Collection_SetsAndGetsValue_WithInputs() // Assert Assert.Equal("TestCollection", item.Collection); - Assert.Equal("TestCollection", item.Properties.GetValue("Collection")); + Assert.Equal("TestCollection", item.Properties.GetValue("Table")); } [Fact] @@ -49,5 +54,81 @@ public void ProcessDataOnServer_SetsAndGetsValue_WithInputs() Assert.True(item.ProcessDataOnServer); Assert.True(item.Properties.GetValue("ServerAggregation")); } + + [Fact] + public void RDashDocument_HasCorrectDataSourceItem_WhenLoadFromFile() + { + // Arrange + var filePath = Path.Combine(Environment.CurrentDirectory, "Dashboards", "TestMongoDb.rdash"); + + // Act + var document = RdashDocument.Load(filePath); + var dataSource = document.DataSources[0]; + var dataSourceItem = document.Visualizations[0].DataDefinition.DataSourceItem; + + // Assert + Assert.Equal(dataSource.Id, dataSourceItem.DataSourceId); + Assert.Equal(DataSourceProvider.MongoDB, dataSource.Provider); + Assert.NotNull(dataSourceItem.Properties.GetValue("Table")); + Assert.True(dataSourceItem.Properties.GetValue("ServerAggregation")); + } + + [Fact] + public void RDashDocument_ProduceAsExpected_WhenExportJson() + { + // Arrange + var mongoDbDs = new MongoDBDataSource() + { + Id = "MyMongoDatasource", + Title = "MyMongoDatasource", + Subtitle = "My MongoDB", + ProcessDataOnServerDefaultValue = true, + ProcessDataOnServerReadOnly = false, + }; + + var testCollection = new MongoDbDataSourceItem("DB Test", mongoDbDs) + { + Id = "MyMongoDatasourceItem", + Title = "MyMongoDatasourceItem", + Subtitle = "Test Collection", + Collection = "data", + Fields = new List + { + new TextField("_id"), + new TextField("name"), + } + }; + + var document = new RdashDocument("My Dashboard"); + + document.Visualizations.Add(new GridVisualization("Test List", testCollection).SetColumns("name")); + + var expectedDsJson = """ + { + "_type": "DataSourceItemType", + "Id": "MyMongoDatasourceItem", + "Title": "MyMongoDatasourceItem", + "Subtitle": "Test Collection", + "DataSourceId": "MyMongoDatasource", + "HasTabularData": true, + "HasAsset": false, + "Properties": { + "Collection": "data" + }, + "Parameters": {} + } + """; + + // Act + var jsonData = document.ToJsonString(); + var jObject = JObject.Parse(jsonData); + var datasourceJson = jObject["Widgets"][0]["DataSpec"]["DataSourceItem"]; + + // Deserialize JSON strings to JObjects to make comparing them easier + var expectedJObject = JObject.Parse(expectedDsJson); + + // Assert + Assert.Equal(expectedJObject, datasourceJson); + } } } \ No newline at end of file diff --git a/src/Reveal.Sdk.Dom.Tests/Data/DataSources/MongoDbDataSourceFixture.cs b/src/Reveal.Sdk.Dom.Tests/Data/DataSources/MongoDbDataSourceFixture.cs new file mode 100644 index 00000000..ed992e1b --- /dev/null +++ b/src/Reveal.Sdk.Dom.Tests/Data/DataSources/MongoDbDataSourceFixture.cs @@ -0,0 +1,145 @@ +using Newtonsoft.Json.Linq; +using Reveal.Sdk.Dom.Core.Extensions; +using Reveal.Sdk.Dom.Data; +using System.Collections.Generic; +using System.IO; +using System; +using Xunit; +using Reveal.Sdk.Dom.Visualizations; + +namespace Reveal.Sdk.Dom.Tests.Data.DataSources +{ + public class MongoDbDataSourceFixture + { + [Fact] + public void Constructor_SetsProviderToMongoDB_WhenConstructed() + { + // Act + var dataSource = new MongoDBDataSource(); + + // Assert + Assert.Equal(DataSourceProvider.MongoDB, dataSource.Provider); + } + + [Theory] + [InlineData("mongodb://localhost:27017")] + [InlineData(null)] + public void ConnectionString_SetsAndGetsValue_WithDifferentInputs(string connectionString) + { + // Arrange + var dataSource = new MongoDBDataSource(); + + // Act + dataSource.ConnectionString = connectionString; + + // Assert + Assert.Equal(connectionString, dataSource.ConnectionString); + Assert.Equal(connectionString, dataSource.Properties.GetValue("ConnectionString")); + } + + [Theory] + [InlineData(true)] + [InlineData(false)] + public void ProcessDataOnServerDefaultValue_SetsAndGetsValue_WithDifferentInputs(bool defaultValue) + { + // Arrange + var dataSource = new MongoDBDataSource(); + + // Act + dataSource.ProcessDataOnServerDefaultValue = defaultValue; + + // Assert + Assert.Equal(defaultValue, dataSource.ProcessDataOnServerDefaultValue); + Assert.Equal(defaultValue, dataSource.Properties.GetValue("ServerAggregationDefault")); + } + + [Theory] + [InlineData(true)] + [InlineData(false)] + public void ProcessDataOnServerReadOnly_SetsAndGetsValue_WithDifferentInputs(bool readOnlyValue) + { + // Arrange + var dataSource = new MongoDBDataSource(); + + // Act + dataSource.ProcessDataOnServerReadOnly = readOnlyValue; + + // Assert + Assert.Equal(readOnlyValue, dataSource.ProcessDataOnServerReadOnly); + Assert.Equal(readOnlyValue, dataSource.Properties.GetValue("ServerAggregationReadOnly")); + } + + [Fact] + public void RDashDocument_HasCorrectDataSource_WhenLoadFromFile() + { + // Arrange + var filePath = Path.Combine(Environment.CurrentDirectory, "Dashboards", "TestMongoDb.rdash"); + + // Act + var document = RdashDocument.Load(filePath); + var dataSource = document.DataSources[0]; + + // Assert + Assert.Equal(DataSourceProvider.MongoDB, dataSource.Provider); + Assert.NotNull(dataSource.Properties.GetValue("ServerAggregationDefault")); + Assert.NotNull(dataSource.Properties.GetValue("ServerAggregationReadOnly")); + } + + [Fact] + public void RDashDocument_ProduceAsExpected_WhenExportJson() + { + // Arrange + var mongoDbDs = new MongoDBDataSource() + { + Id = "MyMongoDatasource", + Title = "MyMongoDatasource", + Subtitle = "My MongoDB", + ProcessDataOnServerDefaultValue = true, + ProcessDataOnServerReadOnly = false, + }; + + var testCollection = new MongoDbDataSourceItem("DB Test", mongoDbDs) + { + Id = "MyMongoDatasourceItem", + Title = "MyMongoDatasourceItem", + Subtitle = "Test Collection", + Collection = "data", + Fields = new List + { + new TextField("_id"), + new TextField("name"), + } + }; + + var document = new RdashDocument("My Dashboard"); + + document.Visualizations.Add(new GridVisualization("Test List", testCollection).SetColumns("name")); + + var expectedDsJson = """ + { + "_type": "DataSourceType", + "Id": "MyMongoDatasource", + "Provider": "MONGODB", + "Description": "MyMongoDatasource", + "Subtitle": "My MongoDB", + "Properties": { + "ServerAggregationDefault": true, + "ServerAggregationReadOnly": false + }, + "Settings": {} + } + """; + + // Act + var jsonData = document.ToJsonString(); + var jObject = JObject.Parse(jsonData); + var datasourceJson = jObject["DataSources"][0]; + + // Deserialize JSON strings to JObjects to make comparing them easier + var expectedJObject = JObject.Parse(expectedDsJson); + + // Assert + Assert.Equal(expectedJObject, datasourceJson); + } + } +} \ No newline at end of file diff --git a/src/Reveal.Sdk.Dom.Tests/Data/DataSources/MongoDbDataSourceItemFixture.cs b/src/Reveal.Sdk.Dom.Tests/Data/DataSources/MongoDbDataSourceItemFixture.cs deleted file mode 100644 index 21c6c821..00000000 --- a/src/Reveal.Sdk.Dom.Tests/Data/DataSources/MongoDbDataSourceItemFixture.cs +++ /dev/null @@ -1,67 +0,0 @@ -using Reveal.Sdk.Dom.Core.Extensions; -using Reveal.Sdk.Dom.Data; -using Xunit; - -namespace Reveal.Sdk.Dom.Tests.Data.DataSources -{ - public class MongoDbDataSourceItemFixture - { - [Fact] - public void Constructor_SetsProviderToMongoDB_WhenConstructed() - { - // Act - var dataSource = new MongoDBDataSource(); - - // Assert - Assert.Equal(DataSourceProvider.MongoDB, dataSource.Provider); - } - - [Theory] - [InlineData("mongodb://localhost:27017")] - [InlineData(null)] - public void ConnectionString_SetsAndGetsValue_WithDifferentInputs(string connectionString) - { - // Arrange - var dataSource = new MongoDBDataSource(); - - // Act - dataSource.ConnectionString = connectionString; - - // Assert - Assert.Equal(connectionString, dataSource.ConnectionString); - Assert.Equal(connectionString, dataSource.Properties.GetValue("ConnectionString")); - } - - [Theory] - [InlineData(true)] - [InlineData(false)] - public void ProcessDataOnServerDefaultValue_SetsAndGetsValue_WithDifferentInputs(bool defaultValue) - { - // Arrange - var dataSource = new MongoDBDataSource(); - - // Act - dataSource.ProcessDataOnServerDefaultValue = defaultValue; - - // Assert - Assert.Equal(defaultValue, dataSource.ProcessDataOnServerDefaultValue); - Assert.Equal(defaultValue, dataSource.Properties.GetValue("ServerAggregationDefault")); - } - - [Theory] - [InlineData(true)] - [InlineData(false)] - public void ProcessDataOnServerReadOnly_SetsAndGetsValue_WithDifferentInputs(bool readOnlyValue) - { - // Arrange - var dataSource = new MongoDBDataSource(); - - // Act - dataSource.ProcessDataOnServerReadOnly = readOnlyValue; - - // Assert - Assert.Equal(readOnlyValue, dataSource.ProcessDataOnServerReadOnly); - Assert.Equal(readOnlyValue, dataSource.Properties.GetValue("ServerAggregationReadOnly")); - } - } -} \ No newline at end of file diff --git a/src/Reveal.Sdk.Dom.Tests/Reveal.Sdk.Dom.Tests.csproj b/src/Reveal.Sdk.Dom.Tests/Reveal.Sdk.Dom.Tests.csproj index 59ee8f29..5957a73c 100644 --- a/src/Reveal.Sdk.Dom.Tests/Reveal.Sdk.Dom.Tests.csproj +++ b/src/Reveal.Sdk.Dom.Tests/Reveal.Sdk.Dom.Tests.csproj @@ -51,6 +51,13 @@ PreserveNewest + + Always + + + + + diff --git a/src/Reveal.Sdk.Dom/Data/DataSourceItems/MongoDbDataSourceItem.cs b/src/Reveal.Sdk.Dom/Data/DataSourceItems/MongoDbDataSourceItem.cs index 0ae51b64..63b29b3b 100644 --- a/src/Reveal.Sdk.Dom/Data/DataSourceItems/MongoDbDataSourceItem.cs +++ b/src/Reveal.Sdk.Dom/Data/DataSourceItems/MongoDbDataSourceItem.cs @@ -3,7 +3,7 @@ namespace Reveal.Sdk.Dom.Data { - internal class MongoDbDataSourceItem : DataSourceItem, IProcessDataOnServer + public class MongoDbDataSourceItem : DataSourceItem, IProcessDataOnServer { public MongoDbDataSourceItem(string title, DataSource dataSource) : base(title, dataSource) @@ -12,8 +12,8 @@ public MongoDbDataSourceItem(string title, DataSource dataSource) : [JsonIgnore] public string Collection { - get => Properties.GetValue("Collection"); - set => Properties.SetItem("Collection", value); + get => Properties.GetValue("Table"); + set => Properties.SetItem("Table", value); } [JsonIgnore] diff --git a/src/Reveal.Sdk.Dom/Data/DataSources/MongoDBDataSource.cs b/src/Reveal.Sdk.Dom/Data/DataSources/MongoDBDataSource.cs index 0fb4fc49..96caecc4 100644 --- a/src/Reveal.Sdk.Dom/Data/DataSources/MongoDBDataSource.cs +++ b/src/Reveal.Sdk.Dom/Data/DataSources/MongoDBDataSource.cs @@ -3,7 +3,7 @@ namespace Reveal.Sdk.Dom.Data { - internal class MongoDBDataSource : DatabaseDataSource + public class MongoDBDataSource : DatabaseDataSource { public MongoDBDataSource() { diff --git a/src/Reveal.Sdk.Dom/Data/Enums/DataSourceType.cs b/src/Reveal.Sdk.Dom/Data/Enums/DataSourceType.cs index 06822a5d..7b0e2dfe 100644 --- a/src/Reveal.Sdk.Dom/Data/Enums/DataSourceType.cs +++ b/src/Reveal.Sdk.Dom/Data/Enums/DataSourceType.cs @@ -7,5 +7,6 @@ public enum DataSourceType MySql, Oracle, PostgreSQL, + MongoDB, } }