From 292797d74991e3bbbf734eb48fe55314f5386d69 Mon Sep 17 00:00:00 2001 From: Tr00d Date: Mon, 10 Oct 2022 16:32:22 +0200 Subject: [PATCH 01/23] Create object and implement parsing for StartRender operation --- OpenTok/OpenTok.csproj | 25 +- OpenTok/Render/ScreenResolution.cs | 40 +++ OpenTok/Render/StartRenderRequest.cs | 233 ++++++++++++++++++ OpenTokTest/OpenTokTest.csproj | 2 + .../Render/StartRenderRequestDataBuilder.cs | 117 +++++++++ OpenTokTest/Render/StartRenderRequestTest.cs | 136 ++++++++++ 6 files changed, 541 insertions(+), 12 deletions(-) create mode 100644 OpenTok/Render/ScreenResolution.cs create mode 100644 OpenTok/Render/StartRenderRequest.cs create mode 100644 OpenTokTest/Render/StartRenderRequestDataBuilder.cs create mode 100644 OpenTokTest/Render/StartRenderRequestTest.cs diff --git a/OpenTok/OpenTok.csproj b/OpenTok/OpenTok.csproj index ef338729..1ba8153d 100644 --- a/OpenTok/OpenTok.csproj +++ b/OpenTok/OpenTok.csproj @@ -1,4 +1,4 @@ - + net452;net46;net461;netstandard2.0 @@ -23,29 +23,30 @@ true - + - - + + - - + + - - + + - - + + - + - + + diff --git a/OpenTok/Render/ScreenResolution.cs b/OpenTok/Render/ScreenResolution.cs new file mode 100644 index 00000000..78e7719f --- /dev/null +++ b/OpenTok/Render/ScreenResolution.cs @@ -0,0 +1,40 @@ +using System.ComponentModel; + +namespace OpenTokSDK.Render +{ + /// + /// Enum for representing resolutions with orientation. + /// + public enum ScreenResolution + { + /// + /// Standard definition (SD) resolution with landscape orientation (640x480) + /// + [Description("640x480")] StandardDefinitionLandscape, + + /// + /// Standard definition (SD) resolution with portrait orientation (480x640) + /// + [Description("480x640")] StandardDefinitionPortrait, + + /// + /// High definition (HD) resolution with landscape orientation (1280x780) + /// + [Description("1280x720")] HighDefinitionLandscape, + + /// + /// High definition (HD) resolution with portrait orientation (780x1280) + /// + [Description("720x1280")] HighDefinitionPortrait, + + /// + /// Full high definition (FHD) resolution with landscape orientation (1920x1080) + /// + [Description("1920x1080")] FullHighDefinitionLandscape, + + /// + /// Full high definition (FHD) resolution with portrait orientation (1080x1920) + /// + [Description("1080x1920")] FullHighDefinitionPortrait, + } +} \ No newline at end of file diff --git a/OpenTok/Render/StartRenderRequest.cs b/OpenTok/Render/StartRenderRequest.cs new file mode 100644 index 00000000..dc1bf3a1 --- /dev/null +++ b/OpenTok/Render/StartRenderRequest.cs @@ -0,0 +1,233 @@ +using System; +using System.Linq; +using OpenTokSDK.Exception; + +namespace OpenTokSDK.Render +{ + /// + /// + public class StartRenderRequest + { + private const int MinimumUrlLength = 15; + private const int MaximumUrlLength = 2048; + private const int MinimumMaxDuration = 60; + private const int MaximumMaxDuration = 36000; + private const int MaximumPropertyNameLength = 200; + + /// + /// Indicates SessionId needs to be provided. + /// + public const string MissingSessionId = "SessionId needs to be provided."; + + /// + /// Indicates Token needs to be provided. + /// + public const string MissingToken = "Token needs to be provided."; + + /// + /// Indicates Url length should be between 15 and 2048. + /// + public const string InvalidUrl = "Url length should be between 15 and 2048."; + + /// + /// Indicates Url length should be between 15 and 2048. + /// + public const string InvalidStatusCallbackUrl = "Url length should be between 15 and 2048."; + + /// + /// Indicates MaxDuration value should be between 60s and 36000s. + /// + public const string InvalidMaxDuration = "MaxDuration value should be between 60s and 36000s."; + + /// + /// Indicates the provided resolution is not supported. + /// + public const string InvalidResolution = "The provided resolution is not supported."; + + private readonly ScreenResolution[] allowedResolutions = + { + ScreenResolution.HighDefinitionLandscape, + ScreenResolution.StandardDefinitionLandscape, + ScreenResolution.StandardDefinitionPortrait, + ScreenResolution.FullHighDefinitionLandscape, + }; + + /// + /// + /// + /// The ID of a session (generated with the same `APIKEY` as specified in the URL) which you wish + /// to start rendering into + /// + /// + /// A valid OpenTok token with a Publisher role and (optionally) connection data to be associated with + /// the output stream. + /// + /// + /// A publically reachable URL controlled by the customer and capable of generating the content to be + /// rendered without user intervention. The absolute URI should have a minimum length of 15 and maximum length of 2048. + /// + /// + /// Resolution of the display area for the composition. Allowed values are 480x640 (SD Portrait), + /// 640x480 (SD Landscape), 720x1280 (HD Portrait), 1280x720 (HD Landscape). The default value is 1280x720 (HD + /// Landscape). + /// + /// + /// URL of the customer service where the callbacks will be received. The absolute URI + /// should have a minimum length of 15 and maximum length of 2048. + /// + /// + /// The name of the composed output stream which will be published to the session. The minimum + /// length is 1 and the maximum one is 200. + /// + /// + /// The maximum time allowed for the Render, in seconds. After this time, the Render will be + /// stopped automatically, if it is still running. The minimum duration is 1s and the maximum one is 36000s (10 hours). + /// + public StartRenderRequest(string sessionId, string token, Uri url, + Uri statusCallbackUrl, string streamName, int maxDuration = 7200, + ScreenResolution resolution = ScreenResolution.HighDefinitionLandscape) + { + ValidateSessionId(sessionId); + ValidateToken(token); + ValidateUrl(url, InvalidUrl); + ValidateUrl(statusCallbackUrl, InvalidStatusCallbackUrl); + ValidateMaxDuration(maxDuration); + this.ValidateResolution(resolution); + this.SessionId = sessionId; + this.Token = token; + this.Url = url; + this.MaxDuration = maxDuration; + this.Resolution = resolution; + this.StatusCallbackUrl = statusCallbackUrl; + this.Properties = new PublisherProperty(streamName); + } + + /// + /// The ID of a session (generated with the same `APIKEY` as specified in the URL) which you wish to start rendering + /// into + /// + public string SessionId { get; } + + /// + /// A valid OpenTok token with a Publisher role and (optionally) connection data to be associated with the output + /// stream. + /// + public string Token { get; } + + /// + /// A publically reachable URL controlled by the customer and capable of generating the content to be rendered without + /// user intervention. The absolute URI should have a minimum length of 15 and maximum length of 2048. + /// + public Uri Url { get; } + + /// + /// The maximum time allowed for the Render, in seconds. After this time, the Render will be stopped automatically, if + /// it is still running. The minimum duration is 1s and the maximum one is 36000s (10 hours). + /// + public int MaxDuration { get; } + + /// + /// Resolution of the display area for the composition. Allowed values are 480x640 (SD Portrait), 640x480 (SD + /// Landscape), 720x1280 (HD Portrait), 1280x720 (HD Landscape). The default value is 1280x720 (HD Landscape). + /// + public ScreenResolution Resolution { get; } + + /// + /// URL of the customer service where the callbacks will be received. The absolute URI should have a minimum length of + /// 15 and maximum length of 2048. + /// + public Uri StatusCallbackUrl { get; } + + /// + /// Initial configuration of Publisher properties for the composed output stream. + /// + public PublisherProperty Properties { get; } + + private static void ValidateSessionId(string sessionId) + { + if (string.IsNullOrWhiteSpace(sessionId)) + { + throw new OpenTokException(MissingSessionId); + } + } + + private static void ValidateToken(string token) + { + if (string.IsNullOrWhiteSpace(token)) + { + throw new OpenTokException(MissingToken); + } + } + + private static void ValidateUrl(Uri url, string message) + { + if (url.AbsoluteUri.Length < MinimumUrlLength || url.AbsoluteUri.Length > MaximumUrlLength) + { + throw new OpenTokException(message); + } + } + + private static void ValidateMaxDuration(int maxDuration) + { + if (maxDuration < MinimumMaxDuration || maxDuration > MaximumMaxDuration) + { + throw new OpenTokException(InvalidMaxDuration); + } + } + + private void ValidateResolution(ScreenResolution resolution) + { + if (!this.allowedResolutions.Contains(resolution)) + { + throw new OpenTokException(InvalidResolution); + } + } + + /// + /// Initial configuration of Publisher properties for the composed output stream. + /// + public class PublisherProperty + { + /// + /// Indicates StreamName needs to be provided. + /// + public const string MissingStreamName = "StreamName needs to be provided."; + + /// + /// Indicates StreamName cannot exceeds 200 characters. + /// + public const string OverflowStreamName = "StreamName cannot exceeds 200 characters."; + + /// + /// + /// + /// The name of the composed output stream which will be published to the session. The minimum length is + /// 1 and the maximum one is 200. + /// + public PublisherProperty(string name) + { + ValidateName(name); + this.Name = name; + } + + /// + /// The name of the composed output stream which will be published to the session. The minimum length is 1 and the + /// maximum one is 200. + /// + public string Name { get; } + + private static void ValidateName(string name) + { + if (string.IsNullOrWhiteSpace(name)) + { + throw new OpenTokException(MissingStreamName); + } + + if (name.Length > MaximumPropertyNameLength) + { + throw new OpenTokException(OverflowStreamName); + } + } + } + } +} \ No newline at end of file diff --git a/OpenTokTest/OpenTokTest.csproj b/OpenTokTest/OpenTokTest.csproj index b8bffe60..4599d312 100644 --- a/OpenTokTest/OpenTokTest.csproj +++ b/OpenTokTest/OpenTokTest.csproj @@ -232,6 +232,8 @@ + + diff --git a/OpenTokTest/Render/StartRenderRequestDataBuilder.cs b/OpenTokTest/Render/StartRenderRequestDataBuilder.cs new file mode 100644 index 00000000..8228aa33 --- /dev/null +++ b/OpenTokTest/Render/StartRenderRequestDataBuilder.cs @@ -0,0 +1,117 @@ +using System; +using AutoFixture; +using OpenTokSDK.Render; + +namespace OpenTokSDKTest.Render +{ + public class StartRenderRequestDataBuilder + { + private int? maxDuration; + private ScreenResolution? resolution; + private string sessionId; + private Uri statusCallbackUrl; + private string streamName; + private string token; + private Uri url; + + private StartRenderRequestDataBuilder() + { + var fixture = new Fixture(); + this.sessionId = fixture.Create(); + this.token = fixture.Create(); + this.url = fixture.Create(); + this.maxDuration = default; + this.resolution = default; + this.statusCallbackUrl = fixture.Create(); + this.streamName = fixture.Create(); + } + + public static StartRenderRequestDataBuilder Build() => new StartRenderRequestDataBuilder(); + + public StartRenderRequestDataBuilder WithSessionId(string value) + { + this.sessionId = value; + return this; + } + + public StartRenderRequestDataBuilder WithToken(string value) + { + this.token = value; + return this; + } + + public StartRenderRequestDataBuilder WithUrl(Uri value) + { + this.url = value; + return this; + } + + public StartRenderRequestDataBuilder WithStatusCallbackUrl(Uri value) + { + this.statusCallbackUrl = value; + return this; + } + + public StartRenderRequestDataBuilder WithResolution(ScreenResolution value) + { + this.resolution = value; + return this; + } + + public StartRenderRequest Create() + { + if (this.maxDuration.HasValue && this.resolution.HasValue) + { + return new StartRenderRequest( + this.sessionId, + this.token, + this.url, + this.statusCallbackUrl, + this.streamName, + this.maxDuration.Value, + this.resolution.Value); + } + + if (this.maxDuration.HasValue) + { + return new StartRenderRequest( + this.sessionId, + this.token, + this.url, + this.statusCallbackUrl, + this.streamName, + this.maxDuration.Value); + } + + if (this.resolution.HasValue) + { + return new StartRenderRequest( + this.sessionId, + this.token, + this.url, + this.statusCallbackUrl, + this.streamName, + resolution: this.resolution.Value); + } + + return new StartRenderRequest( + this.sessionId, + this.token, + this.url, + this.statusCallbackUrl, + this.streamName); + } + + public StartRenderRequestDataBuilder WithMaxDuration(int value) + { + this.maxDuration = value; + return this; + } + + public StartRenderRequestDataBuilder WithStreamName(string value) + { + this.streamName = value; + return this; + } + } +} \ No newline at end of file diff --git a/OpenTokTest/Render/StartRenderRequestTest.cs b/OpenTokTest/Render/StartRenderRequestTest.cs new file mode 100644 index 00000000..2d706ef8 --- /dev/null +++ b/OpenTokTest/Render/StartRenderRequestTest.cs @@ -0,0 +1,136 @@ +using System; +using System.Linq; +using OpenTokSDK.Exception; +using OpenTokSDK.Render; +using Xunit; + +namespace OpenTokSDKTest.Render +{ + public class StartRenderRequestTest + { + [Theory] + [InlineData(null)] + [InlineData("")] + [InlineData(" ")] + public void StartRenderRequest_ShouldThrowOpenTokException_GivenSessionIdIsNotProvided(string sessionId) + { + void Act() => StartRenderRequestDataBuilder.Build().WithSessionId(sessionId).Create(); + var exception = Assert.Throws(Act); + Assert.Equal(StartRenderRequest.MissingSessionId, exception.Message); + } + + [Theory] + [InlineData(null)] + [InlineData("")] + [InlineData(" ")] + public void StartRenderRequest_ShouldThrowOpenTokException_GivenStreamNameIsNotProvided(string streamName) + { + void Act() => StartRenderRequestDataBuilder.Build().WithStreamName(streamName).Create(); + var exception = Assert.Throws(Act); + Assert.Equal(StartRenderRequest.PublisherProperty.MissingStreamName, exception.Message); + } + + [Theory] + [InlineData(null)] + [InlineData("")] + [InlineData(" ")] + public void StartRenderRequest_ShouldThrowOpenTokException_GivenTokenIsNotProvided(string token) + { + void Act() => StartRenderRequestDataBuilder.Build().WithToken(token).Create(); + var exception = Assert.Throws(Act); + Assert.Equal(StartRenderRequest.MissingToken, exception.Message); + } + + [Theory] + [InlineData("http://localh/")] + [InlineData("https://local/")] + public void StartRenderRequest_ShouldThrowOpenTokException_GivenUrlLengthIsLowerThan15(string url) + { + void Act() => StartRenderRequestDataBuilder.Build().WithUrl(new Uri(url)).Create(); + var exception = Assert.Throws(Act); + Assert.Equal(StartRenderRequest.InvalidUrl, exception.Message); + } + + [Fact] + public void StartRenderRequest_ShouldThrowOpenTokException_GivenUrlLengthIsHigherThan2048() + { + var filler = string.Join(string.Empty, Enumerable.Range(0, 2021).Select(_ => 'a').ToArray()); + var uri = new Uri($"https://www.example.com?p={filler}/"); + void Act() => StartRenderRequestDataBuilder.Build().WithUrl(uri).Create(); + var exception = Assert.Throws(Act); + Assert.Equal(2049, uri.AbsoluteUri.Length); + Assert.Equal(StartRenderRequest.InvalidUrl, exception.Message); + } + + [Fact] + public void StartRenderRequest_ShouldThrowOpenTokException_GivenMaxDurationIsLowerThan60() + { + void Act() => StartRenderRequestDataBuilder.Build().WithMaxDuration(59).Create(); + var exception = Assert.Throws(Act); + Assert.Equal(StartRenderRequest.InvalidMaxDuration, exception.Message); + } + + [Fact] + public void StartRenderRequest_ShouldHave7200AsDefaultMaxDuration() + { + var request = StartRenderRequestDataBuilder.Build().Create(); + Assert.Equal(7200, request.MaxDuration); + } + + [Fact] + public void ConstructorShouldThrowOpenTokExceptionGivenMaxDurationIsHigherThan36000() + { + void Act() => StartRenderRequestDataBuilder.Build().WithMaxDuration(36001).Create(); + var exception = Assert.Throws(Act); + Assert.Equal(StartRenderRequest.InvalidMaxDuration, exception.Message); + } + + [Theory] + [InlineData("http://localh/")] + [InlineData("https://local/")] + public void StartRenderRequest_ShouldThrowOpenTokException_GivenStatusCallbackUrlLengthIsLowerThan15(string url) + { + void Act() => StartRenderRequestDataBuilder.Build().WithStatusCallbackUrl(new Uri(url)).Create(); + var exception = Assert.Throws(Act); + Assert.Equal(StartRenderRequest.InvalidStatusCallbackUrl, exception.Message); + } + + [Fact] + public void StartRenderRequest_ShouldThrowOpenTokException_GivenStatusCallbackUrlLengthIsHigherThan2048() + { + var filler = string.Join(string.Empty, Enumerable.Range(0, 2021).Select(_ => 'a').ToArray()); + var uri = new Uri($"https://www.example.com?p={filler}/"); + void Act() => StartRenderRequestDataBuilder.Build().WithStatusCallbackUrl(uri).Create(); + var exception = Assert.Throws(Act); + Assert.Equal(2049, uri.AbsoluteUri.Length); + Assert.Equal(StartRenderRequest.InvalidStatusCallbackUrl, exception.Message); + } + + [Theory] + [InlineData(ScreenResolution.HighDefinitionPortrait)] + [InlineData(ScreenResolution.FullHighDefinitionPortrait)] + public void StartRenderRequest_ShouldThrowOpenTokException_GivenResolutionIsNotAllowed( + ScreenResolution resolution) + { + void Act() => StartRenderRequestDataBuilder.Build().WithResolution(resolution).Create(); + var exception = Assert.Throws(Act); + Assert.Equal(StartRenderRequest.InvalidResolution, exception.Message); + } + + [Fact] + public void StartRenderRequest_ShouldHave1280x720AsDefaultResolution() + { + var request = StartRenderRequestDataBuilder.Build().Create(); + Assert.Equal(ScreenResolution.HighDefinitionLandscape, request.Resolution); + } + + [Fact] + public void StartRenderRequest_ShouldThrowOpenTokException_GivenStreamNameExceeds200length() + { + var streamName = string.Join(string.Empty, Enumerable.Range(0, 201).Select(_ => 'a').ToArray()); + void Act() => StartRenderRequestDataBuilder.Build().WithStreamName(streamName).Create(); + var exception = Assert.Throws(Act); + Assert.Equal(StartRenderRequest.PublisherProperty.OverflowStreamName, exception.Message); + } + } +} \ No newline at end of file From b4da8120a9081482bbbeec970d0f0cd011b95ee2 Mon Sep 17 00:00:00 2001 From: Tr00d Date: Tue, 11 Oct 2022 08:20:39 +0200 Subject: [PATCH 02/23] Fix wrong allowed resolution --- OpenTok/Render/StartRenderRequest.cs | 2 +- OpenTokTest/Render/StartRenderRequestTest.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/OpenTok/Render/StartRenderRequest.cs b/OpenTok/Render/StartRenderRequest.cs index dc1bf3a1..65d4045e 100644 --- a/OpenTok/Render/StartRenderRequest.cs +++ b/OpenTok/Render/StartRenderRequest.cs @@ -47,9 +47,9 @@ public class StartRenderRequest private readonly ScreenResolution[] allowedResolutions = { ScreenResolution.HighDefinitionLandscape, + ScreenResolution.HighDefinitionPortrait, ScreenResolution.StandardDefinitionLandscape, ScreenResolution.StandardDefinitionPortrait, - ScreenResolution.FullHighDefinitionLandscape, }; /// diff --git a/OpenTokTest/Render/StartRenderRequestTest.cs b/OpenTokTest/Render/StartRenderRequestTest.cs index 2d706ef8..6589df1b 100644 --- a/OpenTokTest/Render/StartRenderRequestTest.cs +++ b/OpenTokTest/Render/StartRenderRequestTest.cs @@ -107,7 +107,7 @@ public void StartRenderRequest_ShouldThrowOpenTokException_GivenStatusCallbackUr } [Theory] - [InlineData(ScreenResolution.HighDefinitionPortrait)] + [InlineData(ScreenResolution.FullHighDefinitionLandscape)] [InlineData(ScreenResolution.FullHighDefinitionPortrait)] public void StartRenderRequest_ShouldThrowOpenTokException_GivenResolutionIsNotAllowed( ScreenResolution resolution) From 9cabae60c3447255e8edc09fa01c372a8d776a9b Mon Sep 17 00:00:00 2001 From: Tr00d Date: Tue, 11 Oct 2022 08:39:22 +0200 Subject: [PATCH 03/23] Implement request creation with various values, including optional ones --- .../Render/StartRenderRequestDataBuilder.cs | 4 +-- OpenTokTest/Render/StartRenderRequestTest.cs | 28 +++++++++++++++++++ 2 files changed, 30 insertions(+), 2 deletions(-) diff --git a/OpenTokTest/Render/StartRenderRequestDataBuilder.cs b/OpenTokTest/Render/StartRenderRequestDataBuilder.cs index 8228aa33..2a8bf831 100644 --- a/OpenTokTest/Render/StartRenderRequestDataBuilder.cs +++ b/OpenTokTest/Render/StartRenderRequestDataBuilder.cs @@ -52,7 +52,7 @@ public StartRenderRequestDataBuilder WithStatusCallbackUrl(Uri value) return this; } - public StartRenderRequestDataBuilder WithResolution(ScreenResolution value) + public StartRenderRequestDataBuilder WithResolution(ScreenResolution? value) { this.resolution = value; return this; @@ -102,7 +102,7 @@ public StartRenderRequest Create() this.streamName); } - public StartRenderRequestDataBuilder WithMaxDuration(int value) + public StartRenderRequestDataBuilder WithMaxDuration(int? value) { this.maxDuration = value; return this; diff --git a/OpenTokTest/Render/StartRenderRequestTest.cs b/OpenTokTest/Render/StartRenderRequestTest.cs index 6589df1b..5cfd2494 100644 --- a/OpenTokTest/Render/StartRenderRequestTest.cs +++ b/OpenTokTest/Render/StartRenderRequestTest.cs @@ -132,5 +132,33 @@ public void StartRenderRequest_ShouldThrowOpenTokException_GivenStreamNameExceed var exception = Assert.Throws(Act); Assert.Equal(StartRenderRequest.PublisherProperty.OverflowStreamName, exception.Message); } + + [Theory] + [InlineData("sessionId", "token", "https://www.example.com/", "http://www.example.com/callback", "stream", 1200, ScreenResolution.StandardDefinitionLandscape)] + [InlineData("sessionId", "token", "https://www.example.com/", "http://www.example.com/callback", "stream", 60, ScreenResolution.StandardDefinitionPortrait)] + [InlineData("sessionId", "token", "https://www.example.com/", "http://www.example.com/callback", "stream", 36000, ScreenResolution.HighDefinitionLandscape)] + [InlineData("sessionId", "token", "https://www.example.com/", "http://www.example.com/callback", "stream", 15647, ScreenResolution.HighDefinitionPortrait)] + [InlineData("sessionId", "token", "https://www.example.com/", "http://www.example.com/callback", "stream", null, ScreenResolution.StandardDefinitionLandscape)] + [InlineData("sessionId", "token", "https://www.example.com/", "http://www.example.com/callback", "stream", 36000, null)] + public void StartRenderRequest_ShouldReturnInstance(string sessionId, string token, string url, string callbackUrl, string streamName, int? maxDuration, ScreenResolution? resolution) + { + var request = StartRenderRequestDataBuilder + .Build() + .WithSessionId(sessionId) + .WithToken(token) + .WithUrl(new Uri(url)) + .WithStatusCallbackUrl(new Uri(callbackUrl)) + .WithStreamName(streamName) + .WithMaxDuration(maxDuration) + .WithResolution(resolution) + .Create(); + Assert.Equal(sessionId, request.SessionId); + Assert.Equal(token, request.Token); + Assert.Equal(url, request.Url.AbsoluteUri); + Assert.Equal(callbackUrl, request.StatusCallbackUrl.AbsoluteUri); + Assert.Equal(streamName, request.Properties.Name); + Assert.Equal(maxDuration ?? 7200, request.MaxDuration); + Assert.Equal(resolution ?? ScreenResolution.HighDefinitionLandscape, request.Resolution); + } } } \ No newline at end of file From b40fdbcfc177a37c9022752aa416e8b03c658058 Mon Sep 17 00:00:00 2001 From: Tr00d Date: Tue, 11 Oct 2022 08:42:10 +0200 Subject: [PATCH 04/23] Fix warning for http (test value) --- OpenTokTest/Render/StartRenderRequestTest.cs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/OpenTokTest/Render/StartRenderRequestTest.cs b/OpenTokTest/Render/StartRenderRequestTest.cs index 5cfd2494..304f1355 100644 --- a/OpenTokTest/Render/StartRenderRequestTest.cs +++ b/OpenTokTest/Render/StartRenderRequestTest.cs @@ -134,12 +134,12 @@ public void StartRenderRequest_ShouldThrowOpenTokException_GivenStreamNameExceed } [Theory] - [InlineData("sessionId", "token", "https://www.example.com/", "http://www.example.com/callback", "stream", 1200, ScreenResolution.StandardDefinitionLandscape)] - [InlineData("sessionId", "token", "https://www.example.com/", "http://www.example.com/callback", "stream", 60, ScreenResolution.StandardDefinitionPortrait)] - [InlineData("sessionId", "token", "https://www.example.com/", "http://www.example.com/callback", "stream", 36000, ScreenResolution.HighDefinitionLandscape)] - [InlineData("sessionId", "token", "https://www.example.com/", "http://www.example.com/callback", "stream", 15647, ScreenResolution.HighDefinitionPortrait)] - [InlineData("sessionId", "token", "https://www.example.com/", "http://www.example.com/callback", "stream", null, ScreenResolution.StandardDefinitionLandscape)] - [InlineData("sessionId", "token", "https://www.example.com/", "http://www.example.com/callback", "stream", 36000, null)] + [InlineData("sessionId", "token", "https://www.example.com/", "https://www.example.com/callback", "stream", 1200, ScreenResolution.StandardDefinitionLandscape)] + [InlineData("sessionId", "token", "https://www.example.com/", "https://www.example.com/callback", "stream", 60, ScreenResolution.StandardDefinitionPortrait)] + [InlineData("sessionId", "token", "https://www.example.com/", "https://www.example.com/callback", "stream", 36000, ScreenResolution.HighDefinitionLandscape)] + [InlineData("sessionId", "token", "https://www.example.com/", "https://www.example.com/callback", "stream", 15647, ScreenResolution.HighDefinitionPortrait)] + [InlineData("sessionId", "token", "https://www.example.com/", "https://www.example.com/callback", "stream", null, ScreenResolution.StandardDefinitionLandscape)] + [InlineData("sessionId", "token", "https://www.example.com/", "https://www.example.com/callback", "stream", 36000, null)] public void StartRenderRequest_ShouldReturnInstance(string sessionId, string token, string url, string callbackUrl, string streamName, int? maxDuration, ScreenResolution? resolution) { var request = StartRenderRequestDataBuilder From c732ea6960e916b68a0eefb8667bb0a9d95eed5e Mon Sep 17 00:00:00 2001 From: Tr00d Date: Tue, 11 Oct 2022 08:53:09 +0200 Subject: [PATCH 05/23] Kill last mutants for threshold values --- OpenTokTest/Render/StartRenderRequestTest.cs | 30 ++++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/OpenTokTest/Render/StartRenderRequestTest.cs b/OpenTokTest/Render/StartRenderRequestTest.cs index 304f1355..090df5e7 100644 --- a/OpenTokTest/Render/StartRenderRequestTest.cs +++ b/OpenTokTest/Render/StartRenderRequestTest.cs @@ -61,6 +61,15 @@ public void StartRenderRequest_ShouldThrowOpenTokException_GivenUrlLengthIsHighe Assert.Equal(2049, uri.AbsoluteUri.Length); Assert.Equal(StartRenderRequest.InvalidUrl, exception.Message); } + + [Fact] + public void StartRenderRequest_ShouldReturnInstance_GivenUrlHasMaximumLength() + { + var filler = string.Join(string.Empty, Enumerable.Range(0, 2020).Select(_ => 'a').ToArray()); + var uri = new Uri($"https://www.example.com?p={filler}/"); + var request = StartRenderRequestDataBuilder.Build().WithUrl(uri).Create(); + Assert.Equal(uri, request.Url); + } [Fact] public void StartRenderRequest_ShouldThrowOpenTokException_GivenMaxDurationIsLowerThan60() @@ -105,6 +114,15 @@ public void StartRenderRequest_ShouldThrowOpenTokException_GivenStatusCallbackUr Assert.Equal(2049, uri.AbsoluteUri.Length); Assert.Equal(StartRenderRequest.InvalidStatusCallbackUrl, exception.Message); } + + [Fact] + public void StartRenderRequest_ShouldReturnInstance_GivenStatusCallbackUrlHasMaximumLength() + { + var filler = string.Join(string.Empty, Enumerable.Range(0, 2020).Select(_ => 'a').ToArray()); + var uri = new Uri($"https://www.example.com?p={filler}/"); + var request = StartRenderRequestDataBuilder.Build().WithStatusCallbackUrl(uri).Create(); + Assert.Equal(uri, request.StatusCallbackUrl); + } [Theory] [InlineData(ScreenResolution.FullHighDefinitionLandscape)] @@ -132,14 +150,22 @@ public void StartRenderRequest_ShouldThrowOpenTokException_GivenStreamNameExceed var exception = Assert.Throws(Act); Assert.Equal(StartRenderRequest.PublisherProperty.OverflowStreamName, exception.Message); } + + [Fact] + public void StartRenderRequest_ShouldReturnInstance_GivenStreamNameHasMaximumLength() + { + var streamName = string.Join(string.Empty, Enumerable.Range(0, 200).Select(_ => 'a').ToArray()); + var request = StartRenderRequestDataBuilder.Build().WithStreamName(streamName).Create(); + Assert.Equal(streamName, request.Properties.Name); + } [Theory] [InlineData("sessionId", "token", "https://www.example.com/", "https://www.example.com/callback", "stream", 1200, ScreenResolution.StandardDefinitionLandscape)] [InlineData("sessionId", "token", "https://www.example.com/", "https://www.example.com/callback", "stream", 60, ScreenResolution.StandardDefinitionPortrait)] [InlineData("sessionId", "token", "https://www.example.com/", "https://www.example.com/callback", "stream", 36000, ScreenResolution.HighDefinitionLandscape)] [InlineData("sessionId", "token", "https://www.example.com/", "https://www.example.com/callback", "stream", 15647, ScreenResolution.HighDefinitionPortrait)] - [InlineData("sessionId", "token", "https://www.example.com/", "https://www.example.com/callback", "stream", null, ScreenResolution.StandardDefinitionLandscape)] - [InlineData("sessionId", "token", "https://www.example.com/", "https://www.example.com/callback", "stream", 36000, null)] + [InlineData("sessionId", "token", "https://www.example.com/", "https://hel.fr/", "stream", null, ScreenResolution.StandardDefinitionLandscape)] + [InlineData("sessionId", "token", "https://hel.fr/", "https://www.example.com/callback", "stream", 36000, null)] public void StartRenderRequest_ShouldReturnInstance(string sessionId, string token, string url, string callbackUrl, string streamName, int? maxDuration, ScreenResolution? resolution) { var request = StartRenderRequestDataBuilder From 540638304e7ba03170e91b250597324442ffd93b Mon Sep 17 00:00:00 2001 From: Tr00d Date: Tue, 11 Oct 2022 16:51:59 +0200 Subject: [PATCH 06/23] Implement POST call to start a rendering --- OpenTok/OpenTok.Render.cs | 34 ++++++++++++++++++ OpenTok/OpenTok.cs | 2 +- OpenTok/Render/StartRenderRequest.cs | 17 +++++++++ OpenTok/Render/StartRenderResponse.cs | 52 +++++++++++++++++++++++++++ OpenTokTest/OpenTok.RenderTests.cs | 47 ++++++++++++++++++++++++ 5 files changed, 151 insertions(+), 1 deletion(-) create mode 100644 OpenTok/OpenTok.Render.cs create mode 100644 OpenTok/Render/StartRenderResponse.cs create mode 100644 OpenTokTest/OpenTok.RenderTests.cs diff --git a/OpenTok/OpenTok.Render.cs b/OpenTok/OpenTok.Render.cs new file mode 100644 index 00000000..a460efb5 --- /dev/null +++ b/OpenTok/OpenTok.Render.cs @@ -0,0 +1,34 @@ +using System.Collections.Generic; +using System.Threading.Tasks; +using Newtonsoft.Json; +using OpenTokSDK.Render; + +namespace OpenTokSDK +{ + public partial class OpenTok + { + /// + /// Indicates the StartRender endpoint (/render) + /// + public const string StartRenderEndpoint = "/render"; + + /// + /// TODO + /// + /// TODO + /// TODO + public async Task StartRenderAsync(StartRenderRequest request) + { + var response = await this.Client.PostAsync( + this.BuildUrl(StartRenderEndpoint), + GetHeaderDictionary("application/json"), + request.ToDataDictionary()); + return JsonConvert.DeserializeObject(response); + } + + private string BuildUrl(string endpoint) => $"v2/project/{ApiKey}{endpoint}"; + + private static Dictionary GetHeaderDictionary(string contentType) => + new Dictionary {{"Content-Type", contentType}}; + } +} \ No newline at end of file diff --git a/OpenTok/OpenTok.cs b/OpenTok/OpenTok.cs index 1032cadc..45435f6b 100644 --- a/OpenTok/OpenTok.cs +++ b/OpenTok/OpenTok.cs @@ -18,7 +18,7 @@ namespace OpenTokSDK /// (only on your web server) to create OpenTok sessions. /// /// - public class OpenTok + public partial class OpenTok { /// /// The OpenTok API key passed into the OpenTok() constructor. diff --git a/OpenTok/Render/StartRenderRequest.cs b/OpenTok/Render/StartRenderRequest.cs index 65d4045e..60e430a4 100644 --- a/OpenTok/Render/StartRenderRequest.cs +++ b/OpenTok/Render/StartRenderRequest.cs @@ -1,5 +1,7 @@ using System; +using System.Collections.Generic; using System.Linq; +using EnumsNET; using OpenTokSDK.Exception; namespace OpenTokSDK.Render @@ -183,6 +185,21 @@ private void ValidateResolution(ScreenResolution resolution) } } + /// + /// + /// + public Dictionary ToDataDictionary() => + new Dictionary + { + {"sessionId", this.SessionId}, + {"token", this.Token}, + {"url", this.Url}, + {"statusCallbackUrl", this.StatusCallbackUrl}, + {"maxDuration", this.MaxDuration}, + {"resolution", this.Resolution.AsString(EnumFormat.Description)}, + {"properties", this.Properties}, + }; + /// /// Initial configuration of Publisher properties for the composed output stream. /// diff --git a/OpenTok/Render/StartRenderResponse.cs b/OpenTok/Render/StartRenderResponse.cs new file mode 100644 index 00000000..64c40b68 --- /dev/null +++ b/OpenTok/Render/StartRenderResponse.cs @@ -0,0 +1,52 @@ +using System; + +namespace OpenTokSDK.Render +{ + /// + /// + public struct StartRenderResponse + { + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + public StartRenderResponse(string id, string sessionId, string projectId, int createdAt, int updatedAt, Uri url, + ScreenResolution resolution, string status, string streamId) + { + this.Id = id; + this.SessionId = sessionId; + this.ProjectId = projectId; + this.CreatedAt = createdAt; + this.UpdatedAt = updatedAt; + this.Url = url; + this.Resolution = resolution; + this.Status = status; + this.StreamId = streamId; + } + + public string Id { get; set; } + + public string SessionId { get; set; } + + public string ProjectId { get; set; } + + public int CreatedAt { get; set; } + + public int UpdatedAt { get; set; } + + public Uri Url { get; set; } + + public ScreenResolution Resolution { get; set; } + + public string Status { get; set; } + + public string StreamId { get; set; } + } +} \ No newline at end of file diff --git a/OpenTokTest/OpenTok.RenderTests.cs b/OpenTokTest/OpenTok.RenderTests.cs new file mode 100644 index 00000000..923a3b4f --- /dev/null +++ b/OpenTokTest/OpenTok.RenderTests.cs @@ -0,0 +1,47 @@ +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using AutoFixture; +using Moq; +using Newtonsoft.Json; +using OpenTokSDK; +using OpenTokSDK.Render; +using OpenTokSDK.Util; +using OpenTokSDKTest.Render; +using Xunit; + +namespace OpenTokSDKTest +{ + public class OpenTokRenderTests + { + private readonly Fixture fixture; + private readonly Mock mockClient; + private readonly OpenTok sut; + + public OpenTokRenderTests() + { + this.fixture = new Fixture(); + this.mockClient = new Mock(); + this.sut = new OpenTok(this.fixture.Create(), this.fixture.Create()) + { + Client = this.mockClient.Object, + }; + } + + [Fact] + public async Task StartRenderAsync_ShouldReturnAFuckingResponse_GivenThisTestHasNoValue() + { + var expectedResponse = this.fixture.Create(); + var serializedResponse = JsonConvert.SerializeObject(expectedResponse); + var request = StartRenderRequestDataBuilder.Build().Create(); + this.mockClient.Setup(httpClient => httpClient.PostAsync( + It.Is(url => url.EndsWith(OpenTok.StartRenderEndpoint)), + It.IsAny>(), + It.Is>(dictionary => + dictionary.SequenceEqual(request.ToDataDictionary())))) + .ReturnsAsync(serializedResponse); + var response = await this.sut.StartRenderAsync(request); + Assert.Equal(expectedResponse, response); + } + } +} \ No newline at end of file From caa94342c3e92a6f5320e45abf591a90ca82f8a9 Mon Sep 17 00:00:00 2001 From: Tr00d Date: Tue, 11 Oct 2022 16:53:36 +0200 Subject: [PATCH 07/23] Make StartRenderResponse immutable --- OpenTok/Render/StartRenderResponse.cs | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/OpenTok/Render/StartRenderResponse.cs b/OpenTok/Render/StartRenderResponse.cs index 64c40b68..c8615b5b 100644 --- a/OpenTok/Render/StartRenderResponse.cs +++ b/OpenTok/Render/StartRenderResponse.cs @@ -3,6 +3,7 @@ namespace OpenTokSDK.Render { /// + /// TODO /// public struct StartRenderResponse { @@ -31,22 +32,22 @@ public StartRenderResponse(string id, string sessionId, string projectId, int cr this.StreamId = streamId; } - public string Id { get; set; } + public string Id { get; } - public string SessionId { get; set; } + public string SessionId { get; } - public string ProjectId { get; set; } + public string ProjectId { get; } - public int CreatedAt { get; set; } + public int CreatedAt { get; } - public int UpdatedAt { get; set; } + public int UpdatedAt { get; } - public Uri Url { get; set; } + public Uri Url { get; } - public ScreenResolution Resolution { get; set; } + public ScreenResolution Resolution { get; } - public string Status { get; set; } + public string Status { get; } - public string StreamId { get; set; } + public string StreamId { get; } } } \ No newline at end of file From 589ebe5dbd2143a886c9abe1535cc3c40ef29038 Mon Sep 17 00:00:00 2001 From: Tr00d Date: Tue, 11 Oct 2022 17:24:57 +0200 Subject: [PATCH 08/23] Implement StopRenderAsync --- OpenTok/OpenTok.Render.cs | 21 ++++++++++---- OpenTok/Render/StartRenderRequest.cs | 1 + OpenTokTest/OpenTok.RenderTests.cs | 43 ++++++++++++++++++++++++++-- 3 files changed, 56 insertions(+), 9 deletions(-) diff --git a/OpenTok/OpenTok.Render.cs b/OpenTok/OpenTok.Render.cs index a460efb5..e2d11896 100644 --- a/OpenTok/OpenTok.Render.cs +++ b/OpenTok/OpenTok.Render.cs @@ -1,4 +1,5 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using System.Threading.Tasks; using Newtonsoft.Json; using OpenTokSDK.Render; @@ -7,10 +8,7 @@ namespace OpenTokSDK { public partial class OpenTok { - /// - /// Indicates the StartRender endpoint (/render) - /// - public const string StartRenderEndpoint = "/render"; + private const string RenderEndpoint = "/render"; /// /// TODO @@ -20,14 +18,25 @@ public partial class OpenTok public async Task StartRenderAsync(StartRenderRequest request) { var response = await this.Client.PostAsync( - this.BuildUrl(StartRenderEndpoint), + this.BuildUrl(RenderEndpoint), GetHeaderDictionary("application/json"), request.ToDataDictionary()); return JsonConvert.DeserializeObject(response); } + /// + /// TODO + /// + /// TODO + public async Task StopRenderAsync(string renderId) => + await this.Client.DeleteAsync( + this.BuildUrlWithQuery(RenderEndpoint, renderId), + new Dictionary()); + private string BuildUrl(string endpoint) => $"v2/project/{ApiKey}{endpoint}"; + private string BuildUrlWithQuery(string endpoint, string query) => $"{this.BuildUrl(endpoint)}/{query}"; + private static Dictionary GetHeaderDictionary(string contentType) => new Dictionary {{"Content-Type", contentType}}; } diff --git a/OpenTok/Render/StartRenderRequest.cs b/OpenTok/Render/StartRenderRequest.cs index 60e430a4..d6e95ffc 100644 --- a/OpenTok/Render/StartRenderRequest.cs +++ b/OpenTok/Render/StartRenderRequest.cs @@ -7,6 +7,7 @@ namespace OpenTokSDK.Render { /// + /// Request for start a rendering. /// public class StartRenderRequest { diff --git a/OpenTokTest/OpenTok.RenderTests.cs b/OpenTokTest/OpenTok.RenderTests.cs index 923a3b4f..08443bed 100644 --- a/OpenTokTest/OpenTok.RenderTests.cs +++ b/OpenTokTest/OpenTok.RenderTests.cs @@ -17,25 +17,51 @@ public class OpenTokRenderTests private readonly Fixture fixture; private readonly Mock mockClient; private readonly OpenTok sut; + private readonly int apiKey; public OpenTokRenderTests() { this.fixture = new Fixture(); + this.apiKey = this.fixture.Create(); this.mockClient = new Mock(); - this.sut = new OpenTok(this.fixture.Create(), this.fixture.Create()) + + this.sut = new OpenTok(this.apiKey, this.fixture.Create()) { Client = this.mockClient.Object, }; } [Fact] - public async Task StartRenderAsync_ShouldReturnAFuckingResponse_GivenThisTestHasNoValue() + public async Task StartRenderAsync_ShouldInitiateRendering() { + var expectedUrl = $"v2/project/{this.apiKey}/render"; var expectedResponse = this.fixture.Create(); var serializedResponse = JsonConvert.SerializeObject(expectedResponse); var request = StartRenderRequestDataBuilder.Build().Create(); this.mockClient.Setup(httpClient => httpClient.PostAsync( - It.Is(url => url.EndsWith(OpenTok.StartRenderEndpoint)), + expectedUrl, + It.IsAny>(), + It.Is>(dictionary => + dictionary.SequenceEqual(request.ToDataDictionary())))) + .ReturnsAsync(serializedResponse); + _ = await this.sut.StartRenderAsync(request); + this.mockClient.Verify(httpClient => httpClient.PostAsync( + It.Is(url => url == expectedUrl), + It.IsAny>(), + It.Is>(dictionary => + dictionary.SequenceEqual(request.ToDataDictionary()))), + Times.Once); + } + + [Fact] + public async Task StartRenderAsync_ShouldReturnResponse() + { + var expectedUrl = $"v2/project/{this.apiKey}/render"; + var expectedResponse = this.fixture.Create(); + var serializedResponse = JsonConvert.SerializeObject(expectedResponse); + var request = StartRenderRequestDataBuilder.Build().Create(); + this.mockClient.Setup(httpClient => httpClient.PostAsync( + expectedUrl, It.IsAny>(), It.Is>(dictionary => dictionary.SequenceEqual(request.ToDataDictionary())))) @@ -43,5 +69,16 @@ public async Task StartRenderAsync_ShouldReturnAFuckingResponse_GivenThisTestHas var response = await this.sut.StartRenderAsync(request); Assert.Equal(expectedResponse, response); } + + [Fact] + public async Task StopRenderAsync_ShouldDeleteRendering() + { + var renderId = this.fixture.Create(); + await this.sut.StopRenderAsync(renderId); + this.mockClient.Verify(httpClient => httpClient.DeleteAsync( + $"v2/project/{this.apiKey}/render/{renderId}", + It.Is>(dictionary => dictionary.Count == 0)), + Times.Once); + } } } \ No newline at end of file From 8e1d68d8cdd47f26cf6c59a525674b8b73634ef2 Mon Sep 17 00:00:00 2001 From: Tr00d Date: Tue, 11 Oct 2022 18:20:50 +0200 Subject: [PATCH 09/23] Implement ListRendersRequest parsing --- OpenTok/Render/ListRendersRequest.cs | 93 +++++++++++++++++++ OpenTok/Render/StartRenderRequest.cs | 2 +- OpenTokTest/Render/ListRendersRequestTests.cs | 60 ++++++++++++ 3 files changed, 154 insertions(+), 1 deletion(-) create mode 100644 OpenTok/Render/ListRendersRequest.cs create mode 100644 OpenTokTest/Render/ListRendersRequestTests.cs diff --git a/OpenTok/Render/ListRendersRequest.cs b/OpenTok/Render/ListRendersRequest.cs new file mode 100644 index 00000000..9cd03908 --- /dev/null +++ b/OpenTok/Render/ListRendersRequest.cs @@ -0,0 +1,93 @@ +using OpenTokSDK.Exception; + +namespace OpenTokSDK.Render +{ + /// + /// Represents a request for retrieving renders. + /// + public class ListRendersRequest + { + private const int DefaultCount = 50; + private const int MaximumCount = 1000; + private const int MinimumCount = 0; + private const int MinimumOffset = 0; + + /// + /// Indicates the maximum count has been exceeded. + /// + public const string CountExceeded = "Count cannot be higher than 1000."; + + /// + /// Indicates the provided count is negative. + /// + public const string NegaviteCount = "Count cannot be negative."; + + /// + /// Indicates the provided offset is negative. + /// + public const string NegaviteOffset = "Offset cannot be negative."; + + /// + /// Initializes a ListRendersRequest with default values. Count will be 50. + /// + public ListRendersRequest() + { + this.Count = DefaultCount; + } + + /// + /// Initializes a ListRendersRequest. + /// + /// Number of Renders to retrieve starting at offset. Default is 50, maximum is 1000. + public ListRendersRequest(int count) + : this() + { + ValidateCount(count); + this.Count = count; + } + + /// + /// Initializes a ListRendersRequest. + /// + /// Start offset in the list of existing Renders. + /// Number of Renders to retrieve starting at offset. Default is 50, maximum is 1000. + public ListRendersRequest(int offset, int count) + : this(count) + { + ValidateOffset(offset); + this.Offset = offset; + this.Count = count; + } + + /// + /// Start offset in the list of existing Renders. + /// + public int? Offset { get; } + + /// + /// Number of Renders to retrieve starting at offset. Default is 50, maximum is 1000. + /// + public int Count { get; } + + private static void ValidateCount(int count) + { + if (count > MaximumCount) + { + throw new OpenTokException(CountExceeded); + } + + if (count < MinimumCount) + { + throw new OpenTokException(NegaviteCount); + } + } + + private static void ValidateOffset(int offset) + { + if (offset < MinimumOffset) + { + throw new OpenTokException(NegaviteOffset); + } + } + } +} \ No newline at end of file diff --git a/OpenTok/Render/StartRenderRequest.cs b/OpenTok/Render/StartRenderRequest.cs index d6e95ffc..0996ebf6 100644 --- a/OpenTok/Render/StartRenderRequest.cs +++ b/OpenTok/Render/StartRenderRequest.cs @@ -7,7 +7,7 @@ namespace OpenTokSDK.Render { /// - /// Request for start a rendering. + /// Represents a request for starting a rendering. /// public class StartRenderRequest { diff --git a/OpenTokTest/Render/ListRendersRequestTests.cs b/OpenTokTest/Render/ListRendersRequestTests.cs new file mode 100644 index 00000000..65edc283 --- /dev/null +++ b/OpenTokTest/Render/ListRendersRequestTests.cs @@ -0,0 +1,60 @@ +using OpenTokSDK.Exception; +using OpenTokSDK.Render; +using Xunit; + +namespace OpenTokSDKTest.Render +{ + public class ListRendersRequestTests + { + [Fact] + public void ListRendersRequest_ShouldThrowOpenTokException_GivenCountIsHigherThanThreshold() + { + void Act() => new ListRendersRequest(1001); + var exception = Assert.Throws(Act); + Assert.Equal(ListRendersRequest.CountExceeded, exception.Message); + } + + [Fact] + public void ListRendersRequest_ShouldThrowOpenTokException_GivenCountIsNegative() + { + void Act() => new ListRendersRequest(-1); + var exception = Assert.Throws(Act); + Assert.Equal(ListRendersRequest.NegaviteCount, exception.Message); + } + + [Fact] + public void ListRendersRequest_ShouldThrowOpenTokException_GivenOffsetIsNegative() + { + void Act() => new ListRendersRequest(-1, 1); + var exception = Assert.Throws(Act); + Assert.Equal(ListRendersRequest.NegaviteOffset, exception.Message); + } + + [Theory] + [InlineData(0, 0)] + public void ListRendersRequest_ShouldReturnInstance(int offset, int count) + { + var request = new ListRendersRequest(offset, count); + Assert.Equal(offset, request.Offset); + Assert.Equal(count, request.Count); + } + + [Theory] + [InlineData(0)] + [InlineData(1000)] + public void ListRendersRequest_ShouldReturnInstance_GivenOnlyCountIsProvided(int count) + { + var request = new ListRendersRequest(count); + Assert.Null(request.Offset); + Assert.Equal(count, request.Count); + } + + [Fact] + public void ListRendersRequest_ShouldHaveDefaultCount() + { + var request = new ListRendersRequest(); + Assert.Null(request.Offset); + Assert.Equal(50, request.Count); + } + } +} \ No newline at end of file From 9556a3debf3c2dfc45ce33e25cedbc749f7fec77 Mon Sep 17 00:00:00 2001 From: Tr00d Date: Tue, 11 Oct 2022 18:34:27 +0200 Subject: [PATCH 10/23] Kill mutants for http headers --- OpenTokTest/OpenTok.RenderTests.cs | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/OpenTokTest/OpenTok.RenderTests.cs b/OpenTokTest/OpenTok.RenderTests.cs index 08443bed..32e2d416 100644 --- a/OpenTokTest/OpenTok.RenderTests.cs +++ b/OpenTokTest/OpenTok.RenderTests.cs @@ -34,20 +34,22 @@ public OpenTokRenderTests() [Fact] public async Task StartRenderAsync_ShouldInitiateRendering() { + const string contentTypeKey = "Content-Type"; + const string contentType = "application/json"; var expectedUrl = $"v2/project/{this.apiKey}/render"; var expectedResponse = this.fixture.Create(); var serializedResponse = JsonConvert.SerializeObject(expectedResponse); var request = StartRenderRequestDataBuilder.Build().Create(); this.mockClient.Setup(httpClient => httpClient.PostAsync( expectedUrl, - It.IsAny>(), + It.Is>(dictionary => dictionary.ContainsKey(contentTypeKey) && dictionary[contentTypeKey] == contentType), It.Is>(dictionary => dictionary.SequenceEqual(request.ToDataDictionary())))) .ReturnsAsync(serializedResponse); _ = await this.sut.StartRenderAsync(request); this.mockClient.Verify(httpClient => httpClient.PostAsync( It.Is(url => url == expectedUrl), - It.IsAny>(), + It.Is>(dictionary => dictionary.ContainsKey(contentTypeKey) && dictionary[contentTypeKey] == contentType), It.Is>(dictionary => dictionary.SequenceEqual(request.ToDataDictionary()))), Times.Once); @@ -56,13 +58,15 @@ public async Task StartRenderAsync_ShouldInitiateRendering() [Fact] public async Task StartRenderAsync_ShouldReturnResponse() { + const string contentTypeKey = "Content-Type"; + const string contentType = "application/json"; var expectedUrl = $"v2/project/{this.apiKey}/render"; var expectedResponse = this.fixture.Create(); var serializedResponse = JsonConvert.SerializeObject(expectedResponse); var request = StartRenderRequestDataBuilder.Build().Create(); this.mockClient.Setup(httpClient => httpClient.PostAsync( expectedUrl, - It.IsAny>(), + It.Is>(dictionary => dictionary.ContainsKey(contentTypeKey) && dictionary[contentTypeKey] == contentType), It.Is>(dictionary => dictionary.SequenceEqual(request.ToDataDictionary())))) .ReturnsAsync(serializedResponse); From 4fce1d88f29a871493f9feed91aa4e2a3a33fb75 Mon Sep 17 00:00:00 2001 From: Tr00d Date: Wed, 12 Oct 2022 09:23:35 +0200 Subject: [PATCH 11/23] Fix type in ListRenders --- OpenTok/Render/ListRendersRequest.cs | 8 ++++---- OpenTokTest/Render/ListRendersRequestTests.cs | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/OpenTok/Render/ListRendersRequest.cs b/OpenTok/Render/ListRendersRequest.cs index 9cd03908..9eec636c 100644 --- a/OpenTok/Render/ListRendersRequest.cs +++ b/OpenTok/Render/ListRendersRequest.cs @@ -20,12 +20,12 @@ public class ListRendersRequest /// /// Indicates the provided count is negative. /// - public const string NegaviteCount = "Count cannot be negative."; + public const string NegativeCount = "Count cannot be negative."; /// /// Indicates the provided offset is negative. /// - public const string NegaviteOffset = "Offset cannot be negative."; + public const string NegativeOffset = "Offset cannot be negative."; /// /// Initializes a ListRendersRequest with default values. Count will be 50. @@ -78,7 +78,7 @@ private static void ValidateCount(int count) if (count < MinimumCount) { - throw new OpenTokException(NegaviteCount); + throw new OpenTokException(NegativeCount); } } @@ -86,7 +86,7 @@ private static void ValidateOffset(int offset) { if (offset < MinimumOffset) { - throw new OpenTokException(NegaviteOffset); + throw new OpenTokException(NegativeOffset); } } } diff --git a/OpenTokTest/Render/ListRendersRequestTests.cs b/OpenTokTest/Render/ListRendersRequestTests.cs index 65edc283..725495ad 100644 --- a/OpenTokTest/Render/ListRendersRequestTests.cs +++ b/OpenTokTest/Render/ListRendersRequestTests.cs @@ -19,7 +19,7 @@ public void ListRendersRequest_ShouldThrowOpenTokException_GivenCountIsNegative( { void Act() => new ListRendersRequest(-1); var exception = Assert.Throws(Act); - Assert.Equal(ListRendersRequest.NegaviteCount, exception.Message); + Assert.Equal(ListRendersRequest.NegativeCount, exception.Message); } [Fact] @@ -27,7 +27,7 @@ public void ListRendersRequest_ShouldThrowOpenTokException_GivenOffsetIsNegative { void Act() => new ListRendersRequest(-1, 1); var exception = Assert.Throws(Act); - Assert.Equal(ListRendersRequest.NegaviteOffset, exception.Message); + Assert.Equal(ListRendersRequest.NegativeOffset, exception.Message); } [Theory] From cef4efea41931691273c9d1b82b0c0eb6737916f Mon Sep 17 00:00:00 2001 From: Tr00d Date: Wed, 12 Oct 2022 16:45:05 +0200 Subject: [PATCH 12/23] Implement ListRendersAsync --- OpenTok/OpenTok.Render.cs | 23 +++++-- OpenTok/Render/ListRenderItem.cs | 88 +++++++++++++++++++++++++++ OpenTok/Render/ListRendersRequest.cs | 15 +++++ OpenTok/Render/ListRendersResponse.cs | 20 ++++++ OpenTokTest/OpenTok.RenderTests.cs | 48 ++++++++++++--- 5 files changed, 181 insertions(+), 13 deletions(-) create mode 100644 OpenTok/Render/ListRenderItem.cs create mode 100644 OpenTok/Render/ListRendersResponse.cs diff --git a/OpenTok/OpenTok.Render.cs b/OpenTok/OpenTok.Render.cs index e2d11896..3e07bae2 100644 --- a/OpenTok/OpenTok.Render.cs +++ b/OpenTok/OpenTok.Render.cs @@ -1,5 +1,4 @@ -using System; -using System.Collections.Generic; +using System.Collections.Generic; using System.Threading.Tasks; using Newtonsoft.Json; using OpenTokSDK.Render; @@ -30,12 +29,28 @@ public async Task StartRenderAsync(StartRenderRequest reque /// TODO public async Task StopRenderAsync(string renderId) => await this.Client.DeleteAsync( - this.BuildUrlWithQuery(RenderEndpoint, renderId), + this.BuildUrlWithRouteParameter(RenderEndpoint, renderId), new Dictionary()); + /// + /// TODO + /// + /// TODO + /// TODO + public async Task ListRendersAsync(ListRendersRequest request) + { + var url = this.BuildUrlWithQueryParameter(RenderEndpoint, request.ToQueryParameters()); + var response = await this.Client.GetAsync(url); + return JsonConvert.DeserializeObject(response); + } + private string BuildUrl(string endpoint) => $"v2/project/{ApiKey}{endpoint}"; - private string BuildUrlWithQuery(string endpoint, string query) => $"{this.BuildUrl(endpoint)}/{query}"; + private string BuildUrlWithRouteParameter(string endpoint, string routeParameter) => + $"{this.BuildUrl(endpoint)}/{routeParameter}"; + + private string BuildUrlWithQueryParameter(string endpoint, string queryParameter) => + $"{this.BuildUrl(endpoint)}?{queryParameter}"; private static Dictionary GetHeaderDictionary(string contentType) => new Dictionary {{"Content-Type", contentType}}; diff --git a/OpenTok/Render/ListRenderItem.cs b/OpenTok/Render/ListRenderItem.cs new file mode 100644 index 00000000..723568f6 --- /dev/null +++ b/OpenTok/Render/ListRenderItem.cs @@ -0,0 +1,88 @@ +using System; + +namespace OpenTokSDK.Render +{ + /// + /// + /// + public struct ListRenderItem + { + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + public ListRenderItem(string id, string sessionId, string projectId, int createdAt, int updatedAt, Uri url, + ScreenResolution resolution, string status, string streamId, string reason) + { + this.Id = id; + this.SessionId = sessionId; + this.ProjectId = projectId; + this.CreatedAt = createdAt; + this.UpdatedAt = updatedAt; + this.Url = url; + this.Resolution = resolution; + this.Status = status; + this.StreamId = streamId; + this.Reason = reason; + } + + /// + /// + /// + public string Id { get; set; } + + /// + /// + /// + public string SessionId { get; set; } + + /// + /// + /// + public string ProjectId { get; set; } + + /// + /// + /// + public int CreatedAt { get; set; } + + /// + /// + /// + public int UpdatedAt { get; set; } + + /// + /// + /// + public Uri Url { get; set; } + + /// + /// + /// + public ScreenResolution Resolution { get; set; } + + /// + /// + /// + public string Status { get; set; } + + /// + /// + /// + public string StreamId { get; set; } + + /// + /// + /// + public string Reason { get; set; } + } +} \ No newline at end of file diff --git a/OpenTok/Render/ListRendersRequest.cs b/OpenTok/Render/ListRendersRequest.cs index 9eec636c..3281c723 100644 --- a/OpenTok/Render/ListRendersRequest.cs +++ b/OpenTok/Render/ListRendersRequest.cs @@ -89,5 +89,20 @@ private static void ValidateOffset(int offset) throw new OpenTokException(NegativeOffset); } } + + /// + /// TODO + /// + /// TODO + public string ToQueryParameters() + { + var parameters = $"count={this.Count}"; + if (this.Offset.HasValue) + { + parameters += $"&offset={this.Offset}"; + } + + return parameters; + } } } \ No newline at end of file diff --git a/OpenTok/Render/ListRendersResponse.cs b/OpenTok/Render/ListRendersResponse.cs new file mode 100644 index 00000000..fa38e97a --- /dev/null +++ b/OpenTok/Render/ListRendersResponse.cs @@ -0,0 +1,20 @@ +using System.Collections.Generic; + +namespace OpenTokSDK.Render +{ + /// + /// + /// + public class ListRendersResponse + { + /// + /// + /// + public int Count { get; set; } + + /// + /// + /// + public IEnumerable Items { get; set; } + } +} \ No newline at end of file diff --git a/OpenTokTest/OpenTok.RenderTests.cs b/OpenTokTest/OpenTok.RenderTests.cs index 32e2d416..912a45d0 100644 --- a/OpenTokTest/OpenTok.RenderTests.cs +++ b/OpenTokTest/OpenTok.RenderTests.cs @@ -14,17 +14,16 @@ namespace OpenTokSDKTest { public class OpenTokRenderTests { + private readonly int apiKey; private readonly Fixture fixture; private readonly Mock mockClient; private readonly OpenTok sut; - private readonly int apiKey; public OpenTokRenderTests() { this.fixture = new Fixture(); this.apiKey = this.fixture.Create(); this.mockClient = new Mock(); - this.sut = new OpenTok(this.apiKey, this.fixture.Create()) { Client = this.mockClient.Object, @@ -42,19 +41,21 @@ public async Task StartRenderAsync_ShouldInitiateRendering() var request = StartRenderRequestDataBuilder.Build().Create(); this.mockClient.Setup(httpClient => httpClient.PostAsync( expectedUrl, - It.Is>(dictionary => dictionary.ContainsKey(contentTypeKey) && dictionary[contentTypeKey] == contentType), + It.Is>(dictionary => + dictionary.ContainsKey(contentTypeKey) && dictionary[contentTypeKey] == contentType), It.Is>(dictionary => dictionary.SequenceEqual(request.ToDataDictionary())))) .ReturnsAsync(serializedResponse); _ = await this.sut.StartRenderAsync(request); this.mockClient.Verify(httpClient => httpClient.PostAsync( It.Is(url => url == expectedUrl), - It.Is>(dictionary => dictionary.ContainsKey(contentTypeKey) && dictionary[contentTypeKey] == contentType), - It.Is>(dictionary => - dictionary.SequenceEqual(request.ToDataDictionary()))), + It.Is>(dictionary => + dictionary.ContainsKey(contentTypeKey) && dictionary[contentTypeKey] == contentType), + It.Is>(dictionary => + dictionary.SequenceEqual(request.ToDataDictionary()))), Times.Once); } - + [Fact] public async Task StartRenderAsync_ShouldReturnResponse() { @@ -66,7 +67,8 @@ public async Task StartRenderAsync_ShouldReturnResponse() var request = StartRenderRequestDataBuilder.Build().Create(); this.mockClient.Setup(httpClient => httpClient.PostAsync( expectedUrl, - It.Is>(dictionary => dictionary.ContainsKey(contentTypeKey) && dictionary[contentTypeKey] == contentType), + It.Is>(dictionary => + dictionary.ContainsKey(contentTypeKey) && dictionary[contentTypeKey] == contentType), It.Is>(dictionary => dictionary.SequenceEqual(request.ToDataDictionary())))) .ReturnsAsync(serializedResponse); @@ -81,8 +83,36 @@ public async Task StopRenderAsync_ShouldDeleteRendering() await this.sut.StopRenderAsync(renderId); this.mockClient.Verify(httpClient => httpClient.DeleteAsync( $"v2/project/{this.apiKey}/render/{renderId}", - It.Is>(dictionary => dictionary.Count == 0)), + It.Is>(dictionary => dictionary.Count == 0)), Times.Once); } + + [Fact] + public async Task ListRendersAsync_ShouldReturnResponse_GivenCountAndOffsetAreProvided() + { + var expectedResponse = this.fixture.Create(); + var serializedResponse = JsonConvert.SerializeObject(expectedResponse); + var request = new ListRendersRequest(5, 6); + var expectedUrl = $"v2/project/{this.apiKey}/render?count=6&offset=5"; + this.mockClient.Setup(httpClient => httpClient.GetAsync(expectedUrl, null)) + .ReturnsAsync(serializedResponse); + var response = await this.sut.ListRendersAsync(request); + Assert.Equal(expectedResponse.Count, response.Count); + Assert.True(expectedResponse.Items.SequenceEqual(response.Items)); + } + + [Fact] + public async Task ListRendersAsync_ShouldReturnResponse_GivenCountIsProvided() + { + var expectedResponse = this.fixture.Create(); + var serializedResponse = JsonConvert.SerializeObject(expectedResponse); + var request = new ListRendersRequest(5); + var expectedUrl = $"v2/project/{this.apiKey}/render?count=5"; + this.mockClient.Setup(httpClient => httpClient.GetAsync(expectedUrl, null)) + .ReturnsAsync(serializedResponse); + var response = await this.sut.ListRendersAsync(request); + Assert.Equal(expectedResponse.Count, response.Count); + Assert.True(expectedResponse.Items.SequenceEqual(response.Items)); + } } } \ No newline at end of file From 75d2f7a712ede30f4cdff4e9204e4f6e9349d718 Mon Sep 17 00:00:00 2001 From: Tr00d Date: Thu, 13 Oct 2022 16:41:28 +0200 Subject: [PATCH 13/23] Implement GetRenderAsync --- OpenTok/OpenTok.Render.cs | 13 ++++- OpenTok/Render/GetRenderResponse.cs | 81 +++++++++++++++++++++++++++ OpenTok/Render/ListRenderItem.cs | 24 ++++---- OpenTok/Render/ListRendersResponse.cs | 6 +- OpenTok/Render/StartRenderResponse.cs | 28 +++++++++ OpenTokTest/OpenTok.RenderTests.cs | 12 ++++ 6 files changed, 148 insertions(+), 16 deletions(-) create mode 100644 OpenTok/Render/GetRenderResponse.cs diff --git a/OpenTok/OpenTok.Render.cs b/OpenTok/OpenTok.Render.cs index 3e07bae2..34468d76 100644 --- a/OpenTok/OpenTok.Render.cs +++ b/OpenTok/OpenTok.Render.cs @@ -44,7 +44,18 @@ public async Task ListRendersAsync(ListRendersRequest reque return JsonConvert.DeserializeObject(response); } - private string BuildUrl(string endpoint) => $"v2/project/{ApiKey}{endpoint}"; + /// + /// TODO + /// + /// TODO + public async Task GetRenderAsync(string renderId) + { + var url = this.BuildUrlWithRouteParameter(RenderEndpoint, renderId); + var response = await this.Client.GetAsync(url); + return JsonConvert.DeserializeObject(response); + } + + private string BuildUrl(string endpoint) => $"v2/project/{this.ApiKey}{endpoint}"; private string BuildUrlWithRouteParameter(string endpoint, string routeParameter) => $"{this.BuildUrl(endpoint)}/{routeParameter}"; diff --git a/OpenTok/Render/GetRenderResponse.cs b/OpenTok/Render/GetRenderResponse.cs new file mode 100644 index 00000000..9a65200c --- /dev/null +++ b/OpenTok/Render/GetRenderResponse.cs @@ -0,0 +1,81 @@ +using System; + +namespace OpenTokSDK.Render +{ + /// + /// TODO + /// + public struct GetRenderResponse + { + /// + /// TODO + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + public GetRenderResponse(string id, string sessionId, string projectId, int createdAt, int updatedAt, Uri url, + ScreenResolution resolution, string status, string reason) + { + this.Id = id; + this.SessionId = sessionId; + this.ProjectId = projectId; + this.CreatedAt = createdAt; + this.UpdatedAt = updatedAt; + this.Url = url; + this.Resolution = resolution; + this.Status = status; + this.Reason = reason; + } + + /// + /// TODO + /// + public string Id { get; set; } + + /// + /// TODO + /// + public string SessionId { get; set; } + + /// + /// TODO + /// + public string ProjectId { get; set; } + + /// + /// TODO + /// + public int CreatedAt { get; set; } + + /// + /// TODO + /// + public int UpdatedAt { get; set; } + + /// + /// TODO + /// + public Uri Url { get; set; } + + /// + /// TODO + /// + public ScreenResolution Resolution { get; set; } + + /// + /// TODO + /// + public string Status { get; set; } + + /// + /// TODO + /// + public string Reason { get; set; } + } +} \ No newline at end of file diff --git a/OpenTok/Render/ListRenderItem.cs b/OpenTok/Render/ListRenderItem.cs index 723568f6..800d2618 100644 --- a/OpenTok/Render/ListRenderItem.cs +++ b/OpenTok/Render/ListRenderItem.cs @@ -3,12 +3,12 @@ namespace OpenTokSDK.Render { /// - /// + /// TODO /// public struct ListRenderItem { /// - /// + /// TODO /// /// /// @@ -36,52 +36,52 @@ public ListRenderItem(string id, string sessionId, string projectId, int created } /// - /// + /// TODO /// public string Id { get; set; } /// - /// + /// TODO /// public string SessionId { get; set; } /// - /// + /// TODO /// public string ProjectId { get; set; } /// - /// + /// TODO /// public int CreatedAt { get; set; } /// - /// + /// TODO /// public int UpdatedAt { get; set; } /// - /// + /// TODO /// public Uri Url { get; set; } /// - /// + /// TODO /// public ScreenResolution Resolution { get; set; } /// - /// + /// TODO /// public string Status { get; set; } /// - /// + /// TODO /// public string StreamId { get; set; } /// - /// + /// TODO /// public string Reason { get; set; } } diff --git a/OpenTok/Render/ListRendersResponse.cs b/OpenTok/Render/ListRendersResponse.cs index fa38e97a..9d713069 100644 --- a/OpenTok/Render/ListRendersResponse.cs +++ b/OpenTok/Render/ListRendersResponse.cs @@ -3,17 +3,17 @@ namespace OpenTokSDK.Render { /// - /// + /// TODO /// public class ListRendersResponse { /// - /// + /// TODO /// public int Count { get; set; } /// - /// + /// TODO /// public IEnumerable Items { get; set; } } diff --git a/OpenTok/Render/StartRenderResponse.cs b/OpenTok/Render/StartRenderResponse.cs index c8615b5b..6af43218 100644 --- a/OpenTok/Render/StartRenderResponse.cs +++ b/OpenTok/Render/StartRenderResponse.cs @@ -8,6 +8,7 @@ namespace OpenTokSDK.Render public struct StartRenderResponse { /// + /// TODO /// /// /// @@ -32,22 +33,49 @@ public StartRenderResponse(string id, string sessionId, string projectId, int cr this.StreamId = streamId; } + /// + /// TODO + /// public string Id { get; } + /// + /// TODO + /// public string SessionId { get; } + /// + /// TODO + /// public string ProjectId { get; } + /// + /// TODO + /// public int CreatedAt { get; } + /// + /// TODO + /// public int UpdatedAt { get; } + /// + /// TODO + /// public Uri Url { get; } + /// + /// TODO + /// public ScreenResolution Resolution { get; } + /// + /// TODO + /// public string Status { get; } + /// + /// TODO + /// public string StreamId { get; } } } \ No newline at end of file diff --git a/OpenTokTest/OpenTok.RenderTests.cs b/OpenTokTest/OpenTok.RenderTests.cs index 912a45d0..e72369d8 100644 --- a/OpenTokTest/OpenTok.RenderTests.cs +++ b/OpenTokTest/OpenTok.RenderTests.cs @@ -114,5 +114,17 @@ public async Task ListRendersAsync_ShouldReturnResponse_GivenCountIsProvided() Assert.Equal(expectedResponse.Count, response.Count); Assert.True(expectedResponse.Items.SequenceEqual(response.Items)); } + + [Fact] + public async Task GetRenderAsync_ShouldReturnResponse() + { + var expectedResponse = this.fixture.Create(); + var serializedResponse = JsonConvert.SerializeObject(expectedResponse); + var renderId = this.fixture.Create(); + var expectedUrl = $"v2/project/{this.apiKey}/render/{renderId}"; + this.mockClient.Setup(httpClient => httpClient.GetAsync(expectedUrl, null)).ReturnsAsync(serializedResponse); + var response = await this.sut.GetRenderAsync(renderId); + Assert.Equal(expectedResponse, response); + } } } \ No newline at end of file From d832187867853c61cd9b74120b0acf97bce37df0 Mon Sep 17 00:00:00 2001 From: Tr00d Date: Thu, 13 Oct 2022 17:30:42 +0200 Subject: [PATCH 14/23] Kill mutants on StartRenderRequest, make all responses as struct for value equality --- OpenTok/Render/ListRendersResponse.cs | 13 +++- OpenTokTest/Render/StartRenderRequestTest.cs | 65 +++++++++++++++++--- 2 files changed, 67 insertions(+), 11 deletions(-) diff --git a/OpenTok/Render/ListRendersResponse.cs b/OpenTok/Render/ListRendersResponse.cs index 9d713069..4b3d57c2 100644 --- a/OpenTok/Render/ListRendersResponse.cs +++ b/OpenTok/Render/ListRendersResponse.cs @@ -5,8 +5,19 @@ namespace OpenTokSDK.Render /// /// TODO /// - public class ListRendersResponse + public struct ListRendersResponse { + /// + /// TODO + /// + /// TODO + /// TODO + public ListRendersResponse(int count, IEnumerable items) + { + this.Count = count; + this.Items = items; + } + /// /// TODO /// diff --git a/OpenTokTest/Render/StartRenderRequestTest.cs b/OpenTokTest/Render/StartRenderRequestTest.cs index 090df5e7..678b627c 100644 --- a/OpenTokTest/Render/StartRenderRequestTest.cs +++ b/OpenTokTest/Render/StartRenderRequestTest.cs @@ -1,5 +1,8 @@ using System; +using System.Collections.Generic; using System.Linq; +using EnumsNET; +using Newtonsoft.Json; using OpenTokSDK.Exception; using OpenTokSDK.Render; using Xunit; @@ -61,7 +64,7 @@ public void StartRenderRequest_ShouldThrowOpenTokException_GivenUrlLengthIsHighe Assert.Equal(2049, uri.AbsoluteUri.Length); Assert.Equal(StartRenderRequest.InvalidUrl, exception.Message); } - + [Fact] public void StartRenderRequest_ShouldReturnInstance_GivenUrlHasMaximumLength() { @@ -87,7 +90,7 @@ public void StartRenderRequest_ShouldHave7200AsDefaultMaxDuration() } [Fact] - public void ConstructorShouldThrowOpenTokExceptionGivenMaxDurationIsHigherThan36000() + public void StartRenderRequest_ShouldThrowOpenTokExceptionGivenMaxDurationIsHigherThan36000() { void Act() => StartRenderRequestDataBuilder.Build().WithMaxDuration(36001).Create(); var exception = Assert.Throws(Act); @@ -114,7 +117,7 @@ public void StartRenderRequest_ShouldThrowOpenTokException_GivenStatusCallbackUr Assert.Equal(2049, uri.AbsoluteUri.Length); Assert.Equal(StartRenderRequest.InvalidStatusCallbackUrl, exception.Message); } - + [Fact] public void StartRenderRequest_ShouldReturnInstance_GivenStatusCallbackUrlHasMaximumLength() { @@ -150,7 +153,7 @@ public void StartRenderRequest_ShouldThrowOpenTokException_GivenStreamNameExceed var exception = Assert.Throws(Act); Assert.Equal(StartRenderRequest.PublisherProperty.OverflowStreamName, exception.Message); } - + [Fact] public void StartRenderRequest_ShouldReturnInstance_GivenStreamNameHasMaximumLength() { @@ -160,13 +163,19 @@ public void StartRenderRequest_ShouldReturnInstance_GivenStreamNameHasMaximumLen } [Theory] - [InlineData("sessionId", "token", "https://www.example.com/", "https://www.example.com/callback", "stream", 1200, ScreenResolution.StandardDefinitionLandscape)] - [InlineData("sessionId", "token", "https://www.example.com/", "https://www.example.com/callback", "stream", 60, ScreenResolution.StandardDefinitionPortrait)] - [InlineData("sessionId", "token", "https://www.example.com/", "https://www.example.com/callback", "stream", 36000, ScreenResolution.HighDefinitionLandscape)] - [InlineData("sessionId", "token", "https://www.example.com/", "https://www.example.com/callback", "stream", 15647, ScreenResolution.HighDefinitionPortrait)] - [InlineData("sessionId", "token", "https://www.example.com/", "https://hel.fr/", "stream", null, ScreenResolution.StandardDefinitionLandscape)] + [InlineData("sessionId", "token", "https://www.example.com/", "https://www.example.com/callback", "stream", + 1200, ScreenResolution.StandardDefinitionLandscape)] + [InlineData("sessionId", "token", "https://www.example.com/", "https://www.example.com/callback", "stream", 60, + ScreenResolution.StandardDefinitionPortrait)] + [InlineData("sessionId", "token", "https://www.example.com/", "https://www.example.com/callback", "stream", + 36000, ScreenResolution.HighDefinitionLandscape)] + [InlineData("sessionId", "token", "https://www.example.com/", "https://www.example.com/callback", "stream", + 15647, ScreenResolution.HighDefinitionPortrait)] + [InlineData("sessionId", "token", "https://www.example.com/", "https://hel.fr/", "stream", null, + ScreenResolution.StandardDefinitionLandscape)] [InlineData("sessionId", "token", "https://hel.fr/", "https://www.example.com/callback", "stream", 36000, null)] - public void StartRenderRequest_ShouldReturnInstance(string sessionId, string token, string url, string callbackUrl, string streamName, int? maxDuration, ScreenResolution? resolution) + public void StartRenderRequest_ShouldReturnInstance(string sessionId, string token, string url, + string callbackUrl, string streamName, int? maxDuration, ScreenResolution? resolution) { var request = StartRenderRequestDataBuilder .Build() @@ -186,5 +195,41 @@ public void StartRenderRequest_ShouldReturnInstance(string sessionId, string tok Assert.Equal(maxDuration ?? 7200, request.MaxDuration); Assert.Equal(resolution ?? ScreenResolution.HighDefinitionLandscape, request.Resolution); } + + [Theory] + [InlineData("sessionId", "token", "https://www.example.com/", "https://www.example.com/callback", "stream", + 1200, ScreenResolution.StandardDefinitionLandscape)] + [InlineData("sessionId", "token", "https://www.example.com/", "https://www.example.com/callback", "stream", 60, + ScreenResolution.StandardDefinitionPortrait)] + [InlineData("sessionId", "token", "https://www.example.com/", "https://www.example.com/callback", "stream", + 36000, ScreenResolution.HighDefinitionLandscape)] + [InlineData("sessionId", "token", "https://www.example.com/", "https://www.example.com/callback", "stream", + 15647, ScreenResolution.HighDefinitionPortrait)] + public void ToDataDictionary_ShouldReturnValuesAsDictionary(string sessionId, string token, string url, + string callbackUrl, string streamName, int maxDuration, ScreenResolution resolution) + { + var expectedSerialized = JsonConvert.SerializeObject(new Dictionary + { + {"sessionId", sessionId}, + {"token", token}, + {"url", new Uri(url)}, + {"statusCallbackUrl", new Uri(callbackUrl)}, + {"maxDuration", maxDuration}, + {"resolution", resolution.AsString(EnumFormat.Description)}, + {"properties", new StartRenderRequest.PublisherProperty(streamName)}, + }); + var result = StartRenderRequestDataBuilder + .Build() + .WithSessionId(sessionId) + .WithToken(token) + .WithUrl(new Uri(url)) + .WithStatusCallbackUrl(new Uri(callbackUrl)) + .WithStreamName(streamName) + .WithMaxDuration(maxDuration) + .WithResolution(resolution) + .Create() + .ToDataDictionary(); + Assert.Equal(expectedSerialized, JsonConvert.SerializeObject(result)); + } } } \ No newline at end of file From db8c169a85c72314b4b5bedb9d7ed3bef1c62c11 Mon Sep 17 00:00:00 2001 From: Tr00d Date: Thu, 10 Nov 2022 08:22:09 +0100 Subject: [PATCH 15/23] Fix request formatting issue - last test round --- OpenTok/OpenTok.Render.cs | 8 +- OpenTok/Render/GetRenderResponse.cs | 81 ---------- OpenTok/Render/ListRendersResponse.cs | 4 +- .../{ListRenderItem.cs => RenderItem.cs} | 10 +- OpenTok/Render/ScreenResolutionConverter.cs | 24 +++ OpenTok/Render/StartRenderRequest.cs | 8 +- OpenTok/Render/StartRenderResponse.cs | 81 ---------- OpenTok/Util/HttpClient.cs | 149 +++++++++--------- OpenTokTest/OpenTok.RenderTests.cs | 37 +++-- OpenTokTest/Render/StartRenderRequestTest.cs | 2 +- 10 files changed, 140 insertions(+), 264 deletions(-) delete mode 100644 OpenTok/Render/GetRenderResponse.cs rename OpenTok/Render/{ListRenderItem.cs => RenderItem.cs} (86%) create mode 100644 OpenTok/Render/ScreenResolutionConverter.cs delete mode 100644 OpenTok/Render/StartRenderResponse.cs diff --git a/OpenTok/OpenTok.Render.cs b/OpenTok/OpenTok.Render.cs index 34468d76..f2453987 100644 --- a/OpenTok/OpenTok.Render.cs +++ b/OpenTok/OpenTok.Render.cs @@ -14,13 +14,13 @@ public partial class OpenTok /// /// TODO /// TODO - public async Task StartRenderAsync(StartRenderRequest request) + public async Task StartRenderAsync(StartRenderRequest request) { var response = await this.Client.PostAsync( this.BuildUrl(RenderEndpoint), GetHeaderDictionary("application/json"), request.ToDataDictionary()); - return JsonConvert.DeserializeObject(response); + return JsonConvert.DeserializeObject(response); } /// @@ -48,11 +48,11 @@ public async Task ListRendersAsync(ListRendersRequest reque /// TODO /// /// TODO - public async Task GetRenderAsync(string renderId) + public async Task GetRenderAsync(string renderId) { var url = this.BuildUrlWithRouteParameter(RenderEndpoint, renderId); var response = await this.Client.GetAsync(url); - return JsonConvert.DeserializeObject(response); + return JsonConvert.DeserializeObject(response); } private string BuildUrl(string endpoint) => $"v2/project/{this.ApiKey}{endpoint}"; diff --git a/OpenTok/Render/GetRenderResponse.cs b/OpenTok/Render/GetRenderResponse.cs deleted file mode 100644 index 9a65200c..00000000 --- a/OpenTok/Render/GetRenderResponse.cs +++ /dev/null @@ -1,81 +0,0 @@ -using System; - -namespace OpenTokSDK.Render -{ - /// - /// TODO - /// - public struct GetRenderResponse - { - /// - /// TODO - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - public GetRenderResponse(string id, string sessionId, string projectId, int createdAt, int updatedAt, Uri url, - ScreenResolution resolution, string status, string reason) - { - this.Id = id; - this.SessionId = sessionId; - this.ProjectId = projectId; - this.CreatedAt = createdAt; - this.UpdatedAt = updatedAt; - this.Url = url; - this.Resolution = resolution; - this.Status = status; - this.Reason = reason; - } - - /// - /// TODO - /// - public string Id { get; set; } - - /// - /// TODO - /// - public string SessionId { get; set; } - - /// - /// TODO - /// - public string ProjectId { get; set; } - - /// - /// TODO - /// - public int CreatedAt { get; set; } - - /// - /// TODO - /// - public int UpdatedAt { get; set; } - - /// - /// TODO - /// - public Uri Url { get; set; } - - /// - /// TODO - /// - public ScreenResolution Resolution { get; set; } - - /// - /// TODO - /// - public string Status { get; set; } - - /// - /// TODO - /// - public string Reason { get; set; } - } -} \ No newline at end of file diff --git a/OpenTok/Render/ListRendersResponse.cs b/OpenTok/Render/ListRendersResponse.cs index 4b3d57c2..d3d671f6 100644 --- a/OpenTok/Render/ListRendersResponse.cs +++ b/OpenTok/Render/ListRendersResponse.cs @@ -12,7 +12,7 @@ public struct ListRendersResponse /// /// TODO /// TODO - public ListRendersResponse(int count, IEnumerable items) + public ListRendersResponse(int count, IEnumerable items) { this.Count = count; this.Items = items; @@ -26,6 +26,6 @@ public ListRendersResponse(int count, IEnumerable items) /// /// TODO /// - public IEnumerable Items { get; set; } + public IEnumerable Items { get; set; } } } \ No newline at end of file diff --git a/OpenTok/Render/ListRenderItem.cs b/OpenTok/Render/RenderItem.cs similarity index 86% rename from OpenTok/Render/ListRenderItem.cs rename to OpenTok/Render/RenderItem.cs index 800d2618..f5c9b54c 100644 --- a/OpenTok/Render/ListRenderItem.cs +++ b/OpenTok/Render/RenderItem.cs @@ -1,11 +1,12 @@ using System; +using Newtonsoft.Json; namespace OpenTokSDK.Render { /// /// TODO /// - public struct ListRenderItem + public struct RenderItem { /// /// TODO @@ -20,7 +21,7 @@ public struct ListRenderItem /// /// /// - public ListRenderItem(string id, string sessionId, string projectId, int createdAt, int updatedAt, Uri url, + public RenderItem(string id, string sessionId, string projectId, int createdAt, int updatedAt, Uri url, ScreenResolution resolution, string status, string streamId, string reason) { this.Id = id; @@ -53,12 +54,12 @@ public ListRenderItem(string id, string sessionId, string projectId, int created /// /// TODO /// - public int CreatedAt { get; set; } + public double CreatedAt { get; set; } /// /// TODO /// - public int UpdatedAt { get; set; } + public double UpdatedAt { get; set; } /// /// TODO @@ -68,6 +69,7 @@ public ListRenderItem(string id, string sessionId, string projectId, int created /// /// TODO /// + [JsonConverter(typeof(ScreenResolutionConverter))] public ScreenResolution Resolution { get; set; } /// diff --git a/OpenTok/Render/ScreenResolutionConverter.cs b/OpenTok/Render/ScreenResolutionConverter.cs new file mode 100644 index 00000000..dc729649 --- /dev/null +++ b/OpenTok/Render/ScreenResolutionConverter.cs @@ -0,0 +1,24 @@ +using System; +using EnumsNET; +using Newtonsoft.Json; + +namespace OpenTokSDK.Render +{ + /// + /// Custom converter for serializing ScreenResolution. + /// + public class ScreenResolutionConverter : JsonConverter + { + /// + public override void WriteJson(JsonWriter writer, ScreenResolution value, JsonSerializer serializer) => + writer.WriteValue(value.AsString(EnumFormat.Description)); + + /// + public override ScreenResolution ReadJson(JsonReader reader, Type objectType, ScreenResolution existingValue, + bool hasExistingValue, + JsonSerializer serializer) => + reader.Value != null + ? Enums.Parse(reader.Value.ToString(), false, EnumFormat.Description) + : existingValue; + } +} \ No newline at end of file diff --git a/OpenTok/Render/StartRenderRequest.cs b/OpenTok/Render/StartRenderRequest.cs index 0996ebf6..49278aeb 100644 --- a/OpenTok/Render/StartRenderRequest.cs +++ b/OpenTok/Render/StartRenderRequest.cs @@ -198,7 +198,7 @@ public Dictionary ToDataDictionary() => {"statusCallbackUrl", this.StatusCallbackUrl}, {"maxDuration", this.MaxDuration}, {"resolution", this.Resolution.AsString(EnumFormat.Description)}, - {"properties", this.Properties}, + {"properties", this.Properties.ToDataDictionary()}, }; /// @@ -246,6 +246,12 @@ private static void ValidateName(string name) throw new OpenTokException(OverflowStreamName); } } + + public Dictionary ToDataDictionary() => + new Dictionary + { + {"name", this.Name}, + }; } } } \ No newline at end of file diff --git a/OpenTok/Render/StartRenderResponse.cs b/OpenTok/Render/StartRenderResponse.cs deleted file mode 100644 index 6af43218..00000000 --- a/OpenTok/Render/StartRenderResponse.cs +++ /dev/null @@ -1,81 +0,0 @@ -using System; - -namespace OpenTokSDK.Render -{ - /// - /// TODO - /// - public struct StartRenderResponse - { - /// - /// TODO - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - public StartRenderResponse(string id, string sessionId, string projectId, int createdAt, int updatedAt, Uri url, - ScreenResolution resolution, string status, string streamId) - { - this.Id = id; - this.SessionId = sessionId; - this.ProjectId = projectId; - this.CreatedAt = createdAt; - this.UpdatedAt = updatedAt; - this.Url = url; - this.Resolution = resolution; - this.Status = status; - this.StreamId = streamId; - } - - /// - /// TODO - /// - public string Id { get; } - - /// - /// TODO - /// - public string SessionId { get; } - - /// - /// TODO - /// - public string ProjectId { get; } - - /// - /// TODO - /// - public int CreatedAt { get; } - - /// - /// TODO - /// - public int UpdatedAt { get; } - - /// - /// TODO - /// - public Uri Url { get; } - - /// - /// TODO - /// - public ScreenResolution Resolution { get; } - - /// - /// TODO - /// - public string Status { get; } - - /// - /// TODO - /// - public string StreamId { get; } - } -} \ No newline at end of file diff --git a/OpenTok/Util/HttpClient.cs b/OpenTok/Util/HttpClient.cs index e59934ef..c53cafc0 100644 --- a/OpenTok/Util/HttpClient.cs +++ b/OpenTok/Util/HttpClient.cs @@ -1,17 +1,18 @@ using System; using System.Collections.Generic; +using System.IO; using System.Linq; using System.Net; -using System.IO; -using System.Xml; +using System.Threading.Tasks; using System.Web; -using Newtonsoft.Json; +using System.Xml; using JWT; using JWT.Algorithms; using JWT.Serializers; +using Newtonsoft.Json; using OpenTokSDK.Constants; using OpenTokSDK.Exception; -using System.Threading.Tasks; + #pragma warning disable CS1591 namespace OpenTokSDK.Util @@ -24,24 +25,14 @@ public class HttpClient private readonly int _apiKey; private readonly string _apiSecret; private readonly string _apiUrl; + private readonly DateTime _unixEpoch = new DateTime( 1970, 1, 1, 0, 0, 0, DateTimeKind.Utc ); - /// - /// Turns on and off debug logging - /// - public bool Debug { get; set; } = false; - - /// - /// Timeout in milliseconds for the HttpWebRequests sent by the client. - /// - public int? RequestTimeout { get; set; } - - - internal string LastRequest { get; private set; } - - internal HttpClient() {} + internal HttpClient() + { + } internal HttpClient(int apiKey, string apiSecret) { @@ -56,11 +47,23 @@ public HttpClient(int apiKey, string apiSecret, string apiUrl = "") _apiUrl = apiUrl; } + /// + /// Turns on and off debug logging + /// + public bool Debug { get; set; } = false; + + /// + /// Timeout in milliseconds for the HttpWebRequests sent by the client. + /// + public int? RequestTimeout { get; set; } + + internal string LastRequest { get; private set; } + public virtual string Get(string url) { return Get(url, new Dictionary()); } - + public virtual string Get(string url, Dictionary headers) { headers.Add("Method", "GET"); @@ -69,8 +72,7 @@ public virtual string Get(string url, Dictionary headers) public virtual Task GetAsync(string url, Dictionary headers = null) { - if(headers == null) headers = new Dictionary(); - + if (headers == null) headers = new Dictionary(); headers.Add("Method", "GET"); return DoRequestAsync(url, headers, null); } @@ -81,7 +83,8 @@ public virtual string Post(string url, Dictionary headers, Dicti return DoRequest(url, headers, data); } - public virtual Task PostAsync(string url, Dictionary headers, Dictionary data) + public virtual Task PostAsync(string url, Dictionary headers, + Dictionary data) { headers.Add("Method", "POST"); return DoRequestAsync(url, headers, data); @@ -93,7 +96,8 @@ public virtual string Put(string url, Dictionary headers, Dictio return DoRequest(url, headers, data); } - public virtual async Task PutAsync(string url, Dictionary headers, Dictionary data) + public virtual async Task PutAsync(string url, Dictionary headers, + Dictionary data) { headers.Add("Method", "PUT"); return await DoRequestAsync(url, headers, data); @@ -105,7 +109,8 @@ public virtual string Patch(string url, Dictionary headers, Dict return DoRequest(url, headers, data); } - public virtual Task PatchAsync(string url, Dictionary headers, Dictionary data) + public virtual Task PatchAsync(string url, Dictionary headers, + Dictionary data) { headers.Add("Method", "PATCH"); return DoRequestAsync(url, headers, data); @@ -124,18 +129,15 @@ public virtual Task DeleteAsync(string url, Dictionary h } public string DoRequest(string url, Dictionary specificHeaders, - Dictionary bodyData) + Dictionary bodyData) { string data = GetRequestPostData(bodyData, specificHeaders); var headers = GetRequestHeaders(specificHeaders); HttpWebRequest request = CreateRequest(url, headers, data); - DebugLog("Request Method: " + request.Method); DebugLog("Request URI: " + request.RequestUri); DebugLogHeaders(request.Headers, "Request"); - HttpWebResponse response; - try { if (!string.IsNullOrEmpty(data)) @@ -143,41 +145,44 @@ public string DoRequest(string url, Dictionary specificHeaders, DebugLog("Request Body: " + data); SendData(request, data); } - using (response = (HttpWebResponse)request.GetResponse()) + + using (response = (HttpWebResponse) request.GetResponse()) { DebugLog("Response Status Code: " + response.StatusCode); DebugLog("Response Status Description: " + response.StatusDescription); DebugLogHeaders(response.Headers, "Response"); - switch (response.StatusCode) { case HttpStatusCode.OK: - using (var stream = new StreamReader(response.GetResponseStream() ?? throw new InvalidOperationException("Response stream null"))) + case HttpStatusCode.Accepted: + using (var stream = new StreamReader(response.GetResponseStream() ?? + throw new InvalidOperationException( + "Response stream null"))) { return stream.ReadToEnd(); } case HttpStatusCode.NoContent: return ""; default: - throw new OpenTokWebException($"Response returned with unexpected status code {response.StatusCode}"); + throw new OpenTokWebException( + $"Response returned with unexpected status code {response.StatusCode}"); } } } catch (WebException e) { DebugLog("WebException Status: " + e.Status + ", Message: " + e.Message); - - response = (HttpWebResponse)e.Response; - + response = (HttpWebResponse) e.Response; if (response != null) { DebugLog("Response Status Code: " + response.StatusCode); DebugLog("Response Status Description: " + response.StatusDescription); DebugLogHeaders(response.Headers, "Response"); - if (Debug) { - using (var stream = new StreamReader(response.GetResponseStream() ?? throw new InvalidOperationException("Response stream null"))) + using (var stream = new StreamReader(response.GetResponseStream() ?? + throw new InvalidOperationException( + "Response stream null"))) { DebugLog("Response Body: " + stream.ReadToEnd()); } @@ -185,29 +190,25 @@ public string DoRequest(string url, Dictionary specificHeaders, } else if (e.Status == WebExceptionStatus.SendFailure) { - throw new OpenTokWebException("Error with request submission (TLS1.1 or other network/protocol issue)", e); + throw new OpenTokWebException( + "Error with request submission (TLS1.1 or other network/protocol issue)", e); } OpenTokUtils.ValidateTlsVersion(e); - throw new OpenTokWebException("Error with request submission", e); } - } public async Task DoRequestAsync(string url, Dictionary specificHeaders, - Dictionary bodyData) + Dictionary bodyData) { string data = GetRequestPostData(bodyData, specificHeaders); var headers = GetRequestHeaders(specificHeaders); HttpWebRequest request = CreateRequest(url, headers, data); - DebugLog("Request Method: " + request.Method); DebugLog("Request URI: " + request.RequestUri); DebugLogHeaders(request.Headers, "Request"); - HttpWebResponse response; - try { if (!string.IsNullOrEmpty(data)) @@ -215,41 +216,44 @@ public async Task DoRequestAsync(string url, Dictionary DebugLog("Request Body: " + data); await SendDataAsync(request, data); } + using (response = await request.GetResponseAsync().ConfigureAwait(false) as HttpWebResponse) { DebugLog("Response Status Code: " + response.StatusCode); DebugLog("Response Status Description: " + response.StatusDescription); DebugLogHeaders(response.Headers, "Response"); - switch (response.StatusCode) { case HttpStatusCode.OK: - using (var stream = new StreamReader(response.GetResponseStream() ?? throw new InvalidOperationException("Response stream null"))) + case HttpStatusCode.Accepted: + using (var stream = new StreamReader(response.GetResponseStream() ?? + throw new InvalidOperationException( + "Response stream null"))) { return await stream.ReadToEndAsync(); } case HttpStatusCode.NoContent: return ""; default: - throw new OpenTokWebException($"Response returned with unexpected status code {response.StatusCode}"); + throw new OpenTokWebException( + $"Response returned with unexpected status code {response.StatusCode}"); } } } catch (WebException e) { DebugLog("WebException Status: " + e.Status + ", Message: " + e.Message); - - response = (HttpWebResponse)e.Response; - + response = (HttpWebResponse) e.Response; if (response != null) { DebugLog("Response Status Code: " + response.StatusCode); DebugLog("Response Status Description: " + response.StatusDescription); DebugLogHeaders(response.Headers, "Response"); - if (Debug) { - using (var stream = new StreamReader(response.GetResponseStream() ?? throw new InvalidOperationException("Response stream null"))) + using (var stream = new StreamReader(response.GetResponseStream() ?? + throw new InvalidOperationException( + "Response stream null"))) { var body = await stream.ReadToEndAsync(); DebugLog($"Response Body: {body}"); @@ -258,7 +262,6 @@ public async Task DoRequestAsync(string url, Dictionary } OpenTokUtils.ValidateTlsVersion(e); - throw new OpenTokWebException("Error with request submission", e); } } @@ -273,7 +276,6 @@ public XmlDocument ReadXmlResponse(string xml) private void SendData(HttpWebRequest request, string data) { LastRequest = data; - using (StreamWriter stream = new StreamWriter(request.GetRequestStream())) { stream.Write(data); @@ -291,20 +293,21 @@ private async Task SendDataAsync(HttpWebRequest request, string data) private HttpWebRequest CreateRequest(string url, Dictionary headers, string data) { Uri uri = new Uri($"{_apiUrl}/{url}"); - HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri); + HttpWebRequest request = (HttpWebRequest) WebRequest.Create(uri); if (RequestTimeout != null) { - request.Timeout = (int)RequestTimeout; + request.Timeout = (int) RequestTimeout; } + request.ContentLength = data.Length; request.UserAgent = OpenTokVersion.GetVersion(); - if (headers.ContainsKey("Content-Type")) { request.ContentType = headers["Content-Type"]; request.Expect = headers["Content-Type"]; headers.Remove("Content-Type"); } + if (headers.ContainsKey("Method")) { request.Method = headers["Method"]; @@ -323,7 +326,7 @@ private Dictionary GetRequestHeaders(Dictionary { var requestHeaders = GetCommonHeaders(); requestHeaders = requestHeaders.Concat(headers).GroupBy(d => d.Key) - .ToDictionary(d => d.Key, d => d.First().Value); + .ToDictionary(d => d.Key, d => d.First().Value); return requestHeaders; } @@ -333,7 +336,8 @@ private string GetRequestPostData(Dictionary data, Dictionary data, Dictionary parameters) { string data = string.Empty; - foreach (KeyValuePair pair in parameters) { data += pair.Key + "=" + HttpUtility.UrlEncode(pair.Value.ToString()) + "&"; } + return data.Substring(0, data.Length - 1); } @@ -362,8 +368,7 @@ private int CurrentTime() { IDateTimeProvider provider = new UtcDateTimeProvider(); var now = provider.GetNow(); - - int secondsSinceEpoch = (int)Math.Round((now - _unixEpoch).TotalSeconds); + int secondsSinceEpoch = (int) Math.Round((now - _unixEpoch).TotalSeconds); return secondsSinceEpoch; } @@ -371,20 +376,17 @@ private string GenerateJwt(int key, string secret, int expiryPeriod = 300) { int now = CurrentTime(); int expiry = now + expiryPeriod; - var payload = new Dictionary { - { "iss", Convert.ToString(key) }, - { "ist", "project" }, - { "iat", now }, - { "exp", expiry } + {"iss", Convert.ToString(key)}, + {"ist", "project"}, + {"iat", now}, + {"exp", expiry} }; - IJwtAlgorithm algorithm = new HMACSHA256Algorithm(); IJsonSerializer serializer = new JsonNetSerializer(); IBase64UrlEncoder urlEncoder = new JwtBase64UrlEncoder(); IJwtEncoder encoder = new JwtEncoder(algorithm, serializer, urlEncoder); - var token = encoder.Encode(payload, secret); return token; } @@ -392,8 +394,9 @@ private string GenerateJwt(int key, string secret, int expiryPeriod = 300) private Dictionary GetCommonHeaders() { return new Dictionary - { { "X-OPENTOK-AUTH", GenerateJwt(_apiKey, _apiSecret) }, - { "X-TB-VERSION", "1" }, + { + {"X-OPENTOK-AUTH", GenerateJwt(_apiKey, _apiSecret)}, + {"X-TB-VERSION", "1"}, }; } @@ -421,4 +424,4 @@ private void DebugLogHeaders(WebHeaderCollection headers, string label) } } } -} +} \ No newline at end of file diff --git a/OpenTokTest/OpenTok.RenderTests.cs b/OpenTokTest/OpenTok.RenderTests.cs index e72369d8..5e0dc81e 100644 --- a/OpenTokTest/OpenTok.RenderTests.cs +++ b/OpenTokTest/OpenTok.RenderTests.cs @@ -36,41 +36,43 @@ public async Task StartRenderAsync_ShouldInitiateRendering() const string contentTypeKey = "Content-Type"; const string contentType = "application/json"; var expectedUrl = $"v2/project/{this.apiKey}/render"; - var expectedResponse = this.fixture.Create(); + var expectedResponse = this.fixture.Create(); var serializedResponse = JsonConvert.SerializeObject(expectedResponse); var request = StartRenderRequestDataBuilder.Build().Create(); this.mockClient.Setup(httpClient => httpClient.PostAsync( expectedUrl, - It.Is>(dictionary => - dictionary.ContainsKey(contentTypeKey) && dictionary[contentTypeKey] == contentType), - It.Is>(dictionary => - dictionary.SequenceEqual(request.ToDataDictionary())))) + MatchesContentTypeDictionary(contentTypeKey, contentType), + Matches(request.ToDataDictionary()))) .ReturnsAsync(serializedResponse); _ = await this.sut.StartRenderAsync(request); this.mockClient.Verify(httpClient => httpClient.PostAsync( It.Is(url => url == expectedUrl), - It.Is>(dictionary => - dictionary.ContainsKey(contentTypeKey) && dictionary[contentTypeKey] == contentType), - It.Is>(dictionary => - dictionary.SequenceEqual(request.ToDataDictionary()))), + MatchesContentTypeDictionary(contentTypeKey, contentType), + Matches(request.ToDataDictionary())), Times.Once); } + private static Dictionary MatchesContentTypeDictionary(string contentTypeKey, + string contentType) => + It.Is>(dictionary => + dictionary.ContainsKey(contentTypeKey) && dictionary[contentTypeKey] == contentType); + + private static T Matches(T input) where T : class => + It.Is(element => JsonConvert.SerializeObject(element) == JsonConvert.SerializeObject(input)); + [Fact] public async Task StartRenderAsync_ShouldReturnResponse() { const string contentTypeKey = "Content-Type"; const string contentType = "application/json"; var expectedUrl = $"v2/project/{this.apiKey}/render"; - var expectedResponse = this.fixture.Create(); + var expectedResponse = this.fixture.Create(); var serializedResponse = JsonConvert.SerializeObject(expectedResponse); var request = StartRenderRequestDataBuilder.Build().Create(); this.mockClient.Setup(httpClient => httpClient.PostAsync( expectedUrl, - It.Is>(dictionary => - dictionary.ContainsKey(contentTypeKey) && dictionary[contentTypeKey] == contentType), - It.Is>(dictionary => - dictionary.SequenceEqual(request.ToDataDictionary())))) + MatchesContentTypeDictionary(contentTypeKey, contentType), + Matches(request.ToDataDictionary()))) .ReturnsAsync(serializedResponse); var response = await this.sut.StartRenderAsync(request); Assert.Equal(expectedResponse, response); @@ -114,15 +116,16 @@ public async Task ListRendersAsync_ShouldReturnResponse_GivenCountIsProvided() Assert.Equal(expectedResponse.Count, response.Count); Assert.True(expectedResponse.Items.SequenceEqual(response.Items)); } - + [Fact] public async Task GetRenderAsync_ShouldReturnResponse() { - var expectedResponse = this.fixture.Create(); + var expectedResponse = this.fixture.Create(); var serializedResponse = JsonConvert.SerializeObject(expectedResponse); var renderId = this.fixture.Create(); var expectedUrl = $"v2/project/{this.apiKey}/render/{renderId}"; - this.mockClient.Setup(httpClient => httpClient.GetAsync(expectedUrl, null)).ReturnsAsync(serializedResponse); + this.mockClient.Setup(httpClient => httpClient.GetAsync(expectedUrl, null)) + .ReturnsAsync(serializedResponse); var response = await this.sut.GetRenderAsync(renderId); Assert.Equal(expectedResponse, response); } diff --git a/OpenTokTest/Render/StartRenderRequestTest.cs b/OpenTokTest/Render/StartRenderRequestTest.cs index 678b627c..927be606 100644 --- a/OpenTokTest/Render/StartRenderRequestTest.cs +++ b/OpenTokTest/Render/StartRenderRequestTest.cs @@ -216,7 +216,7 @@ public void ToDataDictionary_ShouldReturnValuesAsDictionary(string sessionId, st {"statusCallbackUrl", new Uri(callbackUrl)}, {"maxDuration", maxDuration}, {"resolution", resolution.AsString(EnumFormat.Description)}, - {"properties", new StartRenderRequest.PublisherProperty(streamName)}, + {"properties", new StartRenderRequest.PublisherProperty(streamName).ToDataDictionary()}, }); var result = StartRenderRequestDataBuilder .Build() From 6a6992cbf46e0379e7a33bc717c5141bb754dc53 Mon Sep 17 00:00:00 2001 From: Tr00d Date: Thu, 10 Nov 2022 08:39:38 +0100 Subject: [PATCH 16/23] Add missing Xml comments --- OpenTok/Render/ListRendersRequest.cs | 4 +-- OpenTok/Render/ListRendersResponse.cs | 10 +++--- OpenTok/Render/RenderItem.cs | 44 +++++++++++++-------------- 3 files changed, 29 insertions(+), 29 deletions(-) diff --git a/OpenTok/Render/ListRendersRequest.cs b/OpenTok/Render/ListRendersRequest.cs index 3281c723..8818c4db 100644 --- a/OpenTok/Render/ListRendersRequest.cs +++ b/OpenTok/Render/ListRendersRequest.cs @@ -91,9 +91,9 @@ private static void ValidateOffset(int offset) } /// - /// TODO + /// Converts the request to query parameters. /// - /// TODO + /// The query parameters equivalent. public string ToQueryParameters() { var parameters = $"count={this.Count}"; diff --git a/OpenTok/Render/ListRendersResponse.cs b/OpenTok/Render/ListRendersResponse.cs index d3d671f6..2401379e 100644 --- a/OpenTok/Render/ListRendersResponse.cs +++ b/OpenTok/Render/ListRendersResponse.cs @@ -3,14 +3,14 @@ namespace OpenTokSDK.Render { /// - /// TODO + /// Represents a response from a ListRenders request. /// public struct ListRendersResponse { /// - /// TODO + /// Constructor. /// - /// TODO + /// Count /// TODO public ListRendersResponse(int count, IEnumerable items) { @@ -19,12 +19,12 @@ public ListRendersResponse(int count, IEnumerable items) } /// - /// TODO + /// Number of rendering items. /// public int Count { get; set; } /// - /// TODO + /// Rendering items contained in the response. /// public IEnumerable Items { get; set; } } diff --git a/OpenTok/Render/RenderItem.cs b/OpenTok/Render/RenderItem.cs index f5c9b54c..59e6a343 100644 --- a/OpenTok/Render/RenderItem.cs +++ b/OpenTok/Render/RenderItem.cs @@ -4,23 +4,23 @@ namespace OpenTokSDK.Render { /// - /// TODO + /// Represents a rendering. /// public struct RenderItem { /// - /// TODO + /// Constructor. /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// + /// The Id of the rendering. + /// The Id of the session. + /// The Id of the project. + /// The creation date. + /// The last update date. + /// The Url. + /// The screen resolution. + /// The status. + /// The Id of the stream. + /// The reason. public RenderItem(string id, string sessionId, string projectId, int createdAt, int updatedAt, Uri url, ScreenResolution resolution, string status, string streamId, string reason) { @@ -37,53 +37,53 @@ public RenderItem(string id, string sessionId, string projectId, int createdAt, } /// - /// TODO + /// The Id of the rendering. /// public string Id { get; set; } /// - /// TODO + /// The Id of the session. /// public string SessionId { get; set; } /// - /// TODO + /// The Id of the project. /// public string ProjectId { get; set; } /// - /// TODO + /// The creation date. /// public double CreatedAt { get; set; } /// - /// TODO + /// The last update date. /// public double UpdatedAt { get; set; } /// - /// TODO + /// The Url. /// public Uri Url { get; set; } /// - /// TODO + /// The screen resolution. /// [JsonConverter(typeof(ScreenResolutionConverter))] public ScreenResolution Resolution { get; set; } /// - /// TODO + /// The status. /// public string Status { get; set; } /// - /// TODO + /// The Id of the stream. /// public string StreamId { get; set; } /// - /// TODO + /// The reason. /// public string Reason { get; set; } } From c07a0e691d9eed4953d4b90b30b1db2e62c13e13 Mon Sep 17 00:00:00 2001 From: Tr00d Date: Mon, 21 Nov 2022 02:49:03 -0500 Subject: [PATCH 17/23] Create BlazorTestApp --- BlazorTestApp/App.razor | 12 + BlazorTestApp/BlazorTestApp.csproj | 40 ++ BlazorTestApp/Data/OpenTokOptions.cs | 19 + BlazorTestApp/Data/OpenTokService.cs | 17 + BlazorTestApp/Data/WeatherForecast.cs | 12 + BlazorTestApp/Data/WeatherForecastService.cs | 19 + .../Pages/ArchivesManagement/Archives.razor | 107 ++++ .../Pages/ArchivesManagement/Delete.razor | 25 + .../Pages/ArchivesManagement/Download.razor | 26 + BlazorTestApp/Pages/Error.cshtml | 42 ++ BlazorTestApp/Pages/Error.cshtml.cs | 26 + BlazorTestApp/Pages/HostManagement/Host.razor | 137 +++++ .../Pages/HostManagement/HostInput.cs | 8 + BlazorTestApp/Pages/Index.razor | 9 + .../ParticipantManagement/Participant.razor | 89 +++ BlazorTestApp/Pages/_Host.cshtml | 9 + BlazorTestApp/Pages/_Layout.cshtml | 36 ++ BlazorTestApp/Program.cs | 15 + BlazorTestApp/Properties/launchSettings.json | 28 + BlazorTestApp/Shared/MainLayout.razor | 15 + BlazorTestApp/Shared/MainLayout.razor.css | 70 +++ BlazorTestApp/Shared/NavMenu.razor | 46 ++ BlazorTestApp/Shared/NavMenu.razor.css | 62 ++ BlazorTestApp/_Imports.razor | 10 + BlazorTestApp/appsettings.Development.json | 9 + BlazorTestApp/appsettings.json | 14 + .../wwwroot/content/img/archiving-off.png | Bin 0 -> 21106 bytes .../wwwroot/content/img/archiving-on-idle.png | Bin 0 -> 21861 bytes .../content/img/archiving-on-message.png | Bin 0 -> 21044 bytes BlazorTestApp/wwwroot/content/js/host.js | 34 ++ .../wwwroot/css/bootstrap/bootstrap.min.css | 7 + .../css/bootstrap/bootstrap.min.css.map | 1 + .../wwwroot/css/open-iconic/FONT-LICENSE | 86 +++ .../wwwroot/css/open-iconic/ICON-LICENSE | 21 + .../wwwroot/css/open-iconic/README.md | 111 ++++ .../font/css/open-iconic-bootstrap.min.css | 1 + .../open-iconic/font/fonts/open-iconic.eot | Bin 0 -> 28196 bytes .../open-iconic/font/fonts/open-iconic.otf | Bin 0 -> 20996 bytes .../open-iconic/font/fonts/open-iconic.svg | 544 ++++++++++++++++++ .../open-iconic/font/fonts/open-iconic.ttf | Bin 0 -> 28028 bytes .../open-iconic/font/fonts/open-iconic.woff | Bin 0 -> 14984 bytes BlazorTestApp/wwwroot/css/sample.css | 22 + BlazorTestApp/wwwroot/css/site.css | 64 +++ BlazorTestApp/wwwroot/favicon.ico | Bin 0 -> 5430 bytes OpenTok.sln | 6 + 45 files changed, 1799 insertions(+) create mode 100644 BlazorTestApp/App.razor create mode 100644 BlazorTestApp/BlazorTestApp.csproj create mode 100644 BlazorTestApp/Data/OpenTokOptions.cs create mode 100644 BlazorTestApp/Data/OpenTokService.cs create mode 100644 BlazorTestApp/Data/WeatherForecast.cs create mode 100644 BlazorTestApp/Data/WeatherForecastService.cs create mode 100644 BlazorTestApp/Pages/ArchivesManagement/Archives.razor create mode 100644 BlazorTestApp/Pages/ArchivesManagement/Delete.razor create mode 100644 BlazorTestApp/Pages/ArchivesManagement/Download.razor create mode 100644 BlazorTestApp/Pages/Error.cshtml create mode 100644 BlazorTestApp/Pages/Error.cshtml.cs create mode 100644 BlazorTestApp/Pages/HostManagement/Host.razor create mode 100644 BlazorTestApp/Pages/HostManagement/HostInput.cs create mode 100644 BlazorTestApp/Pages/Index.razor create mode 100644 BlazorTestApp/Pages/ParticipantManagement/Participant.razor create mode 100644 BlazorTestApp/Pages/_Host.cshtml create mode 100644 BlazorTestApp/Pages/_Layout.cshtml create mode 100644 BlazorTestApp/Program.cs create mode 100644 BlazorTestApp/Properties/launchSettings.json create mode 100644 BlazorTestApp/Shared/MainLayout.razor create mode 100644 BlazorTestApp/Shared/MainLayout.razor.css create mode 100644 BlazorTestApp/Shared/NavMenu.razor create mode 100644 BlazorTestApp/Shared/NavMenu.razor.css create mode 100644 BlazorTestApp/_Imports.razor create mode 100644 BlazorTestApp/appsettings.Development.json create mode 100644 BlazorTestApp/appsettings.json create mode 100644 BlazorTestApp/wwwroot/content/img/archiving-off.png create mode 100644 BlazorTestApp/wwwroot/content/img/archiving-on-idle.png create mode 100644 BlazorTestApp/wwwroot/content/img/archiving-on-message.png create mode 100644 BlazorTestApp/wwwroot/content/js/host.js create mode 100644 BlazorTestApp/wwwroot/css/bootstrap/bootstrap.min.css create mode 100644 BlazorTestApp/wwwroot/css/bootstrap/bootstrap.min.css.map create mode 100644 BlazorTestApp/wwwroot/css/open-iconic/FONT-LICENSE create mode 100644 BlazorTestApp/wwwroot/css/open-iconic/ICON-LICENSE create mode 100644 BlazorTestApp/wwwroot/css/open-iconic/README.md create mode 100644 BlazorTestApp/wwwroot/css/open-iconic/font/css/open-iconic-bootstrap.min.css create mode 100644 BlazorTestApp/wwwroot/css/open-iconic/font/fonts/open-iconic.eot create mode 100644 BlazorTestApp/wwwroot/css/open-iconic/font/fonts/open-iconic.otf create mode 100644 BlazorTestApp/wwwroot/css/open-iconic/font/fonts/open-iconic.svg create mode 100644 BlazorTestApp/wwwroot/css/open-iconic/font/fonts/open-iconic.ttf create mode 100644 BlazorTestApp/wwwroot/css/open-iconic/font/fonts/open-iconic.woff create mode 100644 BlazorTestApp/wwwroot/css/sample.css create mode 100644 BlazorTestApp/wwwroot/css/site.css create mode 100644 BlazorTestApp/wwwroot/favicon.ico diff --git a/BlazorTestApp/App.razor b/BlazorTestApp/App.razor new file mode 100644 index 00000000..c7730d1c --- /dev/null +++ b/BlazorTestApp/App.razor @@ -0,0 +1,12 @@ + + + + + + + Not found + +

Sorry, there's nothing at this address.

+
+
+
\ No newline at end of file diff --git a/BlazorTestApp/BlazorTestApp.csproj b/BlazorTestApp/BlazorTestApp.csproj new file mode 100644 index 00000000..0d827ac8 --- /dev/null +++ b/BlazorTestApp/BlazorTestApp.csproj @@ -0,0 +1,40 @@ + + + + net6.0 + enable + enable + + + + + + + + + Always + + + Always + + + Always + + + Always + + + + + <_ContentIncludedByDefault Remove="Pages\Error.cshtml"/> + <_ContentIncludedByDefault Remove="Pages\_Host.cshtml"/> + <_ContentIncludedByDefault Remove="Pages\_Layout.cshtml"/> + <_ContentIncludedByDefault Remove="Pages\Archives.razor"/> + <_ContentIncludedByDefault Remove="Pages\Counter.razor"/> + <_ContentIncludedByDefault Remove="Pages\FetchData.razor"/> + <_ContentIncludedByDefault Remove="Pages\Host.razor"/> + <_ContentIncludedByDefault Remove="Pages\Index.razor"/> + <_ContentIncludedByDefault Remove="Pages\Participant.razor"/> + + + diff --git a/BlazorTestApp/Data/OpenTokOptions.cs b/BlazorTestApp/Data/OpenTokOptions.cs new file mode 100644 index 00000000..b547015b --- /dev/null +++ b/BlazorTestApp/Data/OpenTokOptions.cs @@ -0,0 +1,19 @@ +namespace BlazorTestApp.Data; + +public class OpenTokOptions +{ + public OpenTokOptions(string apiKey, string apiSecret, string sessionId) + { + this.ApiKey = apiKey; + this.ApiSecret = apiSecret; + this.SessionId = sessionId; + } + + public OpenTokOptions() + { + } + + public string ApiKey { get; set; } + public string ApiSecret { get; set; } + public string SessionId { get; set; } +} \ No newline at end of file diff --git a/BlazorTestApp/Data/OpenTokService.cs b/BlazorTestApp/Data/OpenTokService.cs new file mode 100644 index 00000000..a559147a --- /dev/null +++ b/BlazorTestApp/Data/OpenTokService.cs @@ -0,0 +1,17 @@ +using System.Net; +using OpenTokSDK; + +namespace BlazorTestApp.Data; + +public class OpenTokService +{ + public OpenTokService(OpenTokOptions options) + { + ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12; + this.OpenTok = new OpenTok(Convert.ToInt32(options.ApiKey), options.ApiSecret); + } + + public OpenTok OpenTok { get; } + + public Session CreateSession() => this.OpenTok.CreateSession(mediaMode: MediaMode.ROUTED); +} \ No newline at end of file diff --git a/BlazorTestApp/Data/WeatherForecast.cs b/BlazorTestApp/Data/WeatherForecast.cs new file mode 100644 index 00000000..f42c3b2b --- /dev/null +++ b/BlazorTestApp/Data/WeatherForecast.cs @@ -0,0 +1,12 @@ +namespace BlazorTestApp.Data; + +public class WeatherForecast +{ + public DateTime Date { get; set; } + + public int TemperatureC { get; set; } + + public int TemperatureF => 32 + (int) (TemperatureC / 0.5556); + + public string? Summary { get; set; } +} \ No newline at end of file diff --git a/BlazorTestApp/Data/WeatherForecastService.cs b/BlazorTestApp/Data/WeatherForecastService.cs new file mode 100644 index 00000000..636653c2 --- /dev/null +++ b/BlazorTestApp/Data/WeatherForecastService.cs @@ -0,0 +1,19 @@ +namespace BlazorTestApp.Data; + +public class WeatherForecastService +{ + private static readonly string[] Summaries = + { + "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching", + }; + + public Task GetForecastAsync(DateTime startDate) + { + return Task.FromResult(Enumerable.Range(1, 5).Select(index => new WeatherForecast + { + Date = startDate.AddDays(index), + TemperatureC = Random.Shared.Next(-20, 55), + Summary = Summaries[Random.Shared.Next(Summaries.Length)], + }).ToArray()); + } +} \ No newline at end of file diff --git a/BlazorTestApp/Pages/ArchivesManagement/Archives.razor b/BlazorTestApp/Pages/ArchivesManagement/Archives.razor new file mode 100644 index 00000000..139df967 --- /dev/null +++ b/BlazorTestApp/Pages/ArchivesManagement/Archives.razor @@ -0,0 +1,107 @@ +@page "/archives" +@using BlazorTestApp.Data +@using OpenTokSDK +@inject OpenTokService Service +Archives + +
+ +
+ +
+
+

Past Archives

+
+
+ @if (archiveCount > 0) + { + + + + + + + + + + + @foreach (var archive in archives) + { + + + + + + + + } + + +
NameCreatedDurationStatus
+ @archive.Name + @* @if (archive.Status == ArchiveStatus.AVAILABLE && archive.Url.Length > 0) *@ + @* { *@ + @* @archive.Name *@ + @* *@ + @* } *@ + @* else *@ + @* { *@ + @* Untitled *@ + @* } *@ + + @{ + var epoch = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc); + @epoch.AddMilliseconds(archive.CreatedAt).ToString() + } + @archive.Duration seconds@archive.Status + @if (archive.Status == ArchiveStatus.AVAILABLE) + { + + + + //Delete + } + else + { + @:   + } +
+ } + else + { +

+ Loading archives... +

+ } +
+
+
+
+ +@code { + + private IEnumerable archives = new List(); + private int archiveCount; + private string showPrevious = string.Empty; + private string showNext = string.Empty; + + protected override async Task OnInitializedAsync() + { + await base.OnInitializedAsync(); + var openTokArchives = await Service.OpenTok.ListArchivesAsync(count: 1000); + if (openTokArchives != null) + { + archiveCount = openTokArchives.TotalCount; + archives = openTokArchives.ToList(); + } + } + + private async Task DownloadArchiveAsync(Guid archiveId) + { + } + + private async Task DeleteArchiveAsync(Guid archiveId) + { + } + +} \ No newline at end of file diff --git a/BlazorTestApp/Pages/ArchivesManagement/Delete.razor b/BlazorTestApp/Pages/ArchivesManagement/Delete.razor new file mode 100644 index 00000000..51ac04c0 --- /dev/null +++ b/BlazorTestApp/Pages/ArchivesManagement/Delete.razor @@ -0,0 +1,25 @@ +@page "/archives/delete" +@page "/archives/delete/{id:guid}" +@using BlazorTestApp.Data +@inject OpenTokService Service +@inject NavigationManager NavigationManager +@inject IJSRuntime JavascriptRuntime +Delete +

Deleting your archive...

+ +@code { + + [Parameter] + public Guid Id { get; set; } + + protected override async Task OnInitializedAsync() + { + await base.OnInitializedAsync(); + if (Id != Guid.Empty) + { + await Service.OpenTok.DeleteArchiveAsync(Id.ToString()); + } + NavigationManager.NavigateTo("/archives"); + } + +} \ No newline at end of file diff --git a/BlazorTestApp/Pages/ArchivesManagement/Download.razor b/BlazorTestApp/Pages/ArchivesManagement/Download.razor new file mode 100644 index 00000000..2d81a98b --- /dev/null +++ b/BlazorTestApp/Pages/ArchivesManagement/Download.razor @@ -0,0 +1,26 @@ +@page "/archives/download" +@page "/archives/download/{id:guid}" +@using BlazorTestApp.Data +@inject OpenTokService Service +@inject NavigationManager NavigationManager +@inject IJSRuntime JavascriptRuntime +Download +

Redirecting to your archive...

+ +@code { + + [Parameter] + public Guid Id { get; set; } + + protected override async Task OnInitializedAsync() + { + await base.OnInitializedAsync(); + if (Id != Guid.Empty) + { + var archive = await Service.OpenTok.GetArchiveAsync(Id.ToString()); + await JavascriptRuntime.InvokeVoidAsync("open", archive.Url, "_blank"); + } + NavigationManager.NavigateTo("/archives"); + } + +} \ No newline at end of file diff --git a/BlazorTestApp/Pages/Error.cshtml b/BlazorTestApp/Pages/Error.cshtml new file mode 100644 index 00000000..8c73b12f --- /dev/null +++ b/BlazorTestApp/Pages/Error.cshtml @@ -0,0 +1,42 @@ +@page +@model BlazorTestApp.Pages.ErrorModel + + + + + + + + Error + + + + + +
+
+

Error.

+

An error occurred while processing your request.

+ + @if (Model.ShowRequestId) + { +

+ Request ID: @Model.RequestId +

+ } + +

Development Mode

+

+ Swapping to the Development environment displays detailed information about the error that occurred. +

+

+ The Development environment shouldn't be enabled for deployed applications. + It can result in displaying sensitive information from exceptions to end users. + For local debugging, enable the Development environment by setting the ASPNETCORE_ENVIRONMENT environment variable to Development + and restarting the app. +

+
+
+ + + \ No newline at end of file diff --git a/BlazorTestApp/Pages/Error.cshtml.cs b/BlazorTestApp/Pages/Error.cshtml.cs new file mode 100644 index 00000000..1dcb8412 --- /dev/null +++ b/BlazorTestApp/Pages/Error.cshtml.cs @@ -0,0 +1,26 @@ +using System.Diagnostics; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Mvc.RazorPages; + +namespace BlazorTestApp.Pages; + +[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)] +[IgnoreAntiforgeryToken] +public class ErrorModel : PageModel +{ + private readonly ILogger _logger; + + public ErrorModel(ILogger logger) + { + _logger = logger; + } + + public string? RequestId { get; set; } + + public bool ShowRequestId => !string.IsNullOrEmpty(RequestId); + + public void OnGet() + { + RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier; + } +} \ No newline at end of file diff --git a/BlazorTestApp/Pages/HostManagement/Host.razor b/BlazorTestApp/Pages/HostManagement/Host.razor new file mode 100644 index 00000000..ef6029f5 --- /dev/null +++ b/BlazorTestApp/Pages/HostManagement/Host.razor @@ -0,0 +1,137 @@ +@page "/host" +@using BlazorTestApp.Data +@using OpenTokSDK +@inject IJSRuntime JS +@inject OpenTokService service +Host + +
+ +
+ +
+
+

Host

+
+
+ Publishers +
+
+
+ Subscribers +
+
+
+ +
+
+ +
+
+

Instructions

+
+
+

+ Click Start archiving to begin archiving this session. + All publishers in the session will be included, and all publishers that + join the session will be included as well. +

+

+ Click Stop archiving to end archiving this session. + You can then go to past archives to + view your archive (once its status changes to available). +

+ + + + + + + + + + + + + + + + + + + + + +
WhenYou will see
Archiving is started + +
Archiving remains on + +
Archiving is stopped + +
+
+
+
+ +@code { + + private string sessionId = string.Empty; + private Guid archiveId = Guid.Empty; + private HostInput UserInput { get; } = new(); + + protected override async Task OnAfterRenderAsync(bool firstRender) + { + await base.OnAfterRenderAsync(firstRender); + if (!firstRender) return; + var session = service.CreateSession(); + sessionId = session.Id; + var apiKey = service.OpenTok.ApiKey.ToString(); + var token = session.GenerateToken(); + await JS.InvokeVoidAsync("initializeSession", apiKey, sessionId, token); + } + + private async Task StartArchivingAsync() + { + var archive = await service.OpenTok.StartArchiveAsync( + sessionId, + ".NET Archiving Sample App", + UserInput.HasVideo, + UserInput.HasAudio, + GetOutputMode(UserInput.OutputMode) + ); + archiveId = archive.Id; + } + + private OutputMode GetOutputMode(string value) => value == "composed" ? OutputMode.COMPOSED : OutputMode.INDIVIDUAL; + + private async Task StopArchivingAsync() + { + if (archiveId != Guid.Empty) + { + await service.OpenTok.StopArchiveAsync(archiveId.ToString()); + } + } + +} \ No newline at end of file diff --git a/BlazorTestApp/Pages/HostManagement/HostInput.cs b/BlazorTestApp/Pages/HostManagement/HostInput.cs new file mode 100644 index 00000000..594d19a1 --- /dev/null +++ b/BlazorTestApp/Pages/HostManagement/HostInput.cs @@ -0,0 +1,8 @@ +namespace BlazorTestApp.Pages.HostManagement; + +public class HostInput +{ + public bool HasAudio { get; set; } = true; + public bool HasVideo { get; set; } = true; + public string OutputMode { get; set; } = "composed"; +} \ No newline at end of file diff --git a/BlazorTestApp/Pages/Index.razor b/BlazorTestApp/Pages/Index.razor new file mode 100644 index 00000000..66ce12c8 --- /dev/null +++ b/BlazorTestApp/Pages/Index.razor @@ -0,0 +1,9 @@ +@page "/" + +Index + +

Hello, world!

+ +Welcome to your new app. + + \ No newline at end of file diff --git a/BlazorTestApp/Pages/ParticipantManagement/Participant.razor b/BlazorTestApp/Pages/ParticipantManagement/Participant.razor new file mode 100644 index 00000000..c51248e5 --- /dev/null +++ b/BlazorTestApp/Pages/ParticipantManagement/Participant.razor @@ -0,0 +1,89 @@ +@page "/participant" +@using BlazorTestApp.Data +@inject IJSRuntime JS +@inject OpenTokService service +Participant + +
+ +
+ +
+
+

Participant

+
+
+ Publishers +
+
+
+ Subscribers +
+
+
+
+
+ +
+
+

Instructions

+
+
+

+ Click Start archiving to begin archiving this session. + All publishers in the session will be included, and all publishers that + join the session will be included as well. +

+

+ Click Stop archiving to end archiving this session. + You can then go to past archives to + view your archive (once its status changes to available). +

+ + + + + + + + + + + + + + + + + + + + + +
WhenYou will see
Archiving is started + +
Archiving remains on + +
Archiving is stopped + +
+
+
+
+ +@code { + + private string sessionId = string.Empty; + + protected override async Task OnAfterRenderAsync(bool firstRender) + { + await base.OnAfterRenderAsync(firstRender); + if (!firstRender) return; + var session = service.CreateSession(); + sessionId = session.Id; + var apiKey = service.OpenTok.ApiKey.ToString(); + var token = session.GenerateToken(); + await JS.InvokeVoidAsync("initializeSession", apiKey, sessionId, token); + } + +} \ No newline at end of file diff --git a/BlazorTestApp/Pages/_Host.cshtml b/BlazorTestApp/Pages/_Host.cshtml new file mode 100644 index 00000000..bc2ab5f3 --- /dev/null +++ b/BlazorTestApp/Pages/_Host.cshtml @@ -0,0 +1,9 @@ +@page "/" +@using Microsoft.AspNetCore.Mvc.TagHelpers +@namespace BlazorTestApp.Pages +@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers +@{ + Layout = "_Layout"; +} + + \ No newline at end of file diff --git a/BlazorTestApp/Pages/_Layout.cshtml b/BlazorTestApp/Pages/_Layout.cshtml new file mode 100644 index 00000000..85a352ab --- /dev/null +++ b/BlazorTestApp/Pages/_Layout.cshtml @@ -0,0 +1,36 @@ +@using Microsoft.AspNetCore.Components.Web +@using Microsoft.AspNetCore.Mvc.TagHelpers +@namespace BlazorTestApp.Pages +@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers + + + + + + + + + + + + + + + + +@RenderBody() + +
+ + An error has occurred. This application may no longer respond until reloaded. + + + An unhandled exception has occurred. See browser dev tools for details. + + Reload + 🗙 +
+ + + + \ No newline at end of file diff --git a/BlazorTestApp/Program.cs b/BlazorTestApp/Program.cs new file mode 100644 index 00000000..3f6032f2 --- /dev/null +++ b/BlazorTestApp/Program.cs @@ -0,0 +1,15 @@ +using BlazorTestApp.Data; + +var builder = WebApplication.CreateBuilder(args); +var options = builder.Configuration.GetSection(nameof(OpenTokOptions)).Get(); +builder.Services.AddRazorPages(); +builder.Services.AddServerSideBlazor(); +builder.Services.AddSingleton(); +builder.Services.AddSingleton(_ => new OpenTokService(options)); +var app = builder.Build(); +app.UseHttpsRedirection(); +app.UseStaticFiles(); +app.UseRouting(); +app.MapBlazorHub(); +app.MapFallbackToPage("/_Host"); +app.Run(); \ No newline at end of file diff --git a/BlazorTestApp/Properties/launchSettings.json b/BlazorTestApp/Properties/launchSettings.json new file mode 100644 index 00000000..308984e5 --- /dev/null +++ b/BlazorTestApp/Properties/launchSettings.json @@ -0,0 +1,28 @@ +{ + "iisSettings": { + "windowsAuthentication": false, + "anonymousAuthentication": true, + "iisExpress": { + "applicationUrl": "http://localhost:30806", + "sslPort": 44338 + } + }, + "profiles": { + "BlazorTestApp": { + "commandName": "Project", + "dotnetRunMessages": true, + "launchBrowser": true, + "applicationUrl": "https://localhost:7197;http://localhost:5229", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "IIS Express": { + "commandName": "IISExpress", + "launchBrowser": true, + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + } + } +} diff --git a/BlazorTestApp/Shared/MainLayout.razor b/BlazorTestApp/Shared/MainLayout.razor new file mode 100644 index 00000000..ee2f6b23 --- /dev/null +++ b/BlazorTestApp/Shared/MainLayout.razor @@ -0,0 +1,15 @@ +@inherits LayoutComponentBase + +BlazorTestApp + +
+ + +
+
+ @Body +
+
+
\ No newline at end of file diff --git a/BlazorTestApp/Shared/MainLayout.razor.css b/BlazorTestApp/Shared/MainLayout.razor.css new file mode 100644 index 00000000..12f7e581 --- /dev/null +++ b/BlazorTestApp/Shared/MainLayout.razor.css @@ -0,0 +1,70 @@ +.page { + position: relative; + display: flex; + flex-direction: column; +} + +main { + flex: 1; +} + +.sidebar { + background-image: linear-gradient(180deg, rgb(5, 39, 103) 0%, #3a0647 70%); +} + +.top-row { + background-color: #f7f7f7; + border-bottom: 1px solid #d6d5d5; + justify-content: flex-end; + height: 3.5rem; + display: flex; + align-items: center; +} + +.top-row ::deep a, .top-row .btn-link { + white-space: nowrap; + margin-left: 1.5rem; +} + +.top-row a:first-child { + overflow: hidden; + text-overflow: ellipsis; +} + +@media (max-width: 640.98px) { + .top-row:not(.auth) { + display: none; + } + + .top-row.auth { + justify-content: space-between; + } + + .top-row a, .top-row .btn-link { + margin-left: 0; + } +} + +@media (min-width: 641px) { + .page { + flex-direction: row; + } + + .sidebar { + width: 250px; + height: 100vh; + position: sticky; + top: 0; + } + + .top-row { + position: sticky; + top: 0; + z-index: 1; + } + + .top-row, article { + padding-left: 2rem !important; + padding-right: 1.5rem !important; + } +} diff --git a/BlazorTestApp/Shared/NavMenu.razor b/BlazorTestApp/Shared/NavMenu.razor new file mode 100644 index 00000000..57d09136 --- /dev/null +++ b/BlazorTestApp/Shared/NavMenu.razor @@ -0,0 +1,46 @@ + + +
+ +
+ +@code { + private bool collapseNavMenu = true; + + private string? NavMenuCssClass => collapseNavMenu ? "collapse" : null; + + private void ToggleNavMenu() + { + collapseNavMenu = !collapseNavMenu; + } + +} \ No newline at end of file diff --git a/BlazorTestApp/Shared/NavMenu.razor.css b/BlazorTestApp/Shared/NavMenu.razor.css new file mode 100644 index 00000000..5f415c82 --- /dev/null +++ b/BlazorTestApp/Shared/NavMenu.razor.css @@ -0,0 +1,62 @@ +.navbar-toggler { + background-color: rgba(255, 255, 255, 0.1); +} + +.top-row { + height: 3.5rem; + background-color: rgba(0, 0, 0, 0.4); +} + +.navbar-brand { + font-size: 1.1rem; +} + +.oi { + width: 2rem; + font-size: 1.1rem; + vertical-align: text-top; + top: -2px; +} + +.nav-item { + font-size: 0.9rem; + padding-bottom: 0.5rem; +} + +.nav-item:first-of-type { + padding-top: 1rem; +} + +.nav-item:last-of-type { + padding-bottom: 1rem; +} + +.nav-item ::deep a { + color: #d7d7d7; + border-radius: 4px; + height: 3rem; + display: flex; + align-items: center; + line-height: 3rem; +} + +.nav-item ::deep a.active { + background-color: rgba(255, 255, 255, 0.25); + color: white; +} + +.nav-item ::deep a:hover { + background-color: rgba(255, 255, 255, 0.1); + color: white; +} + +@media (min-width: 641px) { + .navbar-toggler { + display: none; + } + + .collapse { + /* Never collapse the sidebar for wide screens */ + display: block; + } +} diff --git a/BlazorTestApp/_Imports.razor b/BlazorTestApp/_Imports.razor new file mode 100644 index 00000000..7600b3da --- /dev/null +++ b/BlazorTestApp/_Imports.razor @@ -0,0 +1,10 @@ +@using System.Net.Http +@using Microsoft.AspNetCore.Authorization +@using Microsoft.AspNetCore.Components.Authorization +@using Microsoft.AspNetCore.Components.Forms +@using Microsoft.AspNetCore.Components.Routing +@using Microsoft.AspNetCore.Components.Web +@using Microsoft.AspNetCore.Components.Web.Virtualization +@using Microsoft.JSInterop +@using BlazorTestApp +@using BlazorTestApp.Shared \ No newline at end of file diff --git a/BlazorTestApp/appsettings.Development.json b/BlazorTestApp/appsettings.Development.json new file mode 100644 index 00000000..770d3e93 --- /dev/null +++ b/BlazorTestApp/appsettings.Development.json @@ -0,0 +1,9 @@ +{ + "DetailedErrors": true, + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + } +} diff --git a/BlazorTestApp/appsettings.json b/BlazorTestApp/appsettings.json new file mode 100644 index 00000000..458427c5 --- /dev/null +++ b/BlazorTestApp/appsettings.json @@ -0,0 +1,14 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + }, + "AllowedHosts": "*", + "OpenTokOptions": { + "ApiKey": "47581421", + "ApiSecret": "c7715696b35c11b025b7cddd399b035f879cc0dd", + "SessionId": "" + } +} diff --git a/BlazorTestApp/wwwroot/content/img/archiving-off.png b/BlazorTestApp/wwwroot/content/img/archiving-off.png new file mode 100644 index 0000000000000000000000000000000000000000..37fb1d94a66209149059de288b114a978b71e07e GIT binary patch literal 21106 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 N002ovPDHLkV1j3z0fGPk literal 0 HcmV?d00001 diff --git a/BlazorTestApp/wwwroot/content/js/host.js b/BlazorTestApp/wwwroot/content/js/host.js new file mode 100644 index 00000000..69204561 --- /dev/null +++ b/BlazorTestApp/wwwroot/content/js/host.js @@ -0,0 +1,34 @@ +window.initializeSession = (apiKey, sessionId, token) => { + var session = OT.initSession(apiKey, sessionId), + publisher = OT.initPublisher('publisher') + session.connect(token, function (error) { + if (error) { + console.error('Failed to connect', error); + } else { + console.log('Session connected.') + session.publish(publisher, function (error) { + if (error) { + console.error('Failed to publish', error); + } + }); + } + }); + + session.on('streamCreated', function (event) { + console.log('Stream created.') + session.subscribe(event.stream, 'subscribers', { + insertMode: 'append' + }, function (error) { + if (error) { + console.error('Failed to subscribe', error); + } + }); + }); + + window.onbeforeunload = function () { + publisher.publishVideo(false); + session.unpublish(publisher); + publisher.destroy(); + } + +}; diff --git a/BlazorTestApp/wwwroot/css/bootstrap/bootstrap.min.css b/BlazorTestApp/wwwroot/css/bootstrap/bootstrap.min.css new file mode 100644 index 00000000..02ae65b5 --- /dev/null +++ b/BlazorTestApp/wwwroot/css/bootstrap/bootstrap.min.css @@ -0,0 +1,7 @@ +@charset "UTF-8";/*! + * Bootstrap v5.1.0 (https://getbootstrap.com/) + * Copyright 2011-2021 The Bootstrap Authors + * Copyright 2011-2021 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) + */:root{--bs-blue:#0d6efd;--bs-indigo:#6610f2;--bs-purple:#6f42c1;--bs-pink:#d63384;--bs-red:#dc3545;--bs-orange:#fd7e14;--bs-yellow:#ffc107;--bs-green:#198754;--bs-teal:#20c997;--bs-cyan:#0dcaf0;--bs-white:#fff;--bs-gray:#6c757d;--bs-gray-dark:#343a40;--bs-gray-100:#f8f9fa;--bs-gray-200:#e9ecef;--bs-gray-300:#dee2e6;--bs-gray-400:#ced4da;--bs-gray-500:#adb5bd;--bs-gray-600:#6c757d;--bs-gray-700:#495057;--bs-gray-800:#343a40;--bs-gray-900:#212529;--bs-primary:#0d6efd;--bs-secondary:#6c757d;--bs-success:#198754;--bs-info:#0dcaf0;--bs-warning:#ffc107;--bs-danger:#dc3545;--bs-light:#f8f9fa;--bs-dark:#212529;--bs-primary-rgb:13,110,253;--bs-secondary-rgb:108,117,125;--bs-success-rgb:25,135,84;--bs-info-rgb:13,202,240;--bs-warning-rgb:255,193,7;--bs-danger-rgb:220,53,69;--bs-light-rgb:248,249,250;--bs-dark-rgb:33,37,41;--bs-white-rgb:255,255,255;--bs-black-rgb:0,0,0;--bs-body-rgb:33,37,41;--bs-font-sans-serif:system-ui,-apple-system,"Segoe UI",Roboto,"Helvetica Neue",Arial,"Noto Sans","Liberation Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";--bs-font-monospace:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;--bs-gradient:linear-gradient(180deg, rgba(255, 255, 255, 0.15), rgba(255, 255, 255, 0));--bs-body-font-family:var(--bs-font-sans-serif);--bs-body-font-size:1rem;--bs-body-font-weight:400;--bs-body-line-height:1.5;--bs-body-color:#212529;--bs-body-bg:#fff}*,::after,::before{box-sizing:border-box}@media (prefers-reduced-motion:no-preference){:root{scroll-behavior:smooth}}body{margin:0;font-family:var(--bs-body-font-family);font-size:var(--bs-body-font-size);font-weight:var(--bs-body-font-weight);line-height:var(--bs-body-line-height);color:var(--bs-body-color);text-align:var(--bs-body-text-align);background-color:var(--bs-body-bg);-webkit-text-size-adjust:100%;-webkit-tap-highlight-color:transparent}hr{margin:1rem 0;color:inherit;background-color:currentColor;border:0;opacity:.25}hr:not([size]){height:1px}.h1,.h2,.h3,.h4,.h5,.h6,h1,h2,h3,h4,h5,h6{margin-top:0;margin-bottom:.5rem;font-weight:500;line-height:1.2}.h1,h1{font-size:calc(1.375rem + 1.5vw)}@media (min-width:1200px){.h1,h1{font-size:2.5rem}}.h2,h2{font-size:calc(1.325rem + .9vw)}@media (min-width:1200px){.h2,h2{font-size:2rem}}.h3,h3{font-size:calc(1.3rem + .6vw)}@media (min-width:1200px){.h3,h3{font-size:1.75rem}}.h4,h4{font-size:calc(1.275rem + .3vw)}@media (min-width:1200px){.h4,h4{font-size:1.5rem}}.h5,h5{font-size:1.25rem}.h6,h6{font-size:1rem}p{margin-top:0;margin-bottom:1rem}abbr[data-bs-original-title],abbr[title]{-webkit-text-decoration:underline dotted;text-decoration:underline dotted;cursor:help;-webkit-text-decoration-skip-ink:none;text-decoration-skip-ink:none}address{margin-bottom:1rem;font-style:normal;line-height:inherit}ol,ul{padding-left:2rem}dl,ol,ul{margin-top:0;margin-bottom:1rem}ol ol,ol ul,ul ol,ul ul{margin-bottom:0}dt{font-weight:700}dd{margin-bottom:.5rem;margin-left:0}blockquote{margin:0 0 1rem}b,strong{font-weight:bolder}.small,small{font-size:.875em}.mark,mark{padding:.2em;background-color:#fcf8e3}sub,sup{position:relative;font-size:.75em;line-height:0;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}a{color:#0d6efd;text-decoration:underline}a:hover{color:#0a58ca}a:not([href]):not([class]),a:not([href]):not([class]):hover{color:inherit;text-decoration:none}code,kbd,pre,samp{font-family:var(--bs-font-monospace);font-size:1em;direction:ltr;unicode-bidi:bidi-override}pre{display:block;margin-top:0;margin-bottom:1rem;overflow:auto;font-size:.875em}pre code{font-size:inherit;color:inherit;word-break:normal}code{font-size:.875em;color:#d63384;word-wrap:break-word}a>code{color:inherit}kbd{padding:.2rem .4rem;font-size:.875em;color:#fff;background-color:#212529;border-radius:.2rem}kbd kbd{padding:0;font-size:1em;font-weight:700}figure{margin:0 0 1rem}img,svg{vertical-align:middle}table{caption-side:bottom;border-collapse:collapse}caption{padding-top:.5rem;padding-bottom:.5rem;color:#6c757d;text-align:left}th{text-align:inherit;text-align:-webkit-match-parent}tbody,td,tfoot,th,thead,tr{border-color:inherit;border-style:solid;border-width:0}label{display:inline-block}button{border-radius:0}button:focus:not(:focus-visible){outline:0}button,input,optgroup,select,textarea{margin:0;font-family:inherit;font-size:inherit;line-height:inherit}button,select{text-transform:none}[role=button]{cursor:pointer}select{word-wrap:normal}select:disabled{opacity:1}[list]::-webkit-calendar-picker-indicator{display:none}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button}[type=button]:not(:disabled),[type=reset]:not(:disabled),[type=submit]:not(:disabled),button:not(:disabled){cursor:pointer}::-moz-focus-inner{padding:0;border-style:none}textarea{resize:vertical}fieldset{min-width:0;padding:0;margin:0;border:0}legend{float:left;width:100%;padding:0;margin-bottom:.5rem;font-size:calc(1.275rem + .3vw);line-height:inherit}@media (min-width:1200px){legend{font-size:1.5rem}}legend+*{clear:left}::-webkit-datetime-edit-day-field,::-webkit-datetime-edit-fields-wrapper,::-webkit-datetime-edit-hour-field,::-webkit-datetime-edit-minute,::-webkit-datetime-edit-month-field,::-webkit-datetime-edit-text,::-webkit-datetime-edit-year-field{padding:0}::-webkit-inner-spin-button{height:auto}[type=search]{outline-offset:-2px;-webkit-appearance:textfield}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-color-swatch-wrapper{padding:0}::file-selector-button{font:inherit}::-webkit-file-upload-button{font:inherit;-webkit-appearance:button}output{display:inline-block}iframe{border:0}summary{display:list-item;cursor:pointer}progress{vertical-align:baseline}[hidden]{display:none!important}.lead{font-size:1.25rem;font-weight:300}.display-1{font-size:calc(1.625rem + 4.5vw);font-weight:300;line-height:1.2}@media (min-width:1200px){.display-1{font-size:5rem}}.display-2{font-size:calc(1.575rem + 3.9vw);font-weight:300;line-height:1.2}@media (min-width:1200px){.display-2{font-size:4.5rem}}.display-3{font-size:calc(1.525rem + 3.3vw);font-weight:300;line-height:1.2}@media (min-width:1200px){.display-3{font-size:4rem}}.display-4{font-size:calc(1.475rem + 2.7vw);font-weight:300;line-height:1.2}@media (min-width:1200px){.display-4{font-size:3.5rem}}.display-5{font-size:calc(1.425rem + 2.1vw);font-weight:300;line-height:1.2}@media (min-width:1200px){.display-5{font-size:3rem}}.display-6{font-size:calc(1.375rem + 1.5vw);font-weight:300;line-height:1.2}@media (min-width:1200px){.display-6{font-size:2.5rem}}.list-unstyled{padding-left:0;list-style:none}.list-inline{padding-left:0;list-style:none}.list-inline-item{display:inline-block}.list-inline-item:not(:last-child){margin-right:.5rem}.initialism{font-size:.875em;text-transform:uppercase}.blockquote{margin-bottom:1rem;font-size:1.25rem}.blockquote>:last-child{margin-bottom:0}.blockquote-footer{margin-top:-1rem;margin-bottom:1rem;font-size:.875em;color:#6c757d}.blockquote-footer::before{content:"— "}.img-fluid{max-width:100%;height:auto}.img-thumbnail{padding:.25rem;background-color:#fff;border:1px solid #dee2e6;border-radius:.25rem;max-width:100%;height:auto}.figure{display:inline-block}.figure-img{margin-bottom:.5rem;line-height:1}.figure-caption{font-size:.875em;color:#6c757d}.container,.container-fluid,.container-lg,.container-md,.container-sm,.container-xl,.container-xxl{width:100%;padding-right:var(--bs-gutter-x,.75rem);padding-left:var(--bs-gutter-x,.75rem);margin-right:auto;margin-left:auto}@media (min-width:576px){.container,.container-sm{max-width:540px}}@media (min-width:768px){.container,.container-md,.container-sm{max-width:720px}}@media (min-width:992px){.container,.container-lg,.container-md,.container-sm{max-width:960px}}@media (min-width:1200px){.container,.container-lg,.container-md,.container-sm,.container-xl{max-width:1140px}}@media (min-width:1400px){.container,.container-lg,.container-md,.container-sm,.container-xl,.container-xxl{max-width:1320px}}.row{--bs-gutter-x:1.5rem;--bs-gutter-y:0;display:flex;flex-wrap:wrap;margin-top:calc(var(--bs-gutter-y) * -1);margin-right:calc(var(--bs-gutter-x) * -.5);margin-left:calc(var(--bs-gutter-x) * -.5)}.row>*{flex-shrink:0;width:100%;max-width:100%;padding-right:calc(var(--bs-gutter-x) * .5);padding-left:calc(var(--bs-gutter-x) * .5);margin-top:var(--bs-gutter-y)}.col{flex:1 0 0%}.row-cols-auto>*{flex:0 0 auto;width:auto}.row-cols-1>*{flex:0 0 auto;width:100%}.row-cols-2>*{flex:0 0 auto;width:50%}.row-cols-3>*{flex:0 0 auto;width:33.3333333333%}.row-cols-4>*{flex:0 0 auto;width:25%}.row-cols-5>*{flex:0 0 auto;width:20%}.row-cols-6>*{flex:0 0 auto;width:16.6666666667%}.col-auto{flex:0 0 auto;width:auto}.col-1{flex:0 0 auto;width:8.33333333%}.col-2{flex:0 0 auto;width:16.66666667%}.col-3{flex:0 0 auto;width:25%}.col-4{flex:0 0 auto;width:33.33333333%}.col-5{flex:0 0 auto;width:41.66666667%}.col-6{flex:0 0 auto;width:50%}.col-7{flex:0 0 auto;width:58.33333333%}.col-8{flex:0 0 auto;width:66.66666667%}.col-9{flex:0 0 auto;width:75%}.col-10{flex:0 0 auto;width:83.33333333%}.col-11{flex:0 0 auto;width:91.66666667%}.col-12{flex:0 0 auto;width:100%}.offset-1{margin-left:8.33333333%}.offset-2{margin-left:16.66666667%}.offset-3{margin-left:25%}.offset-4{margin-left:33.33333333%}.offset-5{margin-left:41.66666667%}.offset-6{margin-left:50%}.offset-7{margin-left:58.33333333%}.offset-8{margin-left:66.66666667%}.offset-9{margin-left:75%}.offset-10{margin-left:83.33333333%}.offset-11{margin-left:91.66666667%}.g-0,.gx-0{--bs-gutter-x:0}.g-0,.gy-0{--bs-gutter-y:0}.g-1,.gx-1{--bs-gutter-x:0.25rem}.g-1,.gy-1{--bs-gutter-y:0.25rem}.g-2,.gx-2{--bs-gutter-x:0.5rem}.g-2,.gy-2{--bs-gutter-y:0.5rem}.g-3,.gx-3{--bs-gutter-x:1rem}.g-3,.gy-3{--bs-gutter-y:1rem}.g-4,.gx-4{--bs-gutter-x:1.5rem}.g-4,.gy-4{--bs-gutter-y:1.5rem}.g-5,.gx-5{--bs-gutter-x:3rem}.g-5,.gy-5{--bs-gutter-y:3rem}@media (min-width:576px){.col-sm{flex:1 0 0%}.row-cols-sm-auto>*{flex:0 0 auto;width:auto}.row-cols-sm-1>*{flex:0 0 auto;width:100%}.row-cols-sm-2>*{flex:0 0 auto;width:50%}.row-cols-sm-3>*{flex:0 0 auto;width:33.3333333333%}.row-cols-sm-4>*{flex:0 0 auto;width:25%}.row-cols-sm-5>*{flex:0 0 auto;width:20%}.row-cols-sm-6>*{flex:0 0 auto;width:16.6666666667%}.col-sm-auto{flex:0 0 auto;width:auto}.col-sm-1{flex:0 0 auto;width:8.33333333%}.col-sm-2{flex:0 0 auto;width:16.66666667%}.col-sm-3{flex:0 0 auto;width:25%}.col-sm-4{flex:0 0 auto;width:33.33333333%}.col-sm-5{flex:0 0 auto;width:41.66666667%}.col-sm-6{flex:0 0 auto;width:50%}.col-sm-7{flex:0 0 auto;width:58.33333333%}.col-sm-8{flex:0 0 auto;width:66.66666667%}.col-sm-9{flex:0 0 auto;width:75%}.col-sm-10{flex:0 0 auto;width:83.33333333%}.col-sm-11{flex:0 0 auto;width:91.66666667%}.col-sm-12{flex:0 0 auto;width:100%}.offset-sm-0{margin-left:0}.offset-sm-1{margin-left:8.33333333%}.offset-sm-2{margin-left:16.66666667%}.offset-sm-3{margin-left:25%}.offset-sm-4{margin-left:33.33333333%}.offset-sm-5{margin-left:41.66666667%}.offset-sm-6{margin-left:50%}.offset-sm-7{margin-left:58.33333333%}.offset-sm-8{margin-left:66.66666667%}.offset-sm-9{margin-left:75%}.offset-sm-10{margin-left:83.33333333%}.offset-sm-11{margin-left:91.66666667%}.g-sm-0,.gx-sm-0{--bs-gutter-x:0}.g-sm-0,.gy-sm-0{--bs-gutter-y:0}.g-sm-1,.gx-sm-1{--bs-gutter-x:0.25rem}.g-sm-1,.gy-sm-1{--bs-gutter-y:0.25rem}.g-sm-2,.gx-sm-2{--bs-gutter-x:0.5rem}.g-sm-2,.gy-sm-2{--bs-gutter-y:0.5rem}.g-sm-3,.gx-sm-3{--bs-gutter-x:1rem}.g-sm-3,.gy-sm-3{--bs-gutter-y:1rem}.g-sm-4,.gx-sm-4{--bs-gutter-x:1.5rem}.g-sm-4,.gy-sm-4{--bs-gutter-y:1.5rem}.g-sm-5,.gx-sm-5{--bs-gutter-x:3rem}.g-sm-5,.gy-sm-5{--bs-gutter-y:3rem}}@media (min-width:768px){.col-md{flex:1 0 0%}.row-cols-md-auto>*{flex:0 0 auto;width:auto}.row-cols-md-1>*{flex:0 0 auto;width:100%}.row-cols-md-2>*{flex:0 0 auto;width:50%}.row-cols-md-3>*{flex:0 0 auto;width:33.3333333333%}.row-cols-md-4>*{flex:0 0 auto;width:25%}.row-cols-md-5>*{flex:0 0 auto;width:20%}.row-cols-md-6>*{flex:0 0 auto;width:16.6666666667%}.col-md-auto{flex:0 0 auto;width:auto}.col-md-1{flex:0 0 auto;width:8.33333333%}.col-md-2{flex:0 0 auto;width:16.66666667%}.col-md-3{flex:0 0 auto;width:25%}.col-md-4{flex:0 0 auto;width:33.33333333%}.col-md-5{flex:0 0 auto;width:41.66666667%}.col-md-6{flex:0 0 auto;width:50%}.col-md-7{flex:0 0 auto;width:58.33333333%}.col-md-8{flex:0 0 auto;width:66.66666667%}.col-md-9{flex:0 0 auto;width:75%}.col-md-10{flex:0 0 auto;width:83.33333333%}.col-md-11{flex:0 0 auto;width:91.66666667%}.col-md-12{flex:0 0 auto;width:100%}.offset-md-0{margin-left:0}.offset-md-1{margin-left:8.33333333%}.offset-md-2{margin-left:16.66666667%}.offset-md-3{margin-left:25%}.offset-md-4{margin-left:33.33333333%}.offset-md-5{margin-left:41.66666667%}.offset-md-6{margin-left:50%}.offset-md-7{margin-left:58.33333333%}.offset-md-8{margin-left:66.66666667%}.offset-md-9{margin-left:75%}.offset-md-10{margin-left:83.33333333%}.offset-md-11{margin-left:91.66666667%}.g-md-0,.gx-md-0{--bs-gutter-x:0}.g-md-0,.gy-md-0{--bs-gutter-y:0}.g-md-1,.gx-md-1{--bs-gutter-x:0.25rem}.g-md-1,.gy-md-1{--bs-gutter-y:0.25rem}.g-md-2,.gx-md-2{--bs-gutter-x:0.5rem}.g-md-2,.gy-md-2{--bs-gutter-y:0.5rem}.g-md-3,.gx-md-3{--bs-gutter-x:1rem}.g-md-3,.gy-md-3{--bs-gutter-y:1rem}.g-md-4,.gx-md-4{--bs-gutter-x:1.5rem}.g-md-4,.gy-md-4{--bs-gutter-y:1.5rem}.g-md-5,.gx-md-5{--bs-gutter-x:3rem}.g-md-5,.gy-md-5{--bs-gutter-y:3rem}}@media (min-width:992px){.col-lg{flex:1 0 0%}.row-cols-lg-auto>*{flex:0 0 auto;width:auto}.row-cols-lg-1>*{flex:0 0 auto;width:100%}.row-cols-lg-2>*{flex:0 0 auto;width:50%}.row-cols-lg-3>*{flex:0 0 auto;width:33.3333333333%}.row-cols-lg-4>*{flex:0 0 auto;width:25%}.row-cols-lg-5>*{flex:0 0 auto;width:20%}.row-cols-lg-6>*{flex:0 0 auto;width:16.6666666667%}.col-lg-auto{flex:0 0 auto;width:auto}.col-lg-1{flex:0 0 auto;width:8.33333333%}.col-lg-2{flex:0 0 auto;width:16.66666667%}.col-lg-3{flex:0 0 auto;width:25%}.col-lg-4{flex:0 0 auto;width:33.33333333%}.col-lg-5{flex:0 0 auto;width:41.66666667%}.col-lg-6{flex:0 0 auto;width:50%}.col-lg-7{flex:0 0 auto;width:58.33333333%}.col-lg-8{flex:0 0 auto;width:66.66666667%}.col-lg-9{flex:0 0 auto;width:75%}.col-lg-10{flex:0 0 auto;width:83.33333333%}.col-lg-11{flex:0 0 auto;width:91.66666667%}.col-lg-12{flex:0 0 auto;width:100%}.offset-lg-0{margin-left:0}.offset-lg-1{margin-left:8.33333333%}.offset-lg-2{margin-left:16.66666667%}.offset-lg-3{margin-left:25%}.offset-lg-4{margin-left:33.33333333%}.offset-lg-5{margin-left:41.66666667%}.offset-lg-6{margin-left:50%}.offset-lg-7{margin-left:58.33333333%}.offset-lg-8{margin-left:66.66666667%}.offset-lg-9{margin-left:75%}.offset-lg-10{margin-left:83.33333333%}.offset-lg-11{margin-left:91.66666667%}.g-lg-0,.gx-lg-0{--bs-gutter-x:0}.g-lg-0,.gy-lg-0{--bs-gutter-y:0}.g-lg-1,.gx-lg-1{--bs-gutter-x:0.25rem}.g-lg-1,.gy-lg-1{--bs-gutter-y:0.25rem}.g-lg-2,.gx-lg-2{--bs-gutter-x:0.5rem}.g-lg-2,.gy-lg-2{--bs-gutter-y:0.5rem}.g-lg-3,.gx-lg-3{--bs-gutter-x:1rem}.g-lg-3,.gy-lg-3{--bs-gutter-y:1rem}.g-lg-4,.gx-lg-4{--bs-gutter-x:1.5rem}.g-lg-4,.gy-lg-4{--bs-gutter-y:1.5rem}.g-lg-5,.gx-lg-5{--bs-gutter-x:3rem}.g-lg-5,.gy-lg-5{--bs-gutter-y:3rem}}@media (min-width:1200px){.col-xl{flex:1 0 0%}.row-cols-xl-auto>*{flex:0 0 auto;width:auto}.row-cols-xl-1>*{flex:0 0 auto;width:100%}.row-cols-xl-2>*{flex:0 0 auto;width:50%}.row-cols-xl-3>*{flex:0 0 auto;width:33.3333333333%}.row-cols-xl-4>*{flex:0 0 auto;width:25%}.row-cols-xl-5>*{flex:0 0 auto;width:20%}.row-cols-xl-6>*{flex:0 0 auto;width:16.6666666667%}.col-xl-auto{flex:0 0 auto;width:auto}.col-xl-1{flex:0 0 auto;width:8.33333333%}.col-xl-2{flex:0 0 auto;width:16.66666667%}.col-xl-3{flex:0 0 auto;width:25%}.col-xl-4{flex:0 0 auto;width:33.33333333%}.col-xl-5{flex:0 0 auto;width:41.66666667%}.col-xl-6{flex:0 0 auto;width:50%}.col-xl-7{flex:0 0 auto;width:58.33333333%}.col-xl-8{flex:0 0 auto;width:66.66666667%}.col-xl-9{flex:0 0 auto;width:75%}.col-xl-10{flex:0 0 auto;width:83.33333333%}.col-xl-11{flex:0 0 auto;width:91.66666667%}.col-xl-12{flex:0 0 auto;width:100%}.offset-xl-0{margin-left:0}.offset-xl-1{margin-left:8.33333333%}.offset-xl-2{margin-left:16.66666667%}.offset-xl-3{margin-left:25%}.offset-xl-4{margin-left:33.33333333%}.offset-xl-5{margin-left:41.66666667%}.offset-xl-6{margin-left:50%}.offset-xl-7{margin-left:58.33333333%}.offset-xl-8{margin-left:66.66666667%}.offset-xl-9{margin-left:75%}.offset-xl-10{margin-left:83.33333333%}.offset-xl-11{margin-left:91.66666667%}.g-xl-0,.gx-xl-0{--bs-gutter-x:0}.g-xl-0,.gy-xl-0{--bs-gutter-y:0}.g-xl-1,.gx-xl-1{--bs-gutter-x:0.25rem}.g-xl-1,.gy-xl-1{--bs-gutter-y:0.25rem}.g-xl-2,.gx-xl-2{--bs-gutter-x:0.5rem}.g-xl-2,.gy-xl-2{--bs-gutter-y:0.5rem}.g-xl-3,.gx-xl-3{--bs-gutter-x:1rem}.g-xl-3,.gy-xl-3{--bs-gutter-y:1rem}.g-xl-4,.gx-xl-4{--bs-gutter-x:1.5rem}.g-xl-4,.gy-xl-4{--bs-gutter-y:1.5rem}.g-xl-5,.gx-xl-5{--bs-gutter-x:3rem}.g-xl-5,.gy-xl-5{--bs-gutter-y:3rem}}@media (min-width:1400px){.col-xxl{flex:1 0 0%}.row-cols-xxl-auto>*{flex:0 0 auto;width:auto}.row-cols-xxl-1>*{flex:0 0 auto;width:100%}.row-cols-xxl-2>*{flex:0 0 auto;width:50%}.row-cols-xxl-3>*{flex:0 0 auto;width:33.3333333333%}.row-cols-xxl-4>*{flex:0 0 auto;width:25%}.row-cols-xxl-5>*{flex:0 0 auto;width:20%}.row-cols-xxl-6>*{flex:0 0 auto;width:16.6666666667%}.col-xxl-auto{flex:0 0 auto;width:auto}.col-xxl-1{flex:0 0 auto;width:8.33333333%}.col-xxl-2{flex:0 0 auto;width:16.66666667%}.col-xxl-3{flex:0 0 auto;width:25%}.col-xxl-4{flex:0 0 auto;width:33.33333333%}.col-xxl-5{flex:0 0 auto;width:41.66666667%}.col-xxl-6{flex:0 0 auto;width:50%}.col-xxl-7{flex:0 0 auto;width:58.33333333%}.col-xxl-8{flex:0 0 auto;width:66.66666667%}.col-xxl-9{flex:0 0 auto;width:75%}.col-xxl-10{flex:0 0 auto;width:83.33333333%}.col-xxl-11{flex:0 0 auto;width:91.66666667%}.col-xxl-12{flex:0 0 auto;width:100%}.offset-xxl-0{margin-left:0}.offset-xxl-1{margin-left:8.33333333%}.offset-xxl-2{margin-left:16.66666667%}.offset-xxl-3{margin-left:25%}.offset-xxl-4{margin-left:33.33333333%}.offset-xxl-5{margin-left:41.66666667%}.offset-xxl-6{margin-left:50%}.offset-xxl-7{margin-left:58.33333333%}.offset-xxl-8{margin-left:66.66666667%}.offset-xxl-9{margin-left:75%}.offset-xxl-10{margin-left:83.33333333%}.offset-xxl-11{margin-left:91.66666667%}.g-xxl-0,.gx-xxl-0{--bs-gutter-x:0}.g-xxl-0,.gy-xxl-0{--bs-gutter-y:0}.g-xxl-1,.gx-xxl-1{--bs-gutter-x:0.25rem}.g-xxl-1,.gy-xxl-1{--bs-gutter-y:0.25rem}.g-xxl-2,.gx-xxl-2{--bs-gutter-x:0.5rem}.g-xxl-2,.gy-xxl-2{--bs-gutter-y:0.5rem}.g-xxl-3,.gx-xxl-3{--bs-gutter-x:1rem}.g-xxl-3,.gy-xxl-3{--bs-gutter-y:1rem}.g-xxl-4,.gx-xxl-4{--bs-gutter-x:1.5rem}.g-xxl-4,.gy-xxl-4{--bs-gutter-y:1.5rem}.g-xxl-5,.gx-xxl-5{--bs-gutter-x:3rem}.g-xxl-5,.gy-xxl-5{--bs-gutter-y:3rem}}.table{--bs-table-bg:transparent;--bs-table-accent-bg:transparent;--bs-table-striped-color:#212529;--bs-table-striped-bg:rgba(0, 0, 0, 0.05);--bs-table-active-color:#212529;--bs-table-active-bg:rgba(0, 0, 0, 0.1);--bs-table-hover-color:#212529;--bs-table-hover-bg:rgba(0, 0, 0, 0.075);width:100%;margin-bottom:1rem;color:#212529;vertical-align:top;border-color:#dee2e6}.table>:not(caption)>*>*{padding:.5rem .5rem;background-color:var(--bs-table-bg);border-bottom-width:1px;box-shadow:inset 0 0 0 9999px var(--bs-table-accent-bg)}.table>tbody{vertical-align:inherit}.table>thead{vertical-align:bottom}.table>:not(:last-child)>:last-child>*{border-bottom-color:currentColor}.caption-top{caption-side:top}.table-sm>:not(caption)>*>*{padding:.25rem .25rem}.table-bordered>:not(caption)>*{border-width:1px 0}.table-bordered>:not(caption)>*>*{border-width:0 1px}.table-borderless>:not(caption)>*>*{border-bottom-width:0}.table-striped>tbody>tr:nth-of-type(odd){--bs-table-accent-bg:var(--bs-table-striped-bg);color:var(--bs-table-striped-color)}.table-active{--bs-table-accent-bg:var(--bs-table-active-bg);color:var(--bs-table-active-color)}.table-hover>tbody>tr:hover{--bs-table-accent-bg:var(--bs-table-hover-bg);color:var(--bs-table-hover-color)}.table-primary{--bs-table-bg:#cfe2ff;--bs-table-striped-bg:#c5d7f2;--bs-table-striped-color:#000;--bs-table-active-bg:#bacbe6;--bs-table-active-color:#000;--bs-table-hover-bg:#bfd1ec;--bs-table-hover-color:#000;color:#000;border-color:#bacbe6}.table-secondary{--bs-table-bg:#e2e3e5;--bs-table-striped-bg:#d7d8da;--bs-table-striped-color:#000;--bs-table-active-bg:#cbccce;--bs-table-active-color:#000;--bs-table-hover-bg:#d1d2d4;--bs-table-hover-color:#000;color:#000;border-color:#cbccce}.table-success{--bs-table-bg:#d1e7dd;--bs-table-striped-bg:#c7dbd2;--bs-table-striped-color:#000;--bs-table-active-bg:#bcd0c7;--bs-table-active-color:#000;--bs-table-hover-bg:#c1d6cc;--bs-table-hover-color:#000;color:#000;border-color:#bcd0c7}.table-info{--bs-table-bg:#cff4fc;--bs-table-striped-bg:#c5e8ef;--bs-table-striped-color:#000;--bs-table-active-bg:#badce3;--bs-table-active-color:#000;--bs-table-hover-bg:#bfe2e9;--bs-table-hover-color:#000;color:#000;border-color:#badce3}.table-warning{--bs-table-bg:#fff3cd;--bs-table-striped-bg:#f2e7c3;--bs-table-striped-color:#000;--bs-table-active-bg:#e6dbb9;--bs-table-active-color:#000;--bs-table-hover-bg:#ece1be;--bs-table-hover-color:#000;color:#000;border-color:#e6dbb9}.table-danger{--bs-table-bg:#f8d7da;--bs-table-striped-bg:#eccccf;--bs-table-striped-color:#000;--bs-table-active-bg:#dfc2c4;--bs-table-active-color:#000;--bs-table-hover-bg:#e5c7ca;--bs-table-hover-color:#000;color:#000;border-color:#dfc2c4}.table-light{--bs-table-bg:#f8f9fa;--bs-table-striped-bg:#ecedee;--bs-table-striped-color:#000;--bs-table-active-bg:#dfe0e1;--bs-table-active-color:#000;--bs-table-hover-bg:#e5e6e7;--bs-table-hover-color:#000;color:#000;border-color:#dfe0e1}.table-dark{--bs-table-bg:#212529;--bs-table-striped-bg:#2c3034;--bs-table-striped-color:#fff;--bs-table-active-bg:#373b3e;--bs-table-active-color:#fff;--bs-table-hover-bg:#323539;--bs-table-hover-color:#fff;color:#fff;border-color:#373b3e}.table-responsive{overflow-x:auto;-webkit-overflow-scrolling:touch}@media (max-width:575.98px){.table-responsive-sm{overflow-x:auto;-webkit-overflow-scrolling:touch}}@media (max-width:767.98px){.table-responsive-md{overflow-x:auto;-webkit-overflow-scrolling:touch}}@media (max-width:991.98px){.table-responsive-lg{overflow-x:auto;-webkit-overflow-scrolling:touch}}@media (max-width:1199.98px){.table-responsive-xl{overflow-x:auto;-webkit-overflow-scrolling:touch}}@media (max-width:1399.98px){.table-responsive-xxl{overflow-x:auto;-webkit-overflow-scrolling:touch}}.form-label{margin-bottom:.5rem}.col-form-label{padding-top:calc(.375rem + 1px);padding-bottom:calc(.375rem + 1px);margin-bottom:0;font-size:inherit;line-height:1.5}.col-form-label-lg{padding-top:calc(.5rem + 1px);padding-bottom:calc(.5rem + 1px);font-size:1.25rem}.col-form-label-sm{padding-top:calc(.25rem + 1px);padding-bottom:calc(.25rem + 1px);font-size:.875rem}.form-text{margin-top:.25rem;font-size:.875em;color:#6c757d}.form-control{display:block;width:100%;padding:.375rem .75rem;font-size:1rem;font-weight:400;line-height:1.5;color:#212529;background-color:#fff;background-clip:padding-box;border:1px solid #ced4da;-webkit-appearance:none;-moz-appearance:none;appearance:none;border-radius:.25rem;transition:border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media (prefers-reduced-motion:reduce){.form-control{transition:none}}.form-control[type=file]{overflow:hidden}.form-control[type=file]:not(:disabled):not([readonly]){cursor:pointer}.form-control:focus{color:#212529;background-color:#fff;border-color:#86b7fe;outline:0;box-shadow:0 0 0 .25rem rgba(13,110,253,.25)}.form-control::-webkit-date-and-time-value{height:1.5em}.form-control::-moz-placeholder{color:#6c757d;opacity:1}.form-control::placeholder{color:#6c757d;opacity:1}.form-control:disabled,.form-control[readonly]{background-color:#e9ecef;opacity:1}.form-control::file-selector-button{padding:.375rem .75rem;margin:-.375rem -.75rem;-webkit-margin-end:.75rem;margin-inline-end:.75rem;color:#212529;background-color:#e9ecef;pointer-events:none;border-color:inherit;border-style:solid;border-width:0;border-inline-end-width:1px;border-radius:0;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media (prefers-reduced-motion:reduce){.form-control::file-selector-button{transition:none}}.form-control:hover:not(:disabled):not([readonly])::file-selector-button{background-color:#dde0e3}.form-control::-webkit-file-upload-button{padding:.375rem .75rem;margin:-.375rem -.75rem;-webkit-margin-end:.75rem;margin-inline-end:.75rem;color:#212529;background-color:#e9ecef;pointer-events:none;border-color:inherit;border-style:solid;border-width:0;border-inline-end-width:1px;border-radius:0;-webkit-transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media (prefers-reduced-motion:reduce){.form-control::-webkit-file-upload-button{-webkit-transition:none;transition:none}}.form-control:hover:not(:disabled):not([readonly])::-webkit-file-upload-button{background-color:#dde0e3}.form-control-plaintext{display:block;width:100%;padding:.375rem 0;margin-bottom:0;line-height:1.5;color:#212529;background-color:transparent;border:solid transparent;border-width:1px 0}.form-control-plaintext.form-control-lg,.form-control-plaintext.form-control-sm{padding-right:0;padding-left:0}.form-control-sm{min-height:calc(1.5em + .5rem + 2px);padding:.25rem .5rem;font-size:.875rem;border-radius:.2rem}.form-control-sm::file-selector-button{padding:.25rem .5rem;margin:-.25rem -.5rem;-webkit-margin-end:.5rem;margin-inline-end:.5rem}.form-control-sm::-webkit-file-upload-button{padding:.25rem .5rem;margin:-.25rem -.5rem;-webkit-margin-end:.5rem;margin-inline-end:.5rem}.form-control-lg{min-height:calc(1.5em + 1rem + 2px);padding:.5rem 1rem;font-size:1.25rem;border-radius:.3rem}.form-control-lg::file-selector-button{padding:.5rem 1rem;margin:-.5rem -1rem;-webkit-margin-end:1rem;margin-inline-end:1rem}.form-control-lg::-webkit-file-upload-button{padding:.5rem 1rem;margin:-.5rem -1rem;-webkit-margin-end:1rem;margin-inline-end:1rem}textarea.form-control{min-height:calc(1.5em + .75rem + 2px)}textarea.form-control-sm{min-height:calc(1.5em + .5rem + 2px)}textarea.form-control-lg{min-height:calc(1.5em + 1rem + 2px)}.form-control-color{width:3rem;height:auto;padding:.375rem}.form-control-color:not(:disabled):not([readonly]){cursor:pointer}.form-control-color::-moz-color-swatch{height:1.5em;border-radius:.25rem}.form-control-color::-webkit-color-swatch{height:1.5em;border-radius:.25rem}.form-select{display:block;width:100%;padding:.375rem 2.25rem .375rem .75rem;-moz-padding-start:calc(0.75rem - 3px);font-size:1rem;font-weight:400;line-height:1.5;color:#212529;background-color:#fff;background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%23343a40' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M2 5l6 6 6-6'/%3e%3c/svg%3e");background-repeat:no-repeat;background-position:right .75rem center;background-size:16px 12px;border:1px solid #ced4da;border-radius:.25rem;transition:border-color .15s ease-in-out,box-shadow .15s ease-in-out;-webkit-appearance:none;-moz-appearance:none;appearance:none}@media (prefers-reduced-motion:reduce){.form-select{transition:none}}.form-select:focus{border-color:#86b7fe;outline:0;box-shadow:0 0 0 .25rem rgba(13,110,253,.25)}.form-select[multiple],.form-select[size]:not([size="1"]){padding-right:.75rem;background-image:none}.form-select:disabled{background-color:#e9ecef}.form-select:-moz-focusring{color:transparent;text-shadow:0 0 0 #212529}.form-select-sm{padding-top:.25rem;padding-bottom:.25rem;padding-left:.5rem;font-size:.875rem}.form-select-lg{padding-top:.5rem;padding-bottom:.5rem;padding-left:1rem;font-size:1.25rem}.form-check{display:block;min-height:1.5rem;padding-left:1.5em;margin-bottom:.125rem}.form-check .form-check-input{float:left;margin-left:-1.5em}.form-check-input{width:1em;height:1em;margin-top:.25em;vertical-align:top;background-color:#fff;background-repeat:no-repeat;background-position:center;background-size:contain;border:1px solid rgba(0,0,0,.25);-webkit-appearance:none;-moz-appearance:none;appearance:none;-webkit-print-color-adjust:exact;color-adjust:exact}.form-check-input[type=checkbox]{border-radius:.25em}.form-check-input[type=radio]{border-radius:50%}.form-check-input:active{filter:brightness(90%)}.form-check-input:focus{border-color:#86b7fe;outline:0;box-shadow:0 0 0 .25rem rgba(13,110,253,.25)}.form-check-input:checked{background-color:#0d6efd;border-color:#0d6efd}.form-check-input:checked[type=checkbox]{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20'%3e%3cpath fill='none' stroke='%23fff' stroke-linecap='round' stroke-linejoin='round' stroke-width='3' d='M6 10l3 3l6-6'/%3e%3c/svg%3e")}.form-check-input:checked[type=radio]{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='2' fill='%23fff'/%3e%3c/svg%3e")}.form-check-input[type=checkbox]:indeterminate{background-color:#0d6efd;border-color:#0d6efd;background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20'%3e%3cpath fill='none' stroke='%23fff' stroke-linecap='round' stroke-linejoin='round' stroke-width='3' d='M6 10h8'/%3e%3c/svg%3e")}.form-check-input:disabled{pointer-events:none;filter:none;opacity:.5}.form-check-input:disabled~.form-check-label,.form-check-input[disabled]~.form-check-label{opacity:.5}.form-switch{padding-left:2.5em}.form-switch .form-check-input{width:2em;margin-left:-2.5em;background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='rgba%280, 0, 0, 0.25%29'/%3e%3c/svg%3e");background-position:left center;border-radius:2em;transition:background-position .15s ease-in-out}@media (prefers-reduced-motion:reduce){.form-switch .form-check-input{transition:none}}.form-switch .form-check-input:focus{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='%2386b7fe'/%3e%3c/svg%3e")}.form-switch .form-check-input:checked{background-position:right center;background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='%23fff'/%3e%3c/svg%3e")}.form-check-inline{display:inline-block;margin-right:1rem}.btn-check{position:absolute;clip:rect(0,0,0,0);pointer-events:none}.btn-check:disabled+.btn,.btn-check[disabled]+.btn{pointer-events:none;filter:none;opacity:.65}.form-range{width:100%;height:1.5rem;padding:0;background-color:transparent;-webkit-appearance:none;-moz-appearance:none;appearance:none}.form-range:focus{outline:0}.form-range:focus::-webkit-slider-thumb{box-shadow:0 0 0 1px #fff,0 0 0 .25rem rgba(13,110,253,.25)}.form-range:focus::-moz-range-thumb{box-shadow:0 0 0 1px #fff,0 0 0 .25rem rgba(13,110,253,.25)}.form-range::-moz-focus-outer{border:0}.form-range::-webkit-slider-thumb{width:1rem;height:1rem;margin-top:-.25rem;background-color:#0d6efd;border:0;border-radius:1rem;-webkit-transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;-webkit-appearance:none;appearance:none}@media (prefers-reduced-motion:reduce){.form-range::-webkit-slider-thumb{-webkit-transition:none;transition:none}}.form-range::-webkit-slider-thumb:active{background-color:#b6d4fe}.form-range::-webkit-slider-runnable-track{width:100%;height:.5rem;color:transparent;cursor:pointer;background-color:#dee2e6;border-color:transparent;border-radius:1rem}.form-range::-moz-range-thumb{width:1rem;height:1rem;background-color:#0d6efd;border:0;border-radius:1rem;-moz-transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;-moz-appearance:none;appearance:none}@media (prefers-reduced-motion:reduce){.form-range::-moz-range-thumb{-moz-transition:none;transition:none}}.form-range::-moz-range-thumb:active{background-color:#b6d4fe}.form-range::-moz-range-track{width:100%;height:.5rem;color:transparent;cursor:pointer;background-color:#dee2e6;border-color:transparent;border-radius:1rem}.form-range:disabled{pointer-events:none}.form-range:disabled::-webkit-slider-thumb{background-color:#adb5bd}.form-range:disabled::-moz-range-thumb{background-color:#adb5bd}.form-floating{position:relative}.form-floating>.form-control,.form-floating>.form-select{height:calc(3.5rem + 2px);line-height:1.25}.form-floating>label{position:absolute;top:0;left:0;height:100%;padding:1rem .75rem;pointer-events:none;border:1px solid transparent;transform-origin:0 0;transition:opacity .1s ease-in-out,transform .1s ease-in-out}@media (prefers-reduced-motion:reduce){.form-floating>label{transition:none}}.form-floating>.form-control{padding:1rem .75rem}.form-floating>.form-control::-moz-placeholder{color:transparent}.form-floating>.form-control::placeholder{color:transparent}.form-floating>.form-control:not(:-moz-placeholder-shown){padding-top:1.625rem;padding-bottom:.625rem}.form-floating>.form-control:focus,.form-floating>.form-control:not(:placeholder-shown){padding-top:1.625rem;padding-bottom:.625rem}.form-floating>.form-control:-webkit-autofill{padding-top:1.625rem;padding-bottom:.625rem}.form-floating>.form-select{padding-top:1.625rem;padding-bottom:.625rem}.form-floating>.form-control:not(:-moz-placeholder-shown)~label{opacity:.65;transform:scale(.85) translateY(-.5rem) translateX(.15rem)}.form-floating>.form-control:focus~label,.form-floating>.form-control:not(:placeholder-shown)~label,.form-floating>.form-select~label{opacity:.65;transform:scale(.85) translateY(-.5rem) translateX(.15rem)}.form-floating>.form-control:-webkit-autofill~label{opacity:.65;transform:scale(.85) translateY(-.5rem) translateX(.15rem)}.input-group{position:relative;display:flex;flex-wrap:wrap;align-items:stretch;width:100%}.input-group>.form-control,.input-group>.form-select{position:relative;flex:1 1 auto;width:1%;min-width:0}.input-group>.form-control:focus,.input-group>.form-select:focus{z-index:3}.input-group .btn{position:relative;z-index:2}.input-group .btn:focus{z-index:3}.input-group-text{display:flex;align-items:center;padding:.375rem .75rem;font-size:1rem;font-weight:400;line-height:1.5;color:#212529;text-align:center;white-space:nowrap;background-color:#e9ecef;border:1px solid #ced4da;border-radius:.25rem}.input-group-lg>.btn,.input-group-lg>.form-control,.input-group-lg>.form-select,.input-group-lg>.input-group-text{padding:.5rem 1rem;font-size:1.25rem;border-radius:.3rem}.input-group-sm>.btn,.input-group-sm>.form-control,.input-group-sm>.form-select,.input-group-sm>.input-group-text{padding:.25rem .5rem;font-size:.875rem;border-radius:.2rem}.input-group-lg>.form-select,.input-group-sm>.form-select{padding-right:3rem}.input-group:not(.has-validation)>.dropdown-toggle:nth-last-child(n+3),.input-group:not(.has-validation)>:not(:last-child):not(.dropdown-toggle):not(.dropdown-menu){border-top-right-radius:0;border-bottom-right-radius:0}.input-group.has-validation>.dropdown-toggle:nth-last-child(n+4),.input-group.has-validation>:nth-last-child(n+3):not(.dropdown-toggle):not(.dropdown-menu){border-top-right-radius:0;border-bottom-right-radius:0}.input-group>:not(:first-child):not(.dropdown-menu):not(.valid-tooltip):not(.valid-feedback):not(.invalid-tooltip):not(.invalid-feedback){margin-left:-1px;border-top-left-radius:0;border-bottom-left-radius:0}.valid-feedback{display:none;width:100%;margin-top:.25rem;font-size:.875em;color:#198754}.valid-tooltip{position:absolute;top:100%;z-index:5;display:none;max-width:100%;padding:.25rem .5rem;margin-top:.1rem;font-size:.875rem;color:#fff;background-color:rgba(25,135,84,.9);border-radius:.25rem}.is-valid~.valid-feedback,.is-valid~.valid-tooltip,.was-validated :valid~.valid-feedback,.was-validated :valid~.valid-tooltip{display:block}.form-control.is-valid,.was-validated .form-control:valid{border-color:#198754;padding-right:calc(1.5em + .75rem);background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3e%3cpath fill='%23198754' d='M2.3 6.73L.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1z'/%3e%3c/svg%3e");background-repeat:no-repeat;background-position:right calc(.375em + .1875rem) center;background-size:calc(.75em + .375rem) calc(.75em + .375rem)}.form-control.is-valid:focus,.was-validated .form-control:valid:focus{border-color:#198754;box-shadow:0 0 0 .25rem rgba(25,135,84,.25)}.was-validated textarea.form-control:valid,textarea.form-control.is-valid{padding-right:calc(1.5em + .75rem);background-position:top calc(.375em + .1875rem) right calc(.375em + .1875rem)}.form-select.is-valid,.was-validated .form-select:valid{border-color:#198754}.form-select.is-valid:not([multiple]):not([size]),.form-select.is-valid:not([multiple])[size="1"],.was-validated .form-select:valid:not([multiple]):not([size]),.was-validated .form-select:valid:not([multiple])[size="1"]{padding-right:4.125rem;background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%23343a40' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M2 5l6 6 6-6'/%3e%3c/svg%3e"),url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3e%3cpath fill='%23198754' d='M2.3 6.73L.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1z'/%3e%3c/svg%3e");background-position:right .75rem center,center right 2.25rem;background-size:16px 12px,calc(.75em + .375rem) calc(.75em + .375rem)}.form-select.is-valid:focus,.was-validated .form-select:valid:focus{border-color:#198754;box-shadow:0 0 0 .25rem rgba(25,135,84,.25)}.form-check-input.is-valid,.was-validated .form-check-input:valid{border-color:#198754}.form-check-input.is-valid:checked,.was-validated .form-check-input:valid:checked{background-color:#198754}.form-check-input.is-valid:focus,.was-validated .form-check-input:valid:focus{box-shadow:0 0 0 .25rem rgba(25,135,84,.25)}.form-check-input.is-valid~.form-check-label,.was-validated .form-check-input:valid~.form-check-label{color:#198754}.form-check-inline .form-check-input~.valid-feedback{margin-left:.5em}.input-group .form-control.is-valid,.input-group .form-select.is-valid,.was-validated .input-group .form-control:valid,.was-validated .input-group .form-select:valid{z-index:1}.input-group .form-control.is-valid:focus,.input-group .form-select.is-valid:focus,.was-validated .input-group .form-control:valid:focus,.was-validated .input-group .form-select:valid:focus{z-index:3}.invalid-feedback{display:none;width:100%;margin-top:.25rem;font-size:.875em;color:#dc3545}.invalid-tooltip{position:absolute;top:100%;z-index:5;display:none;max-width:100%;padding:.25rem .5rem;margin-top:.1rem;font-size:.875rem;color:#fff;background-color:rgba(220,53,69,.9);border-radius:.25rem}.is-invalid~.invalid-feedback,.is-invalid~.invalid-tooltip,.was-validated :invalid~.invalid-feedback,.was-validated :invalid~.invalid-tooltip{display:block}.form-control.is-invalid,.was-validated .form-control:invalid{border-color:#dc3545;padding-right:calc(1.5em + .75rem);background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12' width='12' height='12' fill='none' stroke='%23dc3545'%3e%3ccircle cx='6' cy='6' r='4.5'/%3e%3cpath stroke-linejoin='round' d='M5.8 3.6h.4L6 6.5z'/%3e%3ccircle cx='6' cy='8.2' r='.6' fill='%23dc3545' stroke='none'/%3e%3c/svg%3e");background-repeat:no-repeat;background-position:right calc(.375em + .1875rem) center;background-size:calc(.75em + .375rem) calc(.75em + .375rem)}.form-control.is-invalid:focus,.was-validated .form-control:invalid:focus{border-color:#dc3545;box-shadow:0 0 0 .25rem rgba(220,53,69,.25)}.was-validated textarea.form-control:invalid,textarea.form-control.is-invalid{padding-right:calc(1.5em + .75rem);background-position:top calc(.375em + .1875rem) right calc(.375em + .1875rem)}.form-select.is-invalid,.was-validated .form-select:invalid{border-color:#dc3545}.form-select.is-invalid:not([multiple]):not([size]),.form-select.is-invalid:not([multiple])[size="1"],.was-validated .form-select:invalid:not([multiple]):not([size]),.was-validated .form-select:invalid:not([multiple])[size="1"]{padding-right:4.125rem;background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%23343a40' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M2 5l6 6 6-6'/%3e%3c/svg%3e"),url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12' width='12' height='12' fill='none' stroke='%23dc3545'%3e%3ccircle cx='6' cy='6' r='4.5'/%3e%3cpath stroke-linejoin='round' d='M5.8 3.6h.4L6 6.5z'/%3e%3ccircle cx='6' cy='8.2' r='.6' fill='%23dc3545' stroke='none'/%3e%3c/svg%3e");background-position:right .75rem center,center right 2.25rem;background-size:16px 12px,calc(.75em + .375rem) calc(.75em + .375rem)}.form-select.is-invalid:focus,.was-validated .form-select:invalid:focus{border-color:#dc3545;box-shadow:0 0 0 .25rem rgba(220,53,69,.25)}.form-check-input.is-invalid,.was-validated .form-check-input:invalid{border-color:#dc3545}.form-check-input.is-invalid:checked,.was-validated .form-check-input:invalid:checked{background-color:#dc3545}.form-check-input.is-invalid:focus,.was-validated .form-check-input:invalid:focus{box-shadow:0 0 0 .25rem rgba(220,53,69,.25)}.form-check-input.is-invalid~.form-check-label,.was-validated .form-check-input:invalid~.form-check-label{color:#dc3545}.form-check-inline .form-check-input~.invalid-feedback{margin-left:.5em}.input-group .form-control.is-invalid,.input-group .form-select.is-invalid,.was-validated .input-group .form-control:invalid,.was-validated .input-group .form-select:invalid{z-index:2}.input-group .form-control.is-invalid:focus,.input-group .form-select.is-invalid:focus,.was-validated .input-group .form-control:invalid:focus,.was-validated .input-group .form-select:invalid:focus{z-index:3}.btn{display:inline-block;font-weight:400;line-height:1.5;color:#212529;text-align:center;text-decoration:none;vertical-align:middle;cursor:pointer;-webkit-user-select:none;-moz-user-select:none;user-select:none;background-color:transparent;border:1px solid transparent;padding:.375rem .75rem;font-size:1rem;border-radius:.25rem;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media (prefers-reduced-motion:reduce){.btn{transition:none}}.btn:hover{color:#212529}.btn-check:focus+.btn,.btn:focus{outline:0;box-shadow:0 0 0 .25rem rgba(13,110,253,.25)}.btn.disabled,.btn:disabled,fieldset:disabled .btn{pointer-events:none;opacity:.65}.btn-primary{color:#fff;background-color:#0d6efd;border-color:#0d6efd}.btn-primary:hover{color:#fff;background-color:#0b5ed7;border-color:#0a58ca}.btn-check:focus+.btn-primary,.btn-primary:focus{color:#fff;background-color:#0b5ed7;border-color:#0a58ca;box-shadow:0 0 0 .25rem rgba(49,132,253,.5)}.btn-check:active+.btn-primary,.btn-check:checked+.btn-primary,.btn-primary.active,.btn-primary:active,.show>.btn-primary.dropdown-toggle{color:#fff;background-color:#0a58ca;border-color:#0a53be}.btn-check:active+.btn-primary:focus,.btn-check:checked+.btn-primary:focus,.btn-primary.active:focus,.btn-primary:active:focus,.show>.btn-primary.dropdown-toggle:focus{box-shadow:0 0 0 .25rem rgba(49,132,253,.5)}.btn-primary.disabled,.btn-primary:disabled{color:#fff;background-color:#0d6efd;border-color:#0d6efd}.btn-secondary{color:#fff;background-color:#6c757d;border-color:#6c757d}.btn-secondary:hover{color:#fff;background-color:#5c636a;border-color:#565e64}.btn-check:focus+.btn-secondary,.btn-secondary:focus{color:#fff;background-color:#5c636a;border-color:#565e64;box-shadow:0 0 0 .25rem rgba(130,138,145,.5)}.btn-check:active+.btn-secondary,.btn-check:checked+.btn-secondary,.btn-secondary.active,.btn-secondary:active,.show>.btn-secondary.dropdown-toggle{color:#fff;background-color:#565e64;border-color:#51585e}.btn-check:active+.btn-secondary:focus,.btn-check:checked+.btn-secondary:focus,.btn-secondary.active:focus,.btn-secondary:active:focus,.show>.btn-secondary.dropdown-toggle:focus{box-shadow:0 0 0 .25rem rgba(130,138,145,.5)}.btn-secondary.disabled,.btn-secondary:disabled{color:#fff;background-color:#6c757d;border-color:#6c757d}.btn-success{color:#fff;background-color:#198754;border-color:#198754}.btn-success:hover{color:#fff;background-color:#157347;border-color:#146c43}.btn-check:focus+.btn-success,.btn-success:focus{color:#fff;background-color:#157347;border-color:#146c43;box-shadow:0 0 0 .25rem rgba(60,153,110,.5)}.btn-check:active+.btn-success,.btn-check:checked+.btn-success,.btn-success.active,.btn-success:active,.show>.btn-success.dropdown-toggle{color:#fff;background-color:#146c43;border-color:#13653f}.btn-check:active+.btn-success:focus,.btn-check:checked+.btn-success:focus,.btn-success.active:focus,.btn-success:active:focus,.show>.btn-success.dropdown-toggle:focus{box-shadow:0 0 0 .25rem rgba(60,153,110,.5)}.btn-success.disabled,.btn-success:disabled{color:#fff;background-color:#198754;border-color:#198754}.btn-info{color:#000;background-color:#0dcaf0;border-color:#0dcaf0}.btn-info:hover{color:#000;background-color:#31d2f2;border-color:#25cff2}.btn-check:focus+.btn-info,.btn-info:focus{color:#000;background-color:#31d2f2;border-color:#25cff2;box-shadow:0 0 0 .25rem rgba(11,172,204,.5)}.btn-check:active+.btn-info,.btn-check:checked+.btn-info,.btn-info.active,.btn-info:active,.show>.btn-info.dropdown-toggle{color:#000;background-color:#3dd5f3;border-color:#25cff2}.btn-check:active+.btn-info:focus,.btn-check:checked+.btn-info:focus,.btn-info.active:focus,.btn-info:active:focus,.show>.btn-info.dropdown-toggle:focus{box-shadow:0 0 0 .25rem rgba(11,172,204,.5)}.btn-info.disabled,.btn-info:disabled{color:#000;background-color:#0dcaf0;border-color:#0dcaf0}.btn-warning{color:#000;background-color:#ffc107;border-color:#ffc107}.btn-warning:hover{color:#000;background-color:#ffca2c;border-color:#ffc720}.btn-check:focus+.btn-warning,.btn-warning:focus{color:#000;background-color:#ffca2c;border-color:#ffc720;box-shadow:0 0 0 .25rem rgba(217,164,6,.5)}.btn-check:active+.btn-warning,.btn-check:checked+.btn-warning,.btn-warning.active,.btn-warning:active,.show>.btn-warning.dropdown-toggle{color:#000;background-color:#ffcd39;border-color:#ffc720}.btn-check:active+.btn-warning:focus,.btn-check:checked+.btn-warning:focus,.btn-warning.active:focus,.btn-warning:active:focus,.show>.btn-warning.dropdown-toggle:focus{box-shadow:0 0 0 .25rem rgba(217,164,6,.5)}.btn-warning.disabled,.btn-warning:disabled{color:#000;background-color:#ffc107;border-color:#ffc107}.btn-danger{color:#fff;background-color:#dc3545;border-color:#dc3545}.btn-danger:hover{color:#fff;background-color:#bb2d3b;border-color:#b02a37}.btn-check:focus+.btn-danger,.btn-danger:focus{color:#fff;background-color:#bb2d3b;border-color:#b02a37;box-shadow:0 0 0 .25rem rgba(225,83,97,.5)}.btn-check:active+.btn-danger,.btn-check:checked+.btn-danger,.btn-danger.active,.btn-danger:active,.show>.btn-danger.dropdown-toggle{color:#fff;background-color:#b02a37;border-color:#a52834}.btn-check:active+.btn-danger:focus,.btn-check:checked+.btn-danger:focus,.btn-danger.active:focus,.btn-danger:active:focus,.show>.btn-danger.dropdown-toggle:focus{box-shadow:0 0 0 .25rem rgba(225,83,97,.5)}.btn-danger.disabled,.btn-danger:disabled{color:#fff;background-color:#dc3545;border-color:#dc3545}.btn-light{color:#000;background-color:#f8f9fa;border-color:#f8f9fa}.btn-light:hover{color:#000;background-color:#f9fafb;border-color:#f9fafb}.btn-check:focus+.btn-light,.btn-light:focus{color:#000;background-color:#f9fafb;border-color:#f9fafb;box-shadow:0 0 0 .25rem rgba(211,212,213,.5)}.btn-check:active+.btn-light,.btn-check:checked+.btn-light,.btn-light.active,.btn-light:active,.show>.btn-light.dropdown-toggle{color:#000;background-color:#f9fafb;border-color:#f9fafb}.btn-check:active+.btn-light:focus,.btn-check:checked+.btn-light:focus,.btn-light.active:focus,.btn-light:active:focus,.show>.btn-light.dropdown-toggle:focus{box-shadow:0 0 0 .25rem rgba(211,212,213,.5)}.btn-light.disabled,.btn-light:disabled{color:#000;background-color:#f8f9fa;border-color:#f8f9fa}.btn-dark{color:#fff;background-color:#212529;border-color:#212529}.btn-dark:hover{color:#fff;background-color:#1c1f23;border-color:#1a1e21}.btn-check:focus+.btn-dark,.btn-dark:focus{color:#fff;background-color:#1c1f23;border-color:#1a1e21;box-shadow:0 0 0 .25rem rgba(66,70,73,.5)}.btn-check:active+.btn-dark,.btn-check:checked+.btn-dark,.btn-dark.active,.btn-dark:active,.show>.btn-dark.dropdown-toggle{color:#fff;background-color:#1a1e21;border-color:#191c1f}.btn-check:active+.btn-dark:focus,.btn-check:checked+.btn-dark:focus,.btn-dark.active:focus,.btn-dark:active:focus,.show>.btn-dark.dropdown-toggle:focus{box-shadow:0 0 0 .25rem rgba(66,70,73,.5)}.btn-dark.disabled,.btn-dark:disabled{color:#fff;background-color:#212529;border-color:#212529}.btn-outline-primary{color:#0d6efd;border-color:#0d6efd}.btn-outline-primary:hover{color:#fff;background-color:#0d6efd;border-color:#0d6efd}.btn-check:focus+.btn-outline-primary,.btn-outline-primary:focus{box-shadow:0 0 0 .25rem rgba(13,110,253,.5)}.btn-check:active+.btn-outline-primary,.btn-check:checked+.btn-outline-primary,.btn-outline-primary.active,.btn-outline-primary.dropdown-toggle.show,.btn-outline-primary:active{color:#fff;background-color:#0d6efd;border-color:#0d6efd}.btn-check:active+.btn-outline-primary:focus,.btn-check:checked+.btn-outline-primary:focus,.btn-outline-primary.active:focus,.btn-outline-primary.dropdown-toggle.show:focus,.btn-outline-primary:active:focus{box-shadow:0 0 0 .25rem rgba(13,110,253,.5)}.btn-outline-primary.disabled,.btn-outline-primary:disabled{color:#0d6efd;background-color:transparent}.btn-outline-secondary{color:#6c757d;border-color:#6c757d}.btn-outline-secondary:hover{color:#fff;background-color:#6c757d;border-color:#6c757d}.btn-check:focus+.btn-outline-secondary,.btn-outline-secondary:focus{box-shadow:0 0 0 .25rem rgba(108,117,125,.5)}.btn-check:active+.btn-outline-secondary,.btn-check:checked+.btn-outline-secondary,.btn-outline-secondary.active,.btn-outline-secondary.dropdown-toggle.show,.btn-outline-secondary:active{color:#fff;background-color:#6c757d;border-color:#6c757d}.btn-check:active+.btn-outline-secondary:focus,.btn-check:checked+.btn-outline-secondary:focus,.btn-outline-secondary.active:focus,.btn-outline-secondary.dropdown-toggle.show:focus,.btn-outline-secondary:active:focus{box-shadow:0 0 0 .25rem rgba(108,117,125,.5)}.btn-outline-secondary.disabled,.btn-outline-secondary:disabled{color:#6c757d;background-color:transparent}.btn-outline-success{color:#198754;border-color:#198754}.btn-outline-success:hover{color:#fff;background-color:#198754;border-color:#198754}.btn-check:focus+.btn-outline-success,.btn-outline-success:focus{box-shadow:0 0 0 .25rem rgba(25,135,84,.5)}.btn-check:active+.btn-outline-success,.btn-check:checked+.btn-outline-success,.btn-outline-success.active,.btn-outline-success.dropdown-toggle.show,.btn-outline-success:active{color:#fff;background-color:#198754;border-color:#198754}.btn-check:active+.btn-outline-success:focus,.btn-check:checked+.btn-outline-success:focus,.btn-outline-success.active:focus,.btn-outline-success.dropdown-toggle.show:focus,.btn-outline-success:active:focus{box-shadow:0 0 0 .25rem rgba(25,135,84,.5)}.btn-outline-success.disabled,.btn-outline-success:disabled{color:#198754;background-color:transparent}.btn-outline-info{color:#0dcaf0;border-color:#0dcaf0}.btn-outline-info:hover{color:#000;background-color:#0dcaf0;border-color:#0dcaf0}.btn-check:focus+.btn-outline-info,.btn-outline-info:focus{box-shadow:0 0 0 .25rem rgba(13,202,240,.5)}.btn-check:active+.btn-outline-info,.btn-check:checked+.btn-outline-info,.btn-outline-info.active,.btn-outline-info.dropdown-toggle.show,.btn-outline-info:active{color:#000;background-color:#0dcaf0;border-color:#0dcaf0}.btn-check:active+.btn-outline-info:focus,.btn-check:checked+.btn-outline-info:focus,.btn-outline-info.active:focus,.btn-outline-info.dropdown-toggle.show:focus,.btn-outline-info:active:focus{box-shadow:0 0 0 .25rem rgba(13,202,240,.5)}.btn-outline-info.disabled,.btn-outline-info:disabled{color:#0dcaf0;background-color:transparent}.btn-outline-warning{color:#ffc107;border-color:#ffc107}.btn-outline-warning:hover{color:#000;background-color:#ffc107;border-color:#ffc107}.btn-check:focus+.btn-outline-warning,.btn-outline-warning:focus{box-shadow:0 0 0 .25rem rgba(255,193,7,.5)}.btn-check:active+.btn-outline-warning,.btn-check:checked+.btn-outline-warning,.btn-outline-warning.active,.btn-outline-warning.dropdown-toggle.show,.btn-outline-warning:active{color:#000;background-color:#ffc107;border-color:#ffc107}.btn-check:active+.btn-outline-warning:focus,.btn-check:checked+.btn-outline-warning:focus,.btn-outline-warning.active:focus,.btn-outline-warning.dropdown-toggle.show:focus,.btn-outline-warning:active:focus{box-shadow:0 0 0 .25rem rgba(255,193,7,.5)}.btn-outline-warning.disabled,.btn-outline-warning:disabled{color:#ffc107;background-color:transparent}.btn-outline-danger{color:#dc3545;border-color:#dc3545}.btn-outline-danger:hover{color:#fff;background-color:#dc3545;border-color:#dc3545}.btn-check:focus+.btn-outline-danger,.btn-outline-danger:focus{box-shadow:0 0 0 .25rem rgba(220,53,69,.5)}.btn-check:active+.btn-outline-danger,.btn-check:checked+.btn-outline-danger,.btn-outline-danger.active,.btn-outline-danger.dropdown-toggle.show,.btn-outline-danger:active{color:#fff;background-color:#dc3545;border-color:#dc3545}.btn-check:active+.btn-outline-danger:focus,.btn-check:checked+.btn-outline-danger:focus,.btn-outline-danger.active:focus,.btn-outline-danger.dropdown-toggle.show:focus,.btn-outline-danger:active:focus{box-shadow:0 0 0 .25rem rgba(220,53,69,.5)}.btn-outline-danger.disabled,.btn-outline-danger:disabled{color:#dc3545;background-color:transparent}.btn-outline-light{color:#f8f9fa;border-color:#f8f9fa}.btn-outline-light:hover{color:#000;background-color:#f8f9fa;border-color:#f8f9fa}.btn-check:focus+.btn-outline-light,.btn-outline-light:focus{box-shadow:0 0 0 .25rem rgba(248,249,250,.5)}.btn-check:active+.btn-outline-light,.btn-check:checked+.btn-outline-light,.btn-outline-light.active,.btn-outline-light.dropdown-toggle.show,.btn-outline-light:active{color:#000;background-color:#f8f9fa;border-color:#f8f9fa}.btn-check:active+.btn-outline-light:focus,.btn-check:checked+.btn-outline-light:focus,.btn-outline-light.active:focus,.btn-outline-light.dropdown-toggle.show:focus,.btn-outline-light:active:focus{box-shadow:0 0 0 .25rem rgba(248,249,250,.5)}.btn-outline-light.disabled,.btn-outline-light:disabled{color:#f8f9fa;background-color:transparent}.btn-outline-dark{color:#212529;border-color:#212529}.btn-outline-dark:hover{color:#fff;background-color:#212529;border-color:#212529}.btn-check:focus+.btn-outline-dark,.btn-outline-dark:focus{box-shadow:0 0 0 .25rem rgba(33,37,41,.5)}.btn-check:active+.btn-outline-dark,.btn-check:checked+.btn-outline-dark,.btn-outline-dark.active,.btn-outline-dark.dropdown-toggle.show,.btn-outline-dark:active{color:#fff;background-color:#212529;border-color:#212529}.btn-check:active+.btn-outline-dark:focus,.btn-check:checked+.btn-outline-dark:focus,.btn-outline-dark.active:focus,.btn-outline-dark.dropdown-toggle.show:focus,.btn-outline-dark:active:focus{box-shadow:0 0 0 .25rem rgba(33,37,41,.5)}.btn-outline-dark.disabled,.btn-outline-dark:disabled{color:#212529;background-color:transparent}.btn-link{font-weight:400;color:#0d6efd;text-decoration:underline}.btn-link:hover{color:#0a58ca}.btn-link.disabled,.btn-link:disabled{color:#6c757d}.btn-group-lg>.btn,.btn-lg{padding:.5rem 1rem;font-size:1.25rem;border-radius:.3rem}.btn-group-sm>.btn,.btn-sm{padding:.25rem .5rem;font-size:.875rem;border-radius:.2rem}.fade{transition:opacity .15s linear}@media (prefers-reduced-motion:reduce){.fade{transition:none}}.fade:not(.show){opacity:0}.collapse:not(.show){display:none}.collapsing{height:0;overflow:hidden;transition:height .35s ease}@media (prefers-reduced-motion:reduce){.collapsing{transition:none}}.collapsing.collapse-horizontal{width:0;height:auto;transition:width .35s ease}@media (prefers-reduced-motion:reduce){.collapsing.collapse-horizontal{transition:none}}.dropdown,.dropend,.dropstart,.dropup{position:relative}.dropdown-toggle{white-space:nowrap}.dropdown-toggle::after{display:inline-block;margin-left:.255em;vertical-align:.255em;content:"";border-top:.3em solid;border-right:.3em solid transparent;border-bottom:0;border-left:.3em solid transparent}.dropdown-toggle:empty::after{margin-left:0}.dropdown-menu{position:absolute;z-index:1000;display:none;min-width:10rem;padding:.5rem 0;margin:0;font-size:1rem;color:#212529;text-align:left;list-style:none;background-color:#fff;background-clip:padding-box;border:1px solid rgba(0,0,0,.15);border-radius:.25rem}.dropdown-menu[data-bs-popper]{top:100%;left:0;margin-top:.125rem}.dropdown-menu-start{--bs-position:start}.dropdown-menu-start[data-bs-popper]{right:auto;left:0}.dropdown-menu-end{--bs-position:end}.dropdown-menu-end[data-bs-popper]{right:0;left:auto}@media (min-width:576px){.dropdown-menu-sm-start{--bs-position:start}.dropdown-menu-sm-start[data-bs-popper]{right:auto;left:0}.dropdown-menu-sm-end{--bs-position:end}.dropdown-menu-sm-end[data-bs-popper]{right:0;left:auto}}@media (min-width:768px){.dropdown-menu-md-start{--bs-position:start}.dropdown-menu-md-start[data-bs-popper]{right:auto;left:0}.dropdown-menu-md-end{--bs-position:end}.dropdown-menu-md-end[data-bs-popper]{right:0;left:auto}}@media (min-width:992px){.dropdown-menu-lg-start{--bs-position:start}.dropdown-menu-lg-start[data-bs-popper]{right:auto;left:0}.dropdown-menu-lg-end{--bs-position:end}.dropdown-menu-lg-end[data-bs-popper]{right:0;left:auto}}@media (min-width:1200px){.dropdown-menu-xl-start{--bs-position:start}.dropdown-menu-xl-start[data-bs-popper]{right:auto;left:0}.dropdown-menu-xl-end{--bs-position:end}.dropdown-menu-xl-end[data-bs-popper]{right:0;left:auto}}@media (min-width:1400px){.dropdown-menu-xxl-start{--bs-position:start}.dropdown-menu-xxl-start[data-bs-popper]{right:auto;left:0}.dropdown-menu-xxl-end{--bs-position:end}.dropdown-menu-xxl-end[data-bs-popper]{right:0;left:auto}}.dropup .dropdown-menu[data-bs-popper]{top:auto;bottom:100%;margin-top:0;margin-bottom:.125rem}.dropup .dropdown-toggle::after{display:inline-block;margin-left:.255em;vertical-align:.255em;content:"";border-top:0;border-right:.3em solid transparent;border-bottom:.3em solid;border-left:.3em solid transparent}.dropup .dropdown-toggle:empty::after{margin-left:0}.dropend .dropdown-menu[data-bs-popper]{top:0;right:auto;left:100%;margin-top:0;margin-left:.125rem}.dropend .dropdown-toggle::after{display:inline-block;margin-left:.255em;vertical-align:.255em;content:"";border-top:.3em solid transparent;border-right:0;border-bottom:.3em solid transparent;border-left:.3em solid}.dropend .dropdown-toggle:empty::after{margin-left:0}.dropend .dropdown-toggle::after{vertical-align:0}.dropstart .dropdown-menu[data-bs-popper]{top:0;right:100%;left:auto;margin-top:0;margin-right:.125rem}.dropstart .dropdown-toggle::after{display:inline-block;margin-left:.255em;vertical-align:.255em;content:""}.dropstart .dropdown-toggle::after{display:none}.dropstart .dropdown-toggle::before{display:inline-block;margin-right:.255em;vertical-align:.255em;content:"";border-top:.3em solid transparent;border-right:.3em solid;border-bottom:.3em solid transparent}.dropstart .dropdown-toggle:empty::after{margin-left:0}.dropstart .dropdown-toggle::before{vertical-align:0}.dropdown-divider{height:0;margin:.5rem 0;overflow:hidden;border-top:1px solid rgba(0,0,0,.15)}.dropdown-item{display:block;width:100%;padding:.25rem 1rem;clear:both;font-weight:400;color:#212529;text-align:inherit;text-decoration:none;white-space:nowrap;background-color:transparent;border:0}.dropdown-item:focus,.dropdown-item:hover{color:#1e2125;background-color:#e9ecef}.dropdown-item.active,.dropdown-item:active{color:#fff;text-decoration:none;background-color:#0d6efd}.dropdown-item.disabled,.dropdown-item:disabled{color:#adb5bd;pointer-events:none;background-color:transparent}.dropdown-menu.show{display:block}.dropdown-header{display:block;padding:.5rem 1rem;margin-bottom:0;font-size:.875rem;color:#6c757d;white-space:nowrap}.dropdown-item-text{display:block;padding:.25rem 1rem;color:#212529}.dropdown-menu-dark{color:#dee2e6;background-color:#343a40;border-color:rgba(0,0,0,.15)}.dropdown-menu-dark .dropdown-item{color:#dee2e6}.dropdown-menu-dark .dropdown-item:focus,.dropdown-menu-dark .dropdown-item:hover{color:#fff;background-color:rgba(255,255,255,.15)}.dropdown-menu-dark .dropdown-item.active,.dropdown-menu-dark .dropdown-item:active{color:#fff;background-color:#0d6efd}.dropdown-menu-dark .dropdown-item.disabled,.dropdown-menu-dark .dropdown-item:disabled{color:#adb5bd}.dropdown-menu-dark .dropdown-divider{border-color:rgba(0,0,0,.15)}.dropdown-menu-dark .dropdown-item-text{color:#dee2e6}.dropdown-menu-dark .dropdown-header{color:#adb5bd}.btn-group,.btn-group-vertical{position:relative;display:inline-flex;vertical-align:middle}.btn-group-vertical>.btn,.btn-group>.btn{position:relative;flex:1 1 auto}.btn-group-vertical>.btn-check:checked+.btn,.btn-group-vertical>.btn-check:focus+.btn,.btn-group-vertical>.btn.active,.btn-group-vertical>.btn:active,.btn-group-vertical>.btn:focus,.btn-group-vertical>.btn:hover,.btn-group>.btn-check:checked+.btn,.btn-group>.btn-check:focus+.btn,.btn-group>.btn.active,.btn-group>.btn:active,.btn-group>.btn:focus,.btn-group>.btn:hover{z-index:1}.btn-toolbar{display:flex;flex-wrap:wrap;justify-content:flex-start}.btn-toolbar .input-group{width:auto}.btn-group>.btn-group:not(:first-child),.btn-group>.btn:not(:first-child){margin-left:-1px}.btn-group>.btn-group:not(:last-child)>.btn,.btn-group>.btn:not(:last-child):not(.dropdown-toggle){border-top-right-radius:0;border-bottom-right-radius:0}.btn-group>.btn-group:not(:first-child)>.btn,.btn-group>.btn:nth-child(n+3),.btn-group>:not(.btn-check)+.btn{border-top-left-radius:0;border-bottom-left-radius:0}.dropdown-toggle-split{padding-right:.5625rem;padding-left:.5625rem}.dropdown-toggle-split::after,.dropend .dropdown-toggle-split::after,.dropup .dropdown-toggle-split::after{margin-left:0}.dropstart .dropdown-toggle-split::before{margin-right:0}.btn-group-sm>.btn+.dropdown-toggle-split,.btn-sm+.dropdown-toggle-split{padding-right:.375rem;padding-left:.375rem}.btn-group-lg>.btn+.dropdown-toggle-split,.btn-lg+.dropdown-toggle-split{padding-right:.75rem;padding-left:.75rem}.btn-group-vertical{flex-direction:column;align-items:flex-start;justify-content:center}.btn-group-vertical>.btn,.btn-group-vertical>.btn-group{width:100%}.btn-group-vertical>.btn-group:not(:first-child),.btn-group-vertical>.btn:not(:first-child){margin-top:-1px}.btn-group-vertical>.btn-group:not(:last-child)>.btn,.btn-group-vertical>.btn:not(:last-child):not(.dropdown-toggle){border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn-group:not(:first-child)>.btn,.btn-group-vertical>.btn~.btn{border-top-left-radius:0;border-top-right-radius:0}.nav{display:flex;flex-wrap:wrap;padding-left:0;margin-bottom:0;list-style:none}.nav-link{display:block;padding:.5rem 1rem;color:#0d6efd;text-decoration:none;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out}@media (prefers-reduced-motion:reduce){.nav-link{transition:none}}.nav-link:focus,.nav-link:hover{color:#0a58ca}.nav-link.disabled{color:#6c757d;pointer-events:none;cursor:default}.nav-tabs{border-bottom:1px solid #dee2e6}.nav-tabs .nav-link{margin-bottom:-1px;background:0 0;border:1px solid transparent;border-top-left-radius:.25rem;border-top-right-radius:.25rem}.nav-tabs .nav-link:focus,.nav-tabs .nav-link:hover{border-color:#e9ecef #e9ecef #dee2e6;isolation:isolate}.nav-tabs .nav-link.disabled{color:#6c757d;background-color:transparent;border-color:transparent}.nav-tabs .nav-item.show .nav-link,.nav-tabs .nav-link.active{color:#495057;background-color:#fff;border-color:#dee2e6 #dee2e6 #fff}.nav-tabs .dropdown-menu{margin-top:-1px;border-top-left-radius:0;border-top-right-radius:0}.nav-pills .nav-link{background:0 0;border:0;border-radius:.25rem}.nav-pills .nav-link.active,.nav-pills .show>.nav-link{color:#fff;background-color:#0d6efd}.nav-fill .nav-item,.nav-fill>.nav-link{flex:1 1 auto;text-align:center}.nav-justified .nav-item,.nav-justified>.nav-link{flex-basis:0;flex-grow:1;text-align:center}.nav-fill .nav-item .nav-link,.nav-justified .nav-item .nav-link{width:100%}.tab-content>.tab-pane{display:none}.tab-content>.active{display:block}.navbar{position:relative;display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;padding-top:.5rem;padding-bottom:.5rem}.navbar>.container,.navbar>.container-fluid,.navbar>.container-lg,.navbar>.container-md,.navbar>.container-sm,.navbar>.container-xl,.navbar>.container-xxl{display:flex;flex-wrap:inherit;align-items:center;justify-content:space-between}.navbar-brand{padding-top:.3125rem;padding-bottom:.3125rem;margin-right:1rem;font-size:1.25rem;text-decoration:none;white-space:nowrap}.navbar-nav{display:flex;flex-direction:column;padding-left:0;margin-bottom:0;list-style:none}.navbar-nav .nav-link{padding-right:0;padding-left:0}.navbar-nav .dropdown-menu{position:static}.navbar-text{padding-top:.5rem;padding-bottom:.5rem}.navbar-collapse{flex-basis:100%;flex-grow:1;align-items:center}.navbar-toggler{padding:.25rem .75rem;font-size:1.25rem;line-height:1;background-color:transparent;border:1px solid transparent;border-radius:.25rem;transition:box-shadow .15s ease-in-out}@media (prefers-reduced-motion:reduce){.navbar-toggler{transition:none}}.navbar-toggler:hover{text-decoration:none}.navbar-toggler:focus{text-decoration:none;outline:0;box-shadow:0 0 0 .25rem}.navbar-toggler-icon{display:inline-block;width:1.5em;height:1.5em;vertical-align:middle;background-repeat:no-repeat;background-position:center;background-size:100%}.navbar-nav-scroll{max-height:var(--bs-scroll-height,75vh);overflow-y:auto}@media (min-width:576px){.navbar-expand-sm{flex-wrap:nowrap;justify-content:flex-start}.navbar-expand-sm .navbar-nav{flex-direction:row}.navbar-expand-sm .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-sm .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.navbar-expand-sm .navbar-nav-scroll{overflow:visible}.navbar-expand-sm .navbar-collapse{display:flex!important;flex-basis:auto}.navbar-expand-sm .navbar-toggler{display:none}.navbar-expand-sm .offcanvas-header{display:none}.navbar-expand-sm .offcanvas{position:inherit;bottom:0;z-index:1000;flex-grow:1;visibility:visible!important;background-color:transparent;border-right:0;border-left:0;transition:none;transform:none}.navbar-expand-sm .offcanvas-bottom,.navbar-expand-sm .offcanvas-top{height:auto;border-top:0;border-bottom:0}.navbar-expand-sm .offcanvas-body{display:flex;flex-grow:0;padding:0;overflow-y:visible}}@media (min-width:768px){.navbar-expand-md{flex-wrap:nowrap;justify-content:flex-start}.navbar-expand-md .navbar-nav{flex-direction:row}.navbar-expand-md .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-md .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.navbar-expand-md .navbar-nav-scroll{overflow:visible}.navbar-expand-md .navbar-collapse{display:flex!important;flex-basis:auto}.navbar-expand-md .navbar-toggler{display:none}.navbar-expand-md .offcanvas-header{display:none}.navbar-expand-md .offcanvas{position:inherit;bottom:0;z-index:1000;flex-grow:1;visibility:visible!important;background-color:transparent;border-right:0;border-left:0;transition:none;transform:none}.navbar-expand-md .offcanvas-bottom,.navbar-expand-md .offcanvas-top{height:auto;border-top:0;border-bottom:0}.navbar-expand-md .offcanvas-body{display:flex;flex-grow:0;padding:0;overflow-y:visible}}@media (min-width:992px){.navbar-expand-lg{flex-wrap:nowrap;justify-content:flex-start}.navbar-expand-lg .navbar-nav{flex-direction:row}.navbar-expand-lg .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-lg .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.navbar-expand-lg .navbar-nav-scroll{overflow:visible}.navbar-expand-lg .navbar-collapse{display:flex!important;flex-basis:auto}.navbar-expand-lg .navbar-toggler{display:none}.navbar-expand-lg .offcanvas-header{display:none}.navbar-expand-lg .offcanvas{position:inherit;bottom:0;z-index:1000;flex-grow:1;visibility:visible!important;background-color:transparent;border-right:0;border-left:0;transition:none;transform:none}.navbar-expand-lg .offcanvas-bottom,.navbar-expand-lg .offcanvas-top{height:auto;border-top:0;border-bottom:0}.navbar-expand-lg .offcanvas-body{display:flex;flex-grow:0;padding:0;overflow-y:visible}}@media (min-width:1200px){.navbar-expand-xl{flex-wrap:nowrap;justify-content:flex-start}.navbar-expand-xl .navbar-nav{flex-direction:row}.navbar-expand-xl .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-xl .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.navbar-expand-xl .navbar-nav-scroll{overflow:visible}.navbar-expand-xl .navbar-collapse{display:flex!important;flex-basis:auto}.navbar-expand-xl .navbar-toggler{display:none}.navbar-expand-xl .offcanvas-header{display:none}.navbar-expand-xl .offcanvas{position:inherit;bottom:0;z-index:1000;flex-grow:1;visibility:visible!important;background-color:transparent;border-right:0;border-left:0;transition:none;transform:none}.navbar-expand-xl .offcanvas-bottom,.navbar-expand-xl .offcanvas-top{height:auto;border-top:0;border-bottom:0}.navbar-expand-xl .offcanvas-body{display:flex;flex-grow:0;padding:0;overflow-y:visible}}@media (min-width:1400px){.navbar-expand-xxl{flex-wrap:nowrap;justify-content:flex-start}.navbar-expand-xxl .navbar-nav{flex-direction:row}.navbar-expand-xxl .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-xxl .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.navbar-expand-xxl .navbar-nav-scroll{overflow:visible}.navbar-expand-xxl .navbar-collapse{display:flex!important;flex-basis:auto}.navbar-expand-xxl .navbar-toggler{display:none}.navbar-expand-xxl .offcanvas-header{display:none}.navbar-expand-xxl .offcanvas{position:inherit;bottom:0;z-index:1000;flex-grow:1;visibility:visible!important;background-color:transparent;border-right:0;border-left:0;transition:none;transform:none}.navbar-expand-xxl .offcanvas-bottom,.navbar-expand-xxl .offcanvas-top{height:auto;border-top:0;border-bottom:0}.navbar-expand-xxl .offcanvas-body{display:flex;flex-grow:0;padding:0;overflow-y:visible}}.navbar-expand{flex-wrap:nowrap;justify-content:flex-start}.navbar-expand .navbar-nav{flex-direction:row}.navbar-expand .navbar-nav .dropdown-menu{position:absolute}.navbar-expand .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.navbar-expand .navbar-nav-scroll{overflow:visible}.navbar-expand .navbar-collapse{display:flex!important;flex-basis:auto}.navbar-expand .navbar-toggler{display:none}.navbar-expand .offcanvas-header{display:none}.navbar-expand .offcanvas{position:inherit;bottom:0;z-index:1000;flex-grow:1;visibility:visible!important;background-color:transparent;border-right:0;border-left:0;transition:none;transform:none}.navbar-expand .offcanvas-bottom,.navbar-expand .offcanvas-top{height:auto;border-top:0;border-bottom:0}.navbar-expand .offcanvas-body{display:flex;flex-grow:0;padding:0;overflow-y:visible}.navbar-light .navbar-brand{color:rgba(0,0,0,.9)}.navbar-light .navbar-brand:focus,.navbar-light .navbar-brand:hover{color:rgba(0,0,0,.9)}.navbar-light .navbar-nav .nav-link{color:rgba(0,0,0,.55)}.navbar-light .navbar-nav .nav-link:focus,.navbar-light .navbar-nav .nav-link:hover{color:rgba(0,0,0,.7)}.navbar-light .navbar-nav .nav-link.disabled{color:rgba(0,0,0,.3)}.navbar-light .navbar-nav .nav-link.active,.navbar-light .navbar-nav .show>.nav-link{color:rgba(0,0,0,.9)}.navbar-light .navbar-toggler{color:rgba(0,0,0,.55);border-color:rgba(0,0,0,.1)}.navbar-light .navbar-toggler-icon{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 30 30'%3e%3cpath stroke='rgba%280, 0, 0, 0.55%29' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e")}.navbar-light .navbar-text{color:rgba(0,0,0,.55)}.navbar-light .navbar-text a,.navbar-light .navbar-text a:focus,.navbar-light .navbar-text a:hover{color:rgba(0,0,0,.9)}.navbar-dark .navbar-brand{color:#fff}.navbar-dark .navbar-brand:focus,.navbar-dark .navbar-brand:hover{color:#fff}.navbar-dark .navbar-nav .nav-link{color:rgba(255,255,255,.55)}.navbar-dark .navbar-nav .nav-link:focus,.navbar-dark .navbar-nav .nav-link:hover{color:rgba(255,255,255,.75)}.navbar-dark .navbar-nav .nav-link.disabled{color:rgba(255,255,255,.25)}.navbar-dark .navbar-nav .nav-link.active,.navbar-dark .navbar-nav .show>.nav-link{color:#fff}.navbar-dark .navbar-toggler{color:rgba(255,255,255,.55);border-color:rgba(255,255,255,.1)}.navbar-dark .navbar-toggler-icon{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 30 30'%3e%3cpath stroke='rgba%28255, 255, 255, 0.55%29' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e")}.navbar-dark .navbar-text{color:rgba(255,255,255,.55)}.navbar-dark .navbar-text a,.navbar-dark .navbar-text a:focus,.navbar-dark .navbar-text a:hover{color:#fff}.card{position:relative;display:flex;flex-direction:column;min-width:0;word-wrap:break-word;background-color:#fff;background-clip:border-box;border:1px solid rgba(0,0,0,.125);border-radius:.25rem}.card>hr{margin-right:0;margin-left:0}.card>.list-group{border-top:inherit;border-bottom:inherit}.card>.list-group:first-child{border-top-width:0;border-top-left-radius:calc(.25rem - 1px);border-top-right-radius:calc(.25rem - 1px)}.card>.list-group:last-child{border-bottom-width:0;border-bottom-right-radius:calc(.25rem - 1px);border-bottom-left-radius:calc(.25rem - 1px)}.card>.card-header+.list-group,.card>.list-group+.card-footer{border-top:0}.card-body{flex:1 1 auto;padding:1rem 1rem}.card-title{margin-bottom:.5rem}.card-subtitle{margin-top:-.25rem;margin-bottom:0}.card-text:last-child{margin-bottom:0}.card-link+.card-link{margin-left:1rem}.card-header{padding:.5rem 1rem;margin-bottom:0;background-color:rgba(0,0,0,.03);border-bottom:1px solid rgba(0,0,0,.125)}.card-header:first-child{border-radius:calc(.25rem - 1px) calc(.25rem - 1px) 0 0}.card-footer{padding:.5rem 1rem;background-color:rgba(0,0,0,.03);border-top:1px solid rgba(0,0,0,.125)}.card-footer:last-child{border-radius:0 0 calc(.25rem - 1px) calc(.25rem - 1px)}.card-header-tabs{margin-right:-.5rem;margin-bottom:-.5rem;margin-left:-.5rem;border-bottom:0}.card-header-pills{margin-right:-.5rem;margin-left:-.5rem}.card-img-overlay{position:absolute;top:0;right:0;bottom:0;left:0;padding:1rem;border-radius:calc(.25rem - 1px)}.card-img,.card-img-bottom,.card-img-top{width:100%}.card-img,.card-img-top{border-top-left-radius:calc(.25rem - 1px);border-top-right-radius:calc(.25rem - 1px)}.card-img,.card-img-bottom{border-bottom-right-radius:calc(.25rem - 1px);border-bottom-left-radius:calc(.25rem - 1px)}.card-group>.card{margin-bottom:.75rem}@media (min-width:576px){.card-group{display:flex;flex-flow:row wrap}.card-group>.card{flex:1 0 0%;margin-bottom:0}.card-group>.card+.card{margin-left:0;border-left:0}.card-group>.card:not(:last-child){border-top-right-radius:0;border-bottom-right-radius:0}.card-group>.card:not(:last-child) .card-header,.card-group>.card:not(:last-child) .card-img-top{border-top-right-radius:0}.card-group>.card:not(:last-child) .card-footer,.card-group>.card:not(:last-child) .card-img-bottom{border-bottom-right-radius:0}.card-group>.card:not(:first-child){border-top-left-radius:0;border-bottom-left-radius:0}.card-group>.card:not(:first-child) .card-header,.card-group>.card:not(:first-child) .card-img-top{border-top-left-radius:0}.card-group>.card:not(:first-child) .card-footer,.card-group>.card:not(:first-child) .card-img-bottom{border-bottom-left-radius:0}}.accordion-button{position:relative;display:flex;align-items:center;width:100%;padding:1rem 1.25rem;font-size:1rem;color:#212529;text-align:left;background-color:#fff;border:0;border-radius:0;overflow-anchor:none;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out,border-radius .15s ease}@media (prefers-reduced-motion:reduce){.accordion-button{transition:none}}.accordion-button:not(.collapsed){color:#0c63e4;background-color:#e7f1ff;box-shadow:inset 0 -1px 0 rgba(0,0,0,.125)}.accordion-button:not(.collapsed)::after{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%230c63e4'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e");transform:rotate(-180deg)}.accordion-button::after{flex-shrink:0;width:1.25rem;height:1.25rem;margin-left:auto;content:"";background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23212529'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e");background-repeat:no-repeat;background-size:1.25rem;transition:transform .2s ease-in-out}@media (prefers-reduced-motion:reduce){.accordion-button::after{transition:none}}.accordion-button:hover{z-index:2}.accordion-button:focus{z-index:3;border-color:#86b7fe;outline:0;box-shadow:0 0 0 .25rem rgba(13,110,253,.25)}.accordion-header{margin-bottom:0}.accordion-item{background-color:#fff;border:1px solid rgba(0,0,0,.125)}.accordion-item:first-of-type{border-top-left-radius:.25rem;border-top-right-radius:.25rem}.accordion-item:first-of-type .accordion-button{border-top-left-radius:calc(.25rem - 1px);border-top-right-radius:calc(.25rem - 1px)}.accordion-item:not(:first-of-type){border-top:0}.accordion-item:last-of-type{border-bottom-right-radius:.25rem;border-bottom-left-radius:.25rem}.accordion-item:last-of-type .accordion-button.collapsed{border-bottom-right-radius:calc(.25rem - 1px);border-bottom-left-radius:calc(.25rem - 1px)}.accordion-item:last-of-type .accordion-collapse{border-bottom-right-radius:.25rem;border-bottom-left-radius:.25rem}.accordion-body{padding:1rem 1.25rem}.accordion-flush .accordion-collapse{border-width:0}.accordion-flush .accordion-item{border-right:0;border-left:0;border-radius:0}.accordion-flush .accordion-item:first-child{border-top:0}.accordion-flush .accordion-item:last-child{border-bottom:0}.accordion-flush .accordion-item .accordion-button{border-radius:0}.breadcrumb{display:flex;flex-wrap:wrap;padding:0 0;margin-bottom:1rem;list-style:none}.breadcrumb-item+.breadcrumb-item{padding-left:.5rem}.breadcrumb-item+.breadcrumb-item::before{float:left;padding-right:.5rem;color:#6c757d;content:var(--bs-breadcrumb-divider, "/")}.breadcrumb-item.active{color:#6c757d}.pagination{display:flex;padding-left:0;list-style:none}.page-link{position:relative;display:block;color:#0d6efd;text-decoration:none;background-color:#fff;border:1px solid #dee2e6;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media (prefers-reduced-motion:reduce){.page-link{transition:none}}.page-link:hover{z-index:2;color:#0a58ca;background-color:#e9ecef;border-color:#dee2e6}.page-link:focus{z-index:3;color:#0a58ca;background-color:#e9ecef;outline:0;box-shadow:0 0 0 .25rem rgba(13,110,253,.25)}.page-item:not(:first-child) .page-link{margin-left:-1px}.page-item.active .page-link{z-index:3;color:#fff;background-color:#0d6efd;border-color:#0d6efd}.page-item.disabled .page-link{color:#6c757d;pointer-events:none;background-color:#fff;border-color:#dee2e6}.page-link{padding:.375rem .75rem}.page-item:first-child .page-link{border-top-left-radius:.25rem;border-bottom-left-radius:.25rem}.page-item:last-child .page-link{border-top-right-radius:.25rem;border-bottom-right-radius:.25rem}.pagination-lg .page-link{padding:.75rem 1.5rem;font-size:1.25rem}.pagination-lg .page-item:first-child .page-link{border-top-left-radius:.3rem;border-bottom-left-radius:.3rem}.pagination-lg .page-item:last-child .page-link{border-top-right-radius:.3rem;border-bottom-right-radius:.3rem}.pagination-sm .page-link{padding:.25rem .5rem;font-size:.875rem}.pagination-sm .page-item:first-child .page-link{border-top-left-radius:.2rem;border-bottom-left-radius:.2rem}.pagination-sm .page-item:last-child .page-link{border-top-right-radius:.2rem;border-bottom-right-radius:.2rem}.badge{display:inline-block;padding:.35em .65em;font-size:.75em;font-weight:700;line-height:1;color:#fff;text-align:center;white-space:nowrap;vertical-align:baseline;border-radius:.25rem}.badge:empty{display:none}.btn .badge{position:relative;top:-1px}.alert{position:relative;padding:1rem 1rem;margin-bottom:1rem;border:1px solid transparent;border-radius:.25rem}.alert-heading{color:inherit}.alert-link{font-weight:700}.alert-dismissible{padding-right:3rem}.alert-dismissible .btn-close{position:absolute;top:0;right:0;z-index:2;padding:1.25rem 1rem}.alert-primary{color:#084298;background-color:#cfe2ff;border-color:#b6d4fe}.alert-primary .alert-link{color:#06357a}.alert-secondary{color:#41464b;background-color:#e2e3e5;border-color:#d3d6d8}.alert-secondary .alert-link{color:#34383c}.alert-success{color:#0f5132;background-color:#d1e7dd;border-color:#badbcc}.alert-success .alert-link{color:#0c4128}.alert-info{color:#055160;background-color:#cff4fc;border-color:#b6effb}.alert-info .alert-link{color:#04414d}.alert-warning{color:#664d03;background-color:#fff3cd;border-color:#ffecb5}.alert-warning .alert-link{color:#523e02}.alert-danger{color:#842029;background-color:#f8d7da;border-color:#f5c2c7}.alert-danger .alert-link{color:#6a1a21}.alert-light{color:#636464;background-color:#fefefe;border-color:#fdfdfe}.alert-light .alert-link{color:#4f5050}.alert-dark{color:#141619;background-color:#d3d3d4;border-color:#bcbebf}.alert-dark .alert-link{color:#101214}@-webkit-keyframes progress-bar-stripes{0%{background-position-x:1rem}}@keyframes progress-bar-stripes{0%{background-position-x:1rem}}.progress{display:flex;height:1rem;overflow:hidden;font-size:.75rem;background-color:#e9ecef;border-radius:.25rem}.progress-bar{display:flex;flex-direction:column;justify-content:center;overflow:hidden;color:#fff;text-align:center;white-space:nowrap;background-color:#0d6efd;transition:width .6s ease}@media (prefers-reduced-motion:reduce){.progress-bar{transition:none}}.progress-bar-striped{background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-size:1rem 1rem}.progress-bar-animated{-webkit-animation:1s linear infinite progress-bar-stripes;animation:1s linear infinite progress-bar-stripes}@media (prefers-reduced-motion:reduce){.progress-bar-animated{-webkit-animation:none;animation:none}}.list-group{display:flex;flex-direction:column;padding-left:0;margin-bottom:0;border-radius:.25rem}.list-group-numbered{list-style-type:none;counter-reset:section}.list-group-numbered>li::before{content:counters(section, ".") ". ";counter-increment:section}.list-group-item-action{width:100%;color:#495057;text-align:inherit}.list-group-item-action:focus,.list-group-item-action:hover{z-index:1;color:#495057;text-decoration:none;background-color:#f8f9fa}.list-group-item-action:active{color:#212529;background-color:#e9ecef}.list-group-item{position:relative;display:block;padding:.5rem 1rem;color:#212529;text-decoration:none;background-color:#fff;border:1px solid rgba(0,0,0,.125)}.list-group-item:first-child{border-top-left-radius:inherit;border-top-right-radius:inherit}.list-group-item:last-child{border-bottom-right-radius:inherit;border-bottom-left-radius:inherit}.list-group-item.disabled,.list-group-item:disabled{color:#6c757d;pointer-events:none;background-color:#fff}.list-group-item.active{z-index:2;color:#fff;background-color:#0d6efd;border-color:#0d6efd}.list-group-item+.list-group-item{border-top-width:0}.list-group-item+.list-group-item.active{margin-top:-1px;border-top-width:1px}.list-group-horizontal{flex-direction:row}.list-group-horizontal>.list-group-item:first-child{border-bottom-left-radius:.25rem;border-top-right-radius:0}.list-group-horizontal>.list-group-item:last-child{border-top-right-radius:.25rem;border-bottom-left-radius:0}.list-group-horizontal>.list-group-item.active{margin-top:0}.list-group-horizontal>.list-group-item+.list-group-item{border-top-width:1px;border-left-width:0}.list-group-horizontal>.list-group-item+.list-group-item.active{margin-left:-1px;border-left-width:1px}@media (min-width:576px){.list-group-horizontal-sm{flex-direction:row}.list-group-horizontal-sm>.list-group-item:first-child{border-bottom-left-radius:.25rem;border-top-right-radius:0}.list-group-horizontal-sm>.list-group-item:last-child{border-top-right-radius:.25rem;border-bottom-left-radius:0}.list-group-horizontal-sm>.list-group-item.active{margin-top:0}.list-group-horizontal-sm>.list-group-item+.list-group-item{border-top-width:1px;border-left-width:0}.list-group-horizontal-sm>.list-group-item+.list-group-item.active{margin-left:-1px;border-left-width:1px}}@media (min-width:768px){.list-group-horizontal-md{flex-direction:row}.list-group-horizontal-md>.list-group-item:first-child{border-bottom-left-radius:.25rem;border-top-right-radius:0}.list-group-horizontal-md>.list-group-item:last-child{border-top-right-radius:.25rem;border-bottom-left-radius:0}.list-group-horizontal-md>.list-group-item.active{margin-top:0}.list-group-horizontal-md>.list-group-item+.list-group-item{border-top-width:1px;border-left-width:0}.list-group-horizontal-md>.list-group-item+.list-group-item.active{margin-left:-1px;border-left-width:1px}}@media (min-width:992px){.list-group-horizontal-lg{flex-direction:row}.list-group-horizontal-lg>.list-group-item:first-child{border-bottom-left-radius:.25rem;border-top-right-radius:0}.list-group-horizontal-lg>.list-group-item:last-child{border-top-right-radius:.25rem;border-bottom-left-radius:0}.list-group-horizontal-lg>.list-group-item.active{margin-top:0}.list-group-horizontal-lg>.list-group-item+.list-group-item{border-top-width:1px;border-left-width:0}.list-group-horizontal-lg>.list-group-item+.list-group-item.active{margin-left:-1px;border-left-width:1px}}@media (min-width:1200px){.list-group-horizontal-xl{flex-direction:row}.list-group-horizontal-xl>.list-group-item:first-child{border-bottom-left-radius:.25rem;border-top-right-radius:0}.list-group-horizontal-xl>.list-group-item:last-child{border-top-right-radius:.25rem;border-bottom-left-radius:0}.list-group-horizontal-xl>.list-group-item.active{margin-top:0}.list-group-horizontal-xl>.list-group-item+.list-group-item{border-top-width:1px;border-left-width:0}.list-group-horizontal-xl>.list-group-item+.list-group-item.active{margin-left:-1px;border-left-width:1px}}@media (min-width:1400px){.list-group-horizontal-xxl{flex-direction:row}.list-group-horizontal-xxl>.list-group-item:first-child{border-bottom-left-radius:.25rem;border-top-right-radius:0}.list-group-horizontal-xxl>.list-group-item:last-child{border-top-right-radius:.25rem;border-bottom-left-radius:0}.list-group-horizontal-xxl>.list-group-item.active{margin-top:0}.list-group-horizontal-xxl>.list-group-item+.list-group-item{border-top-width:1px;border-left-width:0}.list-group-horizontal-xxl>.list-group-item+.list-group-item.active{margin-left:-1px;border-left-width:1px}}.list-group-flush{border-radius:0}.list-group-flush>.list-group-item{border-width:0 0 1px}.list-group-flush>.list-group-item:last-child{border-bottom-width:0}.list-group-item-primary{color:#084298;background-color:#cfe2ff}.list-group-item-primary.list-group-item-action:focus,.list-group-item-primary.list-group-item-action:hover{color:#084298;background-color:#bacbe6}.list-group-item-primary.list-group-item-action.active{color:#fff;background-color:#084298;border-color:#084298}.list-group-item-secondary{color:#41464b;background-color:#e2e3e5}.list-group-item-secondary.list-group-item-action:focus,.list-group-item-secondary.list-group-item-action:hover{color:#41464b;background-color:#cbccce}.list-group-item-secondary.list-group-item-action.active{color:#fff;background-color:#41464b;border-color:#41464b}.list-group-item-success{color:#0f5132;background-color:#d1e7dd}.list-group-item-success.list-group-item-action:focus,.list-group-item-success.list-group-item-action:hover{color:#0f5132;background-color:#bcd0c7}.list-group-item-success.list-group-item-action.active{color:#fff;background-color:#0f5132;border-color:#0f5132}.list-group-item-info{color:#055160;background-color:#cff4fc}.list-group-item-info.list-group-item-action:focus,.list-group-item-info.list-group-item-action:hover{color:#055160;background-color:#badce3}.list-group-item-info.list-group-item-action.active{color:#fff;background-color:#055160;border-color:#055160}.list-group-item-warning{color:#664d03;background-color:#fff3cd}.list-group-item-warning.list-group-item-action:focus,.list-group-item-warning.list-group-item-action:hover{color:#664d03;background-color:#e6dbb9}.list-group-item-warning.list-group-item-action.active{color:#fff;background-color:#664d03;border-color:#664d03}.list-group-item-danger{color:#842029;background-color:#f8d7da}.list-group-item-danger.list-group-item-action:focus,.list-group-item-danger.list-group-item-action:hover{color:#842029;background-color:#dfc2c4}.list-group-item-danger.list-group-item-action.active{color:#fff;background-color:#842029;border-color:#842029}.list-group-item-light{color:#636464;background-color:#fefefe}.list-group-item-light.list-group-item-action:focus,.list-group-item-light.list-group-item-action:hover{color:#636464;background-color:#e5e5e5}.list-group-item-light.list-group-item-action.active{color:#fff;background-color:#636464;border-color:#636464}.list-group-item-dark{color:#141619;background-color:#d3d3d4}.list-group-item-dark.list-group-item-action:focus,.list-group-item-dark.list-group-item-action:hover{color:#141619;background-color:#bebebf}.list-group-item-dark.list-group-item-action.active{color:#fff;background-color:#141619;border-color:#141619}.btn-close{box-sizing:content-box;width:1em;height:1em;padding:.25em .25em;color:#000;background:transparent url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23000'%3e%3cpath d='M.293.293a1 1 0 011.414 0L8 6.586 14.293.293a1 1 0 111.414 1.414L9.414 8l6.293 6.293a1 1 0 01-1.414 1.414L8 9.414l-6.293 6.293a1 1 0 01-1.414-1.414L6.586 8 .293 1.707a1 1 0 010-1.414z'/%3e%3c/svg%3e") center/1em auto no-repeat;border:0;border-radius:.25rem;opacity:.5}.btn-close:hover{color:#000;text-decoration:none;opacity:.75}.btn-close:focus{outline:0;box-shadow:0 0 0 .25rem rgba(13,110,253,.25);opacity:1}.btn-close.disabled,.btn-close:disabled{pointer-events:none;-webkit-user-select:none;-moz-user-select:none;user-select:none;opacity:.25}.btn-close-white{filter:invert(1) grayscale(100%) brightness(200%)}.toast{width:350px;max-width:100%;font-size:.875rem;pointer-events:auto;background-color:rgba(255,255,255,.85);background-clip:padding-box;border:1px solid rgba(0,0,0,.1);box-shadow:0 .5rem 1rem rgba(0,0,0,.15);border-radius:.25rem}.toast.showing{opacity:0}.toast:not(.show){display:none}.toast-container{width:-webkit-max-content;width:-moz-max-content;width:max-content;max-width:100%;pointer-events:none}.toast-container>:not(:last-child){margin-bottom:.75rem}.toast-header{display:flex;align-items:center;padding:.5rem .75rem;color:#6c757d;background-color:rgba(255,255,255,.85);background-clip:padding-box;border-bottom:1px solid rgba(0,0,0,.05);border-top-left-radius:calc(.25rem - 1px);border-top-right-radius:calc(.25rem - 1px)}.toast-header .btn-close{margin-right:-.375rem;margin-left:.75rem}.toast-body{padding:.75rem;word-wrap:break-word}.modal{position:fixed;top:0;left:0;z-index:1055;display:none;width:100%;height:100%;overflow-x:hidden;overflow-y:auto;outline:0}.modal-dialog{position:relative;width:auto;margin:.5rem;pointer-events:none}.modal.fade .modal-dialog{transition:transform .3s ease-out;transform:translate(0,-50px)}@media (prefers-reduced-motion:reduce){.modal.fade .modal-dialog{transition:none}}.modal.show .modal-dialog{transform:none}.modal.modal-static .modal-dialog{transform:scale(1.02)}.modal-dialog-scrollable{height:calc(100% - 1rem)}.modal-dialog-scrollable .modal-content{max-height:100%;overflow:hidden}.modal-dialog-scrollable .modal-body{overflow-y:auto}.modal-dialog-centered{display:flex;align-items:center;min-height:calc(100% - 1rem)}.modal-content{position:relative;display:flex;flex-direction:column;width:100%;pointer-events:auto;background-color:#fff;background-clip:padding-box;border:1px solid rgba(0,0,0,.2);border-radius:.3rem;outline:0}.modal-backdrop{position:fixed;top:0;left:0;z-index:1050;width:100vw;height:100vh;background-color:#000}.modal-backdrop.fade{opacity:0}.modal-backdrop.show{opacity:.5}.modal-header{display:flex;flex-shrink:0;align-items:center;justify-content:space-between;padding:1rem 1rem;border-bottom:1px solid #dee2e6;border-top-left-radius:calc(.3rem - 1px);border-top-right-radius:calc(.3rem - 1px)}.modal-header .btn-close{padding:.5rem .5rem;margin:-.5rem -.5rem -.5rem auto}.modal-title{margin-bottom:0;line-height:1.5}.modal-body{position:relative;flex:1 1 auto;padding:1rem}.modal-footer{display:flex;flex-wrap:wrap;flex-shrink:0;align-items:center;justify-content:flex-end;padding:.75rem;border-top:1px solid #dee2e6;border-bottom-right-radius:calc(.3rem - 1px);border-bottom-left-radius:calc(.3rem - 1px)}.modal-footer>*{margin:.25rem}@media (min-width:576px){.modal-dialog{max-width:500px;margin:1.75rem auto}.modal-dialog-scrollable{height:calc(100% - 3.5rem)}.modal-dialog-centered{min-height:calc(100% - 3.5rem)}.modal-sm{max-width:300px}}@media (min-width:992px){.modal-lg,.modal-xl{max-width:800px}}@media (min-width:1200px){.modal-xl{max-width:1140px}}.modal-fullscreen{width:100vw;max-width:none;height:100%;margin:0}.modal-fullscreen .modal-content{height:100%;border:0;border-radius:0}.modal-fullscreen .modal-header{border-radius:0}.modal-fullscreen .modal-body{overflow-y:auto}.modal-fullscreen .modal-footer{border-radius:0}@media (max-width:575.98px){.modal-fullscreen-sm-down{width:100vw;max-width:none;height:100%;margin:0}.modal-fullscreen-sm-down .modal-content{height:100%;border:0;border-radius:0}.modal-fullscreen-sm-down .modal-header{border-radius:0}.modal-fullscreen-sm-down .modal-body{overflow-y:auto}.modal-fullscreen-sm-down .modal-footer{border-radius:0}}@media (max-width:767.98px){.modal-fullscreen-md-down{width:100vw;max-width:none;height:100%;margin:0}.modal-fullscreen-md-down .modal-content{height:100%;border:0;border-radius:0}.modal-fullscreen-md-down .modal-header{border-radius:0}.modal-fullscreen-md-down .modal-body{overflow-y:auto}.modal-fullscreen-md-down .modal-footer{border-radius:0}}@media (max-width:991.98px){.modal-fullscreen-lg-down{width:100vw;max-width:none;height:100%;margin:0}.modal-fullscreen-lg-down .modal-content{height:100%;border:0;border-radius:0}.modal-fullscreen-lg-down .modal-header{border-radius:0}.modal-fullscreen-lg-down .modal-body{overflow-y:auto}.modal-fullscreen-lg-down .modal-footer{border-radius:0}}@media (max-width:1199.98px){.modal-fullscreen-xl-down{width:100vw;max-width:none;height:100%;margin:0}.modal-fullscreen-xl-down .modal-content{height:100%;border:0;border-radius:0}.modal-fullscreen-xl-down .modal-header{border-radius:0}.modal-fullscreen-xl-down .modal-body{overflow-y:auto}.modal-fullscreen-xl-down .modal-footer{border-radius:0}}@media (max-width:1399.98px){.modal-fullscreen-xxl-down{width:100vw;max-width:none;height:100%;margin:0}.modal-fullscreen-xxl-down .modal-content{height:100%;border:0;border-radius:0}.modal-fullscreen-xxl-down .modal-header{border-radius:0}.modal-fullscreen-xxl-down .modal-body{overflow-y:auto}.modal-fullscreen-xxl-down .modal-footer{border-radius:0}}.tooltip{position:absolute;z-index:1080;display:block;margin:0;font-family:var(--bs-font-sans-serif);font-style:normal;font-weight:400;line-height:1.5;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;letter-spacing:normal;word-break:normal;word-spacing:normal;white-space:normal;line-break:auto;font-size:.875rem;word-wrap:break-word;opacity:0}.tooltip.show{opacity:.9}.tooltip .tooltip-arrow{position:absolute;display:block;width:.8rem;height:.4rem}.tooltip .tooltip-arrow::before{position:absolute;content:"";border-color:transparent;border-style:solid}.bs-tooltip-auto[data-popper-placement^=top],.bs-tooltip-top{padding:.4rem 0}.bs-tooltip-auto[data-popper-placement^=top] .tooltip-arrow,.bs-tooltip-top .tooltip-arrow{bottom:0}.bs-tooltip-auto[data-popper-placement^=top] .tooltip-arrow::before,.bs-tooltip-top .tooltip-arrow::before{top:-1px;border-width:.4rem .4rem 0;border-top-color:#000}.bs-tooltip-auto[data-popper-placement^=right],.bs-tooltip-end{padding:0 .4rem}.bs-tooltip-auto[data-popper-placement^=right] .tooltip-arrow,.bs-tooltip-end .tooltip-arrow{left:0;width:.4rem;height:.8rem}.bs-tooltip-auto[data-popper-placement^=right] .tooltip-arrow::before,.bs-tooltip-end .tooltip-arrow::before{right:-1px;border-width:.4rem .4rem .4rem 0;border-right-color:#000}.bs-tooltip-auto[data-popper-placement^=bottom],.bs-tooltip-bottom{padding:.4rem 0}.bs-tooltip-auto[data-popper-placement^=bottom] .tooltip-arrow,.bs-tooltip-bottom .tooltip-arrow{top:0}.bs-tooltip-auto[data-popper-placement^=bottom] .tooltip-arrow::before,.bs-tooltip-bottom .tooltip-arrow::before{bottom:-1px;border-width:0 .4rem .4rem;border-bottom-color:#000}.bs-tooltip-auto[data-popper-placement^=left],.bs-tooltip-start{padding:0 .4rem}.bs-tooltip-auto[data-popper-placement^=left] .tooltip-arrow,.bs-tooltip-start .tooltip-arrow{right:0;width:.4rem;height:.8rem}.bs-tooltip-auto[data-popper-placement^=left] .tooltip-arrow::before,.bs-tooltip-start .tooltip-arrow::before{left:-1px;border-width:.4rem 0 .4rem .4rem;border-left-color:#000}.tooltip-inner{max-width:200px;padding:.25rem .5rem;color:#fff;text-align:center;background-color:#000;border-radius:.25rem}.popover{position:absolute;top:0;left:0;z-index:1070;display:block;max-width:276px;font-family:var(--bs-font-sans-serif);font-style:normal;font-weight:400;line-height:1.5;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;letter-spacing:normal;word-break:normal;word-spacing:normal;white-space:normal;line-break:auto;font-size:.875rem;word-wrap:break-word;background-color:#fff;background-clip:padding-box;border:1px solid rgba(0,0,0,.2);border-radius:.3rem}.popover .popover-arrow{position:absolute;display:block;width:1rem;height:.5rem}.popover .popover-arrow::after,.popover .popover-arrow::before{position:absolute;display:block;content:"";border-color:transparent;border-style:solid}.bs-popover-auto[data-popper-placement^=top]>.popover-arrow,.bs-popover-top>.popover-arrow{bottom:calc(-.5rem - 1px)}.bs-popover-auto[data-popper-placement^=top]>.popover-arrow::before,.bs-popover-top>.popover-arrow::before{bottom:0;border-width:.5rem .5rem 0;border-top-color:rgba(0,0,0,.25)}.bs-popover-auto[data-popper-placement^=top]>.popover-arrow::after,.bs-popover-top>.popover-arrow::after{bottom:1px;border-width:.5rem .5rem 0;border-top-color:#fff}.bs-popover-auto[data-popper-placement^=right]>.popover-arrow,.bs-popover-end>.popover-arrow{left:calc(-.5rem - 1px);width:.5rem;height:1rem}.bs-popover-auto[data-popper-placement^=right]>.popover-arrow::before,.bs-popover-end>.popover-arrow::before{left:0;border-width:.5rem .5rem .5rem 0;border-right-color:rgba(0,0,0,.25)}.bs-popover-auto[data-popper-placement^=right]>.popover-arrow::after,.bs-popover-end>.popover-arrow::after{left:1px;border-width:.5rem .5rem .5rem 0;border-right-color:#fff}.bs-popover-auto[data-popper-placement^=bottom]>.popover-arrow,.bs-popover-bottom>.popover-arrow{top:calc(-.5rem - 1px)}.bs-popover-auto[data-popper-placement^=bottom]>.popover-arrow::before,.bs-popover-bottom>.popover-arrow::before{top:0;border-width:0 .5rem .5rem .5rem;border-bottom-color:rgba(0,0,0,.25)}.bs-popover-auto[data-popper-placement^=bottom]>.popover-arrow::after,.bs-popover-bottom>.popover-arrow::after{top:1px;border-width:0 .5rem .5rem .5rem;border-bottom-color:#fff}.bs-popover-auto[data-popper-placement^=bottom] .popover-header::before,.bs-popover-bottom .popover-header::before{position:absolute;top:0;left:50%;display:block;width:1rem;margin-left:-.5rem;content:"";border-bottom:1px solid #f0f0f0}.bs-popover-auto[data-popper-placement^=left]>.popover-arrow,.bs-popover-start>.popover-arrow{right:calc(-.5rem - 1px);width:.5rem;height:1rem}.bs-popover-auto[data-popper-placement^=left]>.popover-arrow::before,.bs-popover-start>.popover-arrow::before{right:0;border-width:.5rem 0 .5rem .5rem;border-left-color:rgba(0,0,0,.25)}.bs-popover-auto[data-popper-placement^=left]>.popover-arrow::after,.bs-popover-start>.popover-arrow::after{right:1px;border-width:.5rem 0 .5rem .5rem;border-left-color:#fff}.popover-header{padding:.5rem 1rem;margin-bottom:0;font-size:1rem;background-color:#f0f0f0;border-bottom:1px solid rgba(0,0,0,.2);border-top-left-radius:calc(.3rem - 1px);border-top-right-radius:calc(.3rem - 1px)}.popover-header:empty{display:none}.popover-body{padding:1rem 1rem;color:#212529}.carousel{position:relative}.carousel.pointer-event{touch-action:pan-y}.carousel-inner{position:relative;width:100%;overflow:hidden}.carousel-inner::after{display:block;clear:both;content:""}.carousel-item{position:relative;display:none;float:left;width:100%;margin-right:-100%;-webkit-backface-visibility:hidden;backface-visibility:hidden;transition:transform .6s ease-in-out}@media (prefers-reduced-motion:reduce){.carousel-item{transition:none}}.carousel-item-next,.carousel-item-prev,.carousel-item.active{display:block}.active.carousel-item-end,.carousel-item-next:not(.carousel-item-start){transform:translateX(100%)}.active.carousel-item-start,.carousel-item-prev:not(.carousel-item-end){transform:translateX(-100%)}.carousel-fade .carousel-item{opacity:0;transition-property:opacity;transform:none}.carousel-fade .carousel-item-next.carousel-item-start,.carousel-fade .carousel-item-prev.carousel-item-end,.carousel-fade .carousel-item.active{z-index:1;opacity:1}.carousel-fade .active.carousel-item-end,.carousel-fade .active.carousel-item-start{z-index:0;opacity:0;transition:opacity 0s .6s}@media (prefers-reduced-motion:reduce){.carousel-fade .active.carousel-item-end,.carousel-fade .active.carousel-item-start{transition:none}}.carousel-control-next,.carousel-control-prev{position:absolute;top:0;bottom:0;z-index:1;display:flex;align-items:center;justify-content:center;width:15%;padding:0;color:#fff;text-align:center;background:0 0;border:0;opacity:.5;transition:opacity .15s ease}@media (prefers-reduced-motion:reduce){.carousel-control-next,.carousel-control-prev{transition:none}}.carousel-control-next:focus,.carousel-control-next:hover,.carousel-control-prev:focus,.carousel-control-prev:hover{color:#fff;text-decoration:none;outline:0;opacity:.9}.carousel-control-prev{left:0}.carousel-control-next{right:0}.carousel-control-next-icon,.carousel-control-prev-icon{display:inline-block;width:2rem;height:2rem;background-repeat:no-repeat;background-position:50%;background-size:100% 100%}.carousel-control-prev-icon{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23fff'%3e%3cpath d='M11.354 1.646a.5.5 0 0 1 0 .708L5.707 8l5.647 5.646a.5.5 0 0 1-.708.708l-6-6a.5.5 0 0 1 0-.708l6-6a.5.5 0 0 1 .708 0z'/%3e%3c/svg%3e")}.carousel-control-next-icon{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23fff'%3e%3cpath d='M4.646 1.646a.5.5 0 0 1 .708 0l6 6a.5.5 0 0 1 0 .708l-6 6a.5.5 0 0 1-.708-.708L10.293 8 4.646 2.354a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e")}.carousel-indicators{position:absolute;right:0;bottom:0;left:0;z-index:2;display:flex;justify-content:center;padding:0;margin-right:15%;margin-bottom:1rem;margin-left:15%;list-style:none}.carousel-indicators [data-bs-target]{box-sizing:content-box;flex:0 1 auto;width:30px;height:3px;padding:0;margin-right:3px;margin-left:3px;text-indent:-999px;cursor:pointer;background-color:#fff;background-clip:padding-box;border:0;border-top:10px solid transparent;border-bottom:10px solid transparent;opacity:.5;transition:opacity .6s ease}@media (prefers-reduced-motion:reduce){.carousel-indicators [data-bs-target]{transition:none}}.carousel-indicators .active{opacity:1}.carousel-caption{position:absolute;right:15%;bottom:1.25rem;left:15%;padding-top:1.25rem;padding-bottom:1.25rem;color:#fff;text-align:center}.carousel-dark .carousel-control-next-icon,.carousel-dark .carousel-control-prev-icon{filter:invert(1) grayscale(100)}.carousel-dark .carousel-indicators [data-bs-target]{background-color:#000}.carousel-dark .carousel-caption{color:#000}@-webkit-keyframes spinner-border{to{transform:rotate(360deg)}}@keyframes spinner-border{to{transform:rotate(360deg)}}.spinner-border{display:inline-block;width:2rem;height:2rem;vertical-align:-.125em;border:.25em solid currentColor;border-right-color:transparent;border-radius:50%;-webkit-animation:.75s linear infinite spinner-border;animation:.75s linear infinite spinner-border}.spinner-border-sm{width:1rem;height:1rem;border-width:.2em}@-webkit-keyframes spinner-grow{0%{transform:scale(0)}50%{opacity:1;transform:none}}@keyframes spinner-grow{0%{transform:scale(0)}50%{opacity:1;transform:none}}.spinner-grow{display:inline-block;width:2rem;height:2rem;vertical-align:-.125em;background-color:currentColor;border-radius:50%;opacity:0;-webkit-animation:.75s linear infinite spinner-grow;animation:.75s linear infinite spinner-grow}.spinner-grow-sm{width:1rem;height:1rem}@media (prefers-reduced-motion:reduce){.spinner-border,.spinner-grow{-webkit-animation-duration:1.5s;animation-duration:1.5s}}.offcanvas{position:fixed;bottom:0;z-index:1045;display:flex;flex-direction:column;max-width:100%;visibility:hidden;background-color:#fff;background-clip:padding-box;outline:0;transition:transform .3s ease-in-out}@media (prefers-reduced-motion:reduce){.offcanvas{transition:none}}.offcanvas-backdrop{position:fixed;top:0;left:0;z-index:1040;width:100vw;height:100vh;background-color:#000}.offcanvas-backdrop.fade{opacity:0}.offcanvas-backdrop.show{opacity:.5}.offcanvas-header{display:flex;align-items:center;justify-content:space-between;padding:1rem 1rem}.offcanvas-header .btn-close{padding:.5rem .5rem;margin-top:-.5rem;margin-right:-.5rem;margin-bottom:-.5rem}.offcanvas-title{margin-bottom:0;line-height:1.5}.offcanvas-body{flex-grow:1;padding:1rem 1rem;overflow-y:auto}.offcanvas-start{top:0;left:0;width:400px;border-right:1px solid rgba(0,0,0,.2);transform:translateX(-100%)}.offcanvas-end{top:0;right:0;width:400px;border-left:1px solid rgba(0,0,0,.2);transform:translateX(100%)}.offcanvas-top{top:0;right:0;left:0;height:30vh;max-height:100%;border-bottom:1px solid rgba(0,0,0,.2);transform:translateY(-100%)}.offcanvas-bottom{right:0;left:0;height:30vh;max-height:100%;border-top:1px solid rgba(0,0,0,.2);transform:translateY(100%)}.offcanvas.show{transform:none}.placeholder{display:inline-block;min-height:1em;vertical-align:middle;cursor:wait;background-color:currentColor;opacity:.5}.placeholder.btn::before{display:inline-block;content:""}.placeholder-xs{min-height:.6em}.placeholder-sm{min-height:.8em}.placeholder-lg{min-height:1.2em}.placeholder-glow .placeholder{-webkit-animation:placeholder-glow 2s ease-in-out infinite;animation:placeholder-glow 2s ease-in-out infinite}@-webkit-keyframes placeholder-glow{50%{opacity:.2}}@keyframes placeholder-glow{50%{opacity:.2}}.placeholder-wave{-webkit-mask-image:linear-gradient(130deg,#000 55%,rgba(0,0,0,0.8) 75%,#000 95%);mask-image:linear-gradient(130deg,#000 55%,rgba(0,0,0,0.8) 75%,#000 95%);-webkit-mask-size:200% 100%;mask-size:200% 100%;-webkit-animation:placeholder-wave 2s linear infinite;animation:placeholder-wave 2s linear infinite}@-webkit-keyframes placeholder-wave{100%{-webkit-mask-position:-200% 0%;mask-position:-200% 0%}}@keyframes placeholder-wave{100%{-webkit-mask-position:-200% 0%;mask-position:-200% 0%}}.clearfix::after{display:block;clear:both;content:""}.link-primary{color:#0d6efd}.link-primary:focus,.link-primary:hover{color:#0a58ca}.link-secondary{color:#6c757d}.link-secondary:focus,.link-secondary:hover{color:#565e64}.link-success{color:#198754}.link-success:focus,.link-success:hover{color:#146c43}.link-info{color:#0dcaf0}.link-info:focus,.link-info:hover{color:#3dd5f3}.link-warning{color:#ffc107}.link-warning:focus,.link-warning:hover{color:#ffcd39}.link-danger{color:#dc3545}.link-danger:focus,.link-danger:hover{color:#b02a37}.link-light{color:#f8f9fa}.link-light:focus,.link-light:hover{color:#f9fafb}.link-dark{color:#212529}.link-dark:focus,.link-dark:hover{color:#1a1e21}.ratio{position:relative;width:100%}.ratio::before{display:block;padding-top:var(--bs-aspect-ratio);content:""}.ratio>*{position:absolute;top:0;left:0;width:100%;height:100%}.ratio-1x1{--bs-aspect-ratio:100%}.ratio-4x3{--bs-aspect-ratio:calc(3 / 4 * 100%)}.ratio-16x9{--bs-aspect-ratio:calc(9 / 16 * 100%)}.ratio-21x9{--bs-aspect-ratio:calc(9 / 21 * 100%)}.fixed-top{position:fixed;top:0;right:0;left:0;z-index:1030}.fixed-bottom{position:fixed;right:0;bottom:0;left:0;z-index:1030}.sticky-top{position:-webkit-sticky;position:sticky;top:0;z-index:1020}@media (min-width:576px){.sticky-sm-top{position:-webkit-sticky;position:sticky;top:0;z-index:1020}}@media (min-width:768px){.sticky-md-top{position:-webkit-sticky;position:sticky;top:0;z-index:1020}}@media (min-width:992px){.sticky-lg-top{position:-webkit-sticky;position:sticky;top:0;z-index:1020}}@media (min-width:1200px){.sticky-xl-top{position:-webkit-sticky;position:sticky;top:0;z-index:1020}}@media (min-width:1400px){.sticky-xxl-top{position:-webkit-sticky;position:sticky;top:0;z-index:1020}}.hstack{display:flex;flex-direction:row;align-items:center;align-self:stretch}.vstack{display:flex;flex:1 1 auto;flex-direction:column;align-self:stretch}.visually-hidden,.visually-hidden-focusable:not(:focus):not(:focus-within){position:absolute!important;width:1px!important;height:1px!important;padding:0!important;margin:-1px!important;overflow:hidden!important;clip:rect(0,0,0,0)!important;white-space:nowrap!important;border:0!important}.stretched-link::after{position:absolute;top:0;right:0;bottom:0;left:0;z-index:1;content:""}.text-truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.vr{display:inline-block;align-self:stretch;width:1px;min-height:1em;background-color:currentColor;opacity:.25}.align-baseline{vertical-align:baseline!important}.align-top{vertical-align:top!important}.align-middle{vertical-align:middle!important}.align-bottom{vertical-align:bottom!important}.align-text-bottom{vertical-align:text-bottom!important}.align-text-top{vertical-align:text-top!important}.float-start{float:left!important}.float-end{float:right!important}.float-none{float:none!important}.opacity-0{opacity:0!important}.opacity-25{opacity:.25!important}.opacity-50{opacity:.5!important}.opacity-75{opacity:.75!important}.opacity-100{opacity:1!important}.overflow-auto{overflow:auto!important}.overflow-hidden{overflow:hidden!important}.overflow-visible{overflow:visible!important}.overflow-scroll{overflow:scroll!important}.d-inline{display:inline!important}.d-inline-block{display:inline-block!important}.d-block{display:block!important}.d-grid{display:grid!important}.d-table{display:table!important}.d-table-row{display:table-row!important}.d-table-cell{display:table-cell!important}.d-flex{display:flex!important}.d-inline-flex{display:inline-flex!important}.d-none{display:none!important}.shadow{box-shadow:0 .5rem 1rem rgba(0,0,0,.15)!important}.shadow-sm{box-shadow:0 .125rem .25rem rgba(0,0,0,.075)!important}.shadow-lg{box-shadow:0 1rem 3rem rgba(0,0,0,.175)!important}.shadow-none{box-shadow:none!important}.position-static{position:static!important}.position-relative{position:relative!important}.position-absolute{position:absolute!important}.position-fixed{position:fixed!important}.position-sticky{position:-webkit-sticky!important;position:sticky!important}.top-0{top:0!important}.top-50{top:50%!important}.top-100{top:100%!important}.bottom-0{bottom:0!important}.bottom-50{bottom:50%!important}.bottom-100{bottom:100%!important}.start-0{left:0!important}.start-50{left:50%!important}.start-100{left:100%!important}.end-0{right:0!important}.end-50{right:50%!important}.end-100{right:100%!important}.translate-middle{transform:translate(-50%,-50%)!important}.translate-middle-x{transform:translateX(-50%)!important}.translate-middle-y{transform:translateY(-50%)!important}.border{border:1px solid #dee2e6!important}.border-0{border:0!important}.border-top{border-top:1px solid #dee2e6!important}.border-top-0{border-top:0!important}.border-end{border-right:1px solid #dee2e6!important}.border-end-0{border-right:0!important}.border-bottom{border-bottom:1px solid #dee2e6!important}.border-bottom-0{border-bottom:0!important}.border-start{border-left:1px solid #dee2e6!important}.border-start-0{border-left:0!important}.border-primary{border-color:#0d6efd!important}.border-secondary{border-color:#6c757d!important}.border-success{border-color:#198754!important}.border-info{border-color:#0dcaf0!important}.border-warning{border-color:#ffc107!important}.border-danger{border-color:#dc3545!important}.border-light{border-color:#f8f9fa!important}.border-dark{border-color:#212529!important}.border-white{border-color:#fff!important}.border-1{border-width:1px!important}.border-2{border-width:2px!important}.border-3{border-width:3px!important}.border-4{border-width:4px!important}.border-5{border-width:5px!important}.w-25{width:25%!important}.w-50{width:50%!important}.w-75{width:75%!important}.w-100{width:100%!important}.w-auto{width:auto!important}.mw-100{max-width:100%!important}.vw-100{width:100vw!important}.min-vw-100{min-width:100vw!important}.h-25{height:25%!important}.h-50{height:50%!important}.h-75{height:75%!important}.h-100{height:100%!important}.h-auto{height:auto!important}.mh-100{max-height:100%!important}.vh-100{height:100vh!important}.min-vh-100{min-height:100vh!important}.flex-fill{flex:1 1 auto!important}.flex-row{flex-direction:row!important}.flex-column{flex-direction:column!important}.flex-row-reverse{flex-direction:row-reverse!important}.flex-column-reverse{flex-direction:column-reverse!important}.flex-grow-0{flex-grow:0!important}.flex-grow-1{flex-grow:1!important}.flex-shrink-0{flex-shrink:0!important}.flex-shrink-1{flex-shrink:1!important}.flex-wrap{flex-wrap:wrap!important}.flex-nowrap{flex-wrap:nowrap!important}.flex-wrap-reverse{flex-wrap:wrap-reverse!important}.gap-0{gap:0!important}.gap-1{gap:.25rem!important}.gap-2{gap:.5rem!important}.gap-3{gap:1rem!important}.gap-4{gap:1.5rem!important}.gap-5{gap:3rem!important}.justify-content-start{justify-content:flex-start!important}.justify-content-end{justify-content:flex-end!important}.justify-content-center{justify-content:center!important}.justify-content-between{justify-content:space-between!important}.justify-content-around{justify-content:space-around!important}.justify-content-evenly{justify-content:space-evenly!important}.align-items-start{align-items:flex-start!important}.align-items-end{align-items:flex-end!important}.align-items-center{align-items:center!important}.align-items-baseline{align-items:baseline!important}.align-items-stretch{align-items:stretch!important}.align-content-start{align-content:flex-start!important}.align-content-end{align-content:flex-end!important}.align-content-center{align-content:center!important}.align-content-between{align-content:space-between!important}.align-content-around{align-content:space-around!important}.align-content-stretch{align-content:stretch!important}.align-self-auto{align-self:auto!important}.align-self-start{align-self:flex-start!important}.align-self-end{align-self:flex-end!important}.align-self-center{align-self:center!important}.align-self-baseline{align-self:baseline!important}.align-self-stretch{align-self:stretch!important}.order-first{order:-1!important}.order-0{order:0!important}.order-1{order:1!important}.order-2{order:2!important}.order-3{order:3!important}.order-4{order:4!important}.order-5{order:5!important}.order-last{order:6!important}.m-0{margin:0!important}.m-1{margin:.25rem!important}.m-2{margin:.5rem!important}.m-3{margin:1rem!important}.m-4{margin:1.5rem!important}.m-5{margin:3rem!important}.m-auto{margin:auto!important}.mx-0{margin-right:0!important;margin-left:0!important}.mx-1{margin-right:.25rem!important;margin-left:.25rem!important}.mx-2{margin-right:.5rem!important;margin-left:.5rem!important}.mx-3{margin-right:1rem!important;margin-left:1rem!important}.mx-4{margin-right:1.5rem!important;margin-left:1.5rem!important}.mx-5{margin-right:3rem!important;margin-left:3rem!important}.mx-auto{margin-right:auto!important;margin-left:auto!important}.my-0{margin-top:0!important;margin-bottom:0!important}.my-1{margin-top:.25rem!important;margin-bottom:.25rem!important}.my-2{margin-top:.5rem!important;margin-bottom:.5rem!important}.my-3{margin-top:1rem!important;margin-bottom:1rem!important}.my-4{margin-top:1.5rem!important;margin-bottom:1.5rem!important}.my-5{margin-top:3rem!important;margin-bottom:3rem!important}.my-auto{margin-top:auto!important;margin-bottom:auto!important}.mt-0{margin-top:0!important}.mt-1{margin-top:.25rem!important}.mt-2{margin-top:.5rem!important}.mt-3{margin-top:1rem!important}.mt-4{margin-top:1.5rem!important}.mt-5{margin-top:3rem!important}.mt-auto{margin-top:auto!important}.me-0{margin-right:0!important}.me-1{margin-right:.25rem!important}.me-2{margin-right:.5rem!important}.me-3{margin-right:1rem!important}.me-4{margin-right:1.5rem!important}.me-5{margin-right:3rem!important}.me-auto{margin-right:auto!important}.mb-0{margin-bottom:0!important}.mb-1{margin-bottom:.25rem!important}.mb-2{margin-bottom:.5rem!important}.mb-3{margin-bottom:1rem!important}.mb-4{margin-bottom:1.5rem!important}.mb-5{margin-bottom:3rem!important}.mb-auto{margin-bottom:auto!important}.ms-0{margin-left:0!important}.ms-1{margin-left:.25rem!important}.ms-2{margin-left:.5rem!important}.ms-3{margin-left:1rem!important}.ms-4{margin-left:1.5rem!important}.ms-5{margin-left:3rem!important}.ms-auto{margin-left:auto!important}.p-0{padding:0!important}.p-1{padding:.25rem!important}.p-2{padding:.5rem!important}.p-3{padding:1rem!important}.p-4{padding:1.5rem!important}.p-5{padding:3rem!important}.px-0{padding-right:0!important;padding-left:0!important}.px-1{padding-right:.25rem!important;padding-left:.25rem!important}.px-2{padding-right:.5rem!important;padding-left:.5rem!important}.px-3{padding-right:1rem!important;padding-left:1rem!important}.px-4{padding-right:1.5rem!important;padding-left:1.5rem!important}.px-5{padding-right:3rem!important;padding-left:3rem!important}.py-0{padding-top:0!important;padding-bottom:0!important}.py-1{padding-top:.25rem!important;padding-bottom:.25rem!important}.py-2{padding-top:.5rem!important;padding-bottom:.5rem!important}.py-3{padding-top:1rem!important;padding-bottom:1rem!important}.py-4{padding-top:1.5rem!important;padding-bottom:1.5rem!important}.py-5{padding-top:3rem!important;padding-bottom:3rem!important}.pt-0{padding-top:0!important}.pt-1{padding-top:.25rem!important}.pt-2{padding-top:.5rem!important}.pt-3{padding-top:1rem!important}.pt-4{padding-top:1.5rem!important}.pt-5{padding-top:3rem!important}.pe-0{padding-right:0!important}.pe-1{padding-right:.25rem!important}.pe-2{padding-right:.5rem!important}.pe-3{padding-right:1rem!important}.pe-4{padding-right:1.5rem!important}.pe-5{padding-right:3rem!important}.pb-0{padding-bottom:0!important}.pb-1{padding-bottom:.25rem!important}.pb-2{padding-bottom:.5rem!important}.pb-3{padding-bottom:1rem!important}.pb-4{padding-bottom:1.5rem!important}.pb-5{padding-bottom:3rem!important}.ps-0{padding-left:0!important}.ps-1{padding-left:.25rem!important}.ps-2{padding-left:.5rem!important}.ps-3{padding-left:1rem!important}.ps-4{padding-left:1.5rem!important}.ps-5{padding-left:3rem!important}.font-monospace{font-family:var(--bs-font-monospace)!important}.fs-1{font-size:calc(1.375rem + 1.5vw)!important}.fs-2{font-size:calc(1.325rem + .9vw)!important}.fs-3{font-size:calc(1.3rem + .6vw)!important}.fs-4{font-size:calc(1.275rem + .3vw)!important}.fs-5{font-size:1.25rem!important}.fs-6{font-size:1rem!important}.fst-italic{font-style:italic!important}.fst-normal{font-style:normal!important}.fw-light{font-weight:300!important}.fw-lighter{font-weight:lighter!important}.fw-normal{font-weight:400!important}.fw-bold{font-weight:700!important}.fw-bolder{font-weight:bolder!important}.lh-1{line-height:1!important}.lh-sm{line-height:1.25!important}.lh-base{line-height:1.5!important}.lh-lg{line-height:2!important}.text-start{text-align:left!important}.text-end{text-align:right!important}.text-center{text-align:center!important}.text-decoration-none{text-decoration:none!important}.text-decoration-underline{text-decoration:underline!important}.text-decoration-line-through{text-decoration:line-through!important}.text-lowercase{text-transform:lowercase!important}.text-uppercase{text-transform:uppercase!important}.text-capitalize{text-transform:capitalize!important}.text-wrap{white-space:normal!important}.text-nowrap{white-space:nowrap!important}.text-break{word-wrap:break-word!important;word-break:break-word!important}.text-primary{--bs-text-opacity:1;color:rgba(var(--bs-primary-rgb),var(--bs-text-opacity))!important}.text-secondary{--bs-text-opacity:1;color:rgba(var(--bs-secondary-rgb),var(--bs-text-opacity))!important}.text-success{--bs-text-opacity:1;color:rgba(var(--bs-success-rgb),var(--bs-text-opacity))!important}.text-info{--bs-text-opacity:1;color:rgba(var(--bs-info-rgb),var(--bs-text-opacity))!important}.text-warning{--bs-text-opacity:1;color:rgba(var(--bs-warning-rgb),var(--bs-text-opacity))!important}.text-danger{--bs-text-opacity:1;color:rgba(var(--bs-danger-rgb),var(--bs-text-opacity))!important}.text-light{--bs-text-opacity:1;color:rgba(var(--bs-light-rgb),var(--bs-text-opacity))!important}.text-dark{--bs-text-opacity:1;color:rgba(var(--bs-dark-rgb),var(--bs-text-opacity))!important}.text-black{--bs-text-opacity:1;color:rgba(var(--bs-black-rgb),var(--bs-text-opacity))!important}.text-white{--bs-text-opacity:1;color:rgba(var(--bs-white-rgb),var(--bs-text-opacity))!important}.text-body{--bs-text-opacity:1;color:rgba(var(--bs-body-rgb),var(--bs-text-opacity))!important}.text-muted{--bs-text-opacity:1;color:#6c757d!important}.text-black-50{--bs-text-opacity:1;color:rgba(0,0,0,.5)!important}.text-white-50{--bs-text-opacity:1;color:rgba(255,255,255,.5)!important}.text-reset{--bs-text-opacity:1;color:inherit!important}.text-opacity-25{--bs-text-opacity:0.25}.text-opacity-50{--bs-text-opacity:0.5}.text-opacity-75{--bs-text-opacity:0.75}.text-opacity-100{--bs-text-opacity:1}.bg-primary{--bs-bg-opacity:1;background-color:rgba(var(--bs-primary-rgb),var(--bs-bg-opacity))!important}.bg-secondary{--bs-bg-opacity:1;background-color:rgba(var(--bs-secondary-rgb),var(--bs-bg-opacity))!important}.bg-success{--bs-bg-opacity:1;background-color:rgba(var(--bs-success-rgb),var(--bs-bg-opacity))!important}.bg-info{--bs-bg-opacity:1;background-color:rgba(var(--bs-info-rgb),var(--bs-bg-opacity))!important}.bg-warning{--bs-bg-opacity:1;background-color:rgba(var(--bs-warning-rgb),var(--bs-bg-opacity))!important}.bg-danger{--bs-bg-opacity:1;background-color:rgba(var(--bs-danger-rgb),var(--bs-bg-opacity))!important}.bg-light{--bs-bg-opacity:1;background-color:rgba(var(--bs-light-rgb),var(--bs-bg-opacity))!important}.bg-dark{--bs-bg-opacity:1;background-color:rgba(var(--bs-dark-rgb),var(--bs-bg-opacity))!important}.bg-black{--bs-bg-opacity:1;background-color:rgba(var(--bs-black-rgb),var(--bs-bg-opacity))!important}.bg-white{--bs-bg-opacity:1;background-color:rgba(var(--bs-white-rgb),var(--bs-bg-opacity))!important}.bg-body{--bs-bg-opacity:1;background-color:rgba(var(--bs-body-rgb),var(--bs-bg-opacity))!important}.bg-transparent{--bs-bg-opacity:1;background-color:transparent!important}.bg-opacity-10{--bs-bg-opacity:0.1}.bg-opacity-25{--bs-bg-opacity:0.25}.bg-opacity-50{--bs-bg-opacity:0.5}.bg-opacity-75{--bs-bg-opacity:0.75}.bg-opacity-100{--bs-bg-opacity:1}.bg-gradient{background-image:var(--bs-gradient)!important}.user-select-all{-webkit-user-select:all!important;-moz-user-select:all!important;user-select:all!important}.user-select-auto{-webkit-user-select:auto!important;-moz-user-select:auto!important;user-select:auto!important}.user-select-none{-webkit-user-select:none!important;-moz-user-select:none!important;user-select:none!important}.pe-none{pointer-events:none!important}.pe-auto{pointer-events:auto!important}.rounded{border-radius:.25rem!important}.rounded-0{border-radius:0!important}.rounded-1{border-radius:.2rem!important}.rounded-2{border-radius:.25rem!important}.rounded-3{border-radius:.3rem!important}.rounded-circle{border-radius:50%!important}.rounded-pill{border-radius:50rem!important}.rounded-top{border-top-left-radius:.25rem!important;border-top-right-radius:.25rem!important}.rounded-end{border-top-right-radius:.25rem!important;border-bottom-right-radius:.25rem!important}.rounded-bottom{border-bottom-right-radius:.25rem!important;border-bottom-left-radius:.25rem!important}.rounded-start{border-bottom-left-radius:.25rem!important;border-top-left-radius:.25rem!important}.visible{visibility:visible!important}.invisible{visibility:hidden!important}@media (min-width:576px){.float-sm-start{float:left!important}.float-sm-end{float:right!important}.float-sm-none{float:none!important}.d-sm-inline{display:inline!important}.d-sm-inline-block{display:inline-block!important}.d-sm-block{display:block!important}.d-sm-grid{display:grid!important}.d-sm-table{display:table!important}.d-sm-table-row{display:table-row!important}.d-sm-table-cell{display:table-cell!important}.d-sm-flex{display:flex!important}.d-sm-inline-flex{display:inline-flex!important}.d-sm-none{display:none!important}.flex-sm-fill{flex:1 1 auto!important}.flex-sm-row{flex-direction:row!important}.flex-sm-column{flex-direction:column!important}.flex-sm-row-reverse{flex-direction:row-reverse!important}.flex-sm-column-reverse{flex-direction:column-reverse!important}.flex-sm-grow-0{flex-grow:0!important}.flex-sm-grow-1{flex-grow:1!important}.flex-sm-shrink-0{flex-shrink:0!important}.flex-sm-shrink-1{flex-shrink:1!important}.flex-sm-wrap{flex-wrap:wrap!important}.flex-sm-nowrap{flex-wrap:nowrap!important}.flex-sm-wrap-reverse{flex-wrap:wrap-reverse!important}.gap-sm-0{gap:0!important}.gap-sm-1{gap:.25rem!important}.gap-sm-2{gap:.5rem!important}.gap-sm-3{gap:1rem!important}.gap-sm-4{gap:1.5rem!important}.gap-sm-5{gap:3rem!important}.justify-content-sm-start{justify-content:flex-start!important}.justify-content-sm-end{justify-content:flex-end!important}.justify-content-sm-center{justify-content:center!important}.justify-content-sm-between{justify-content:space-between!important}.justify-content-sm-around{justify-content:space-around!important}.justify-content-sm-evenly{justify-content:space-evenly!important}.align-items-sm-start{align-items:flex-start!important}.align-items-sm-end{align-items:flex-end!important}.align-items-sm-center{align-items:center!important}.align-items-sm-baseline{align-items:baseline!important}.align-items-sm-stretch{align-items:stretch!important}.align-content-sm-start{align-content:flex-start!important}.align-content-sm-end{align-content:flex-end!important}.align-content-sm-center{align-content:center!important}.align-content-sm-between{align-content:space-between!important}.align-content-sm-around{align-content:space-around!important}.align-content-sm-stretch{align-content:stretch!important}.align-self-sm-auto{align-self:auto!important}.align-self-sm-start{align-self:flex-start!important}.align-self-sm-end{align-self:flex-end!important}.align-self-sm-center{align-self:center!important}.align-self-sm-baseline{align-self:baseline!important}.align-self-sm-stretch{align-self:stretch!important}.order-sm-first{order:-1!important}.order-sm-0{order:0!important}.order-sm-1{order:1!important}.order-sm-2{order:2!important}.order-sm-3{order:3!important}.order-sm-4{order:4!important}.order-sm-5{order:5!important}.order-sm-last{order:6!important}.m-sm-0{margin:0!important}.m-sm-1{margin:.25rem!important}.m-sm-2{margin:.5rem!important}.m-sm-3{margin:1rem!important}.m-sm-4{margin:1.5rem!important}.m-sm-5{margin:3rem!important}.m-sm-auto{margin:auto!important}.mx-sm-0{margin-right:0!important;margin-left:0!important}.mx-sm-1{margin-right:.25rem!important;margin-left:.25rem!important}.mx-sm-2{margin-right:.5rem!important;margin-left:.5rem!important}.mx-sm-3{margin-right:1rem!important;margin-left:1rem!important}.mx-sm-4{margin-right:1.5rem!important;margin-left:1.5rem!important}.mx-sm-5{margin-right:3rem!important;margin-left:3rem!important}.mx-sm-auto{margin-right:auto!important;margin-left:auto!important}.my-sm-0{margin-top:0!important;margin-bottom:0!important}.my-sm-1{margin-top:.25rem!important;margin-bottom:.25rem!important}.my-sm-2{margin-top:.5rem!important;margin-bottom:.5rem!important}.my-sm-3{margin-top:1rem!important;margin-bottom:1rem!important}.my-sm-4{margin-top:1.5rem!important;margin-bottom:1.5rem!important}.my-sm-5{margin-top:3rem!important;margin-bottom:3rem!important}.my-sm-auto{margin-top:auto!important;margin-bottom:auto!important}.mt-sm-0{margin-top:0!important}.mt-sm-1{margin-top:.25rem!important}.mt-sm-2{margin-top:.5rem!important}.mt-sm-3{margin-top:1rem!important}.mt-sm-4{margin-top:1.5rem!important}.mt-sm-5{margin-top:3rem!important}.mt-sm-auto{margin-top:auto!important}.me-sm-0{margin-right:0!important}.me-sm-1{margin-right:.25rem!important}.me-sm-2{margin-right:.5rem!important}.me-sm-3{margin-right:1rem!important}.me-sm-4{margin-right:1.5rem!important}.me-sm-5{margin-right:3rem!important}.me-sm-auto{margin-right:auto!important}.mb-sm-0{margin-bottom:0!important}.mb-sm-1{margin-bottom:.25rem!important}.mb-sm-2{margin-bottom:.5rem!important}.mb-sm-3{margin-bottom:1rem!important}.mb-sm-4{margin-bottom:1.5rem!important}.mb-sm-5{margin-bottom:3rem!important}.mb-sm-auto{margin-bottom:auto!important}.ms-sm-0{margin-left:0!important}.ms-sm-1{margin-left:.25rem!important}.ms-sm-2{margin-left:.5rem!important}.ms-sm-3{margin-left:1rem!important}.ms-sm-4{margin-left:1.5rem!important}.ms-sm-5{margin-left:3rem!important}.ms-sm-auto{margin-left:auto!important}.p-sm-0{padding:0!important}.p-sm-1{padding:.25rem!important}.p-sm-2{padding:.5rem!important}.p-sm-3{padding:1rem!important}.p-sm-4{padding:1.5rem!important}.p-sm-5{padding:3rem!important}.px-sm-0{padding-right:0!important;padding-left:0!important}.px-sm-1{padding-right:.25rem!important;padding-left:.25rem!important}.px-sm-2{padding-right:.5rem!important;padding-left:.5rem!important}.px-sm-3{padding-right:1rem!important;padding-left:1rem!important}.px-sm-4{padding-right:1.5rem!important;padding-left:1.5rem!important}.px-sm-5{padding-right:3rem!important;padding-left:3rem!important}.py-sm-0{padding-top:0!important;padding-bottom:0!important}.py-sm-1{padding-top:.25rem!important;padding-bottom:.25rem!important}.py-sm-2{padding-top:.5rem!important;padding-bottom:.5rem!important}.py-sm-3{padding-top:1rem!important;padding-bottom:1rem!important}.py-sm-4{padding-top:1.5rem!important;padding-bottom:1.5rem!important}.py-sm-5{padding-top:3rem!important;padding-bottom:3rem!important}.pt-sm-0{padding-top:0!important}.pt-sm-1{padding-top:.25rem!important}.pt-sm-2{padding-top:.5rem!important}.pt-sm-3{padding-top:1rem!important}.pt-sm-4{padding-top:1.5rem!important}.pt-sm-5{padding-top:3rem!important}.pe-sm-0{padding-right:0!important}.pe-sm-1{padding-right:.25rem!important}.pe-sm-2{padding-right:.5rem!important}.pe-sm-3{padding-right:1rem!important}.pe-sm-4{padding-right:1.5rem!important}.pe-sm-5{padding-right:3rem!important}.pb-sm-0{padding-bottom:0!important}.pb-sm-1{padding-bottom:.25rem!important}.pb-sm-2{padding-bottom:.5rem!important}.pb-sm-3{padding-bottom:1rem!important}.pb-sm-4{padding-bottom:1.5rem!important}.pb-sm-5{padding-bottom:3rem!important}.ps-sm-0{padding-left:0!important}.ps-sm-1{padding-left:.25rem!important}.ps-sm-2{padding-left:.5rem!important}.ps-sm-3{padding-left:1rem!important}.ps-sm-4{padding-left:1.5rem!important}.ps-sm-5{padding-left:3rem!important}.text-sm-start{text-align:left!important}.text-sm-end{text-align:right!important}.text-sm-center{text-align:center!important}}@media (min-width:768px){.float-md-start{float:left!important}.float-md-end{float:right!important}.float-md-none{float:none!important}.d-md-inline{display:inline!important}.d-md-inline-block{display:inline-block!important}.d-md-block{display:block!important}.d-md-grid{display:grid!important}.d-md-table{display:table!important}.d-md-table-row{display:table-row!important}.d-md-table-cell{display:table-cell!important}.d-md-flex{display:flex!important}.d-md-inline-flex{display:inline-flex!important}.d-md-none{display:none!important}.flex-md-fill{flex:1 1 auto!important}.flex-md-row{flex-direction:row!important}.flex-md-column{flex-direction:column!important}.flex-md-row-reverse{flex-direction:row-reverse!important}.flex-md-column-reverse{flex-direction:column-reverse!important}.flex-md-grow-0{flex-grow:0!important}.flex-md-grow-1{flex-grow:1!important}.flex-md-shrink-0{flex-shrink:0!important}.flex-md-shrink-1{flex-shrink:1!important}.flex-md-wrap{flex-wrap:wrap!important}.flex-md-nowrap{flex-wrap:nowrap!important}.flex-md-wrap-reverse{flex-wrap:wrap-reverse!important}.gap-md-0{gap:0!important}.gap-md-1{gap:.25rem!important}.gap-md-2{gap:.5rem!important}.gap-md-3{gap:1rem!important}.gap-md-4{gap:1.5rem!important}.gap-md-5{gap:3rem!important}.justify-content-md-start{justify-content:flex-start!important}.justify-content-md-end{justify-content:flex-end!important}.justify-content-md-center{justify-content:center!important}.justify-content-md-between{justify-content:space-between!important}.justify-content-md-around{justify-content:space-around!important}.justify-content-md-evenly{justify-content:space-evenly!important}.align-items-md-start{align-items:flex-start!important}.align-items-md-end{align-items:flex-end!important}.align-items-md-center{align-items:center!important}.align-items-md-baseline{align-items:baseline!important}.align-items-md-stretch{align-items:stretch!important}.align-content-md-start{align-content:flex-start!important}.align-content-md-end{align-content:flex-end!important}.align-content-md-center{align-content:center!important}.align-content-md-between{align-content:space-between!important}.align-content-md-around{align-content:space-around!important}.align-content-md-stretch{align-content:stretch!important}.align-self-md-auto{align-self:auto!important}.align-self-md-start{align-self:flex-start!important}.align-self-md-end{align-self:flex-end!important}.align-self-md-center{align-self:center!important}.align-self-md-baseline{align-self:baseline!important}.align-self-md-stretch{align-self:stretch!important}.order-md-first{order:-1!important}.order-md-0{order:0!important}.order-md-1{order:1!important}.order-md-2{order:2!important}.order-md-3{order:3!important}.order-md-4{order:4!important}.order-md-5{order:5!important}.order-md-last{order:6!important}.m-md-0{margin:0!important}.m-md-1{margin:.25rem!important}.m-md-2{margin:.5rem!important}.m-md-3{margin:1rem!important}.m-md-4{margin:1.5rem!important}.m-md-5{margin:3rem!important}.m-md-auto{margin:auto!important}.mx-md-0{margin-right:0!important;margin-left:0!important}.mx-md-1{margin-right:.25rem!important;margin-left:.25rem!important}.mx-md-2{margin-right:.5rem!important;margin-left:.5rem!important}.mx-md-3{margin-right:1rem!important;margin-left:1rem!important}.mx-md-4{margin-right:1.5rem!important;margin-left:1.5rem!important}.mx-md-5{margin-right:3rem!important;margin-left:3rem!important}.mx-md-auto{margin-right:auto!important;margin-left:auto!important}.my-md-0{margin-top:0!important;margin-bottom:0!important}.my-md-1{margin-top:.25rem!important;margin-bottom:.25rem!important}.my-md-2{margin-top:.5rem!important;margin-bottom:.5rem!important}.my-md-3{margin-top:1rem!important;margin-bottom:1rem!important}.my-md-4{margin-top:1.5rem!important;margin-bottom:1.5rem!important}.my-md-5{margin-top:3rem!important;margin-bottom:3rem!important}.my-md-auto{margin-top:auto!important;margin-bottom:auto!important}.mt-md-0{margin-top:0!important}.mt-md-1{margin-top:.25rem!important}.mt-md-2{margin-top:.5rem!important}.mt-md-3{margin-top:1rem!important}.mt-md-4{margin-top:1.5rem!important}.mt-md-5{margin-top:3rem!important}.mt-md-auto{margin-top:auto!important}.me-md-0{margin-right:0!important}.me-md-1{margin-right:.25rem!important}.me-md-2{margin-right:.5rem!important}.me-md-3{margin-right:1rem!important}.me-md-4{margin-right:1.5rem!important}.me-md-5{margin-right:3rem!important}.me-md-auto{margin-right:auto!important}.mb-md-0{margin-bottom:0!important}.mb-md-1{margin-bottom:.25rem!important}.mb-md-2{margin-bottom:.5rem!important}.mb-md-3{margin-bottom:1rem!important}.mb-md-4{margin-bottom:1.5rem!important}.mb-md-5{margin-bottom:3rem!important}.mb-md-auto{margin-bottom:auto!important}.ms-md-0{margin-left:0!important}.ms-md-1{margin-left:.25rem!important}.ms-md-2{margin-left:.5rem!important}.ms-md-3{margin-left:1rem!important}.ms-md-4{margin-left:1.5rem!important}.ms-md-5{margin-left:3rem!important}.ms-md-auto{margin-left:auto!important}.p-md-0{padding:0!important}.p-md-1{padding:.25rem!important}.p-md-2{padding:.5rem!important}.p-md-3{padding:1rem!important}.p-md-4{padding:1.5rem!important}.p-md-5{padding:3rem!important}.px-md-0{padding-right:0!important;padding-left:0!important}.px-md-1{padding-right:.25rem!important;padding-left:.25rem!important}.px-md-2{padding-right:.5rem!important;padding-left:.5rem!important}.px-md-3{padding-right:1rem!important;padding-left:1rem!important}.px-md-4{padding-right:1.5rem!important;padding-left:1.5rem!important}.px-md-5{padding-right:3rem!important;padding-left:3rem!important}.py-md-0{padding-top:0!important;padding-bottom:0!important}.py-md-1{padding-top:.25rem!important;padding-bottom:.25rem!important}.py-md-2{padding-top:.5rem!important;padding-bottom:.5rem!important}.py-md-3{padding-top:1rem!important;padding-bottom:1rem!important}.py-md-4{padding-top:1.5rem!important;padding-bottom:1.5rem!important}.py-md-5{padding-top:3rem!important;padding-bottom:3rem!important}.pt-md-0{padding-top:0!important}.pt-md-1{padding-top:.25rem!important}.pt-md-2{padding-top:.5rem!important}.pt-md-3{padding-top:1rem!important}.pt-md-4{padding-top:1.5rem!important}.pt-md-5{padding-top:3rem!important}.pe-md-0{padding-right:0!important}.pe-md-1{padding-right:.25rem!important}.pe-md-2{padding-right:.5rem!important}.pe-md-3{padding-right:1rem!important}.pe-md-4{padding-right:1.5rem!important}.pe-md-5{padding-right:3rem!important}.pb-md-0{padding-bottom:0!important}.pb-md-1{padding-bottom:.25rem!important}.pb-md-2{padding-bottom:.5rem!important}.pb-md-3{padding-bottom:1rem!important}.pb-md-4{padding-bottom:1.5rem!important}.pb-md-5{padding-bottom:3rem!important}.ps-md-0{padding-left:0!important}.ps-md-1{padding-left:.25rem!important}.ps-md-2{padding-left:.5rem!important}.ps-md-3{padding-left:1rem!important}.ps-md-4{padding-left:1.5rem!important}.ps-md-5{padding-left:3rem!important}.text-md-start{text-align:left!important}.text-md-end{text-align:right!important}.text-md-center{text-align:center!important}}@media (min-width:992px){.float-lg-start{float:left!important}.float-lg-end{float:right!important}.float-lg-none{float:none!important}.d-lg-inline{display:inline!important}.d-lg-inline-block{display:inline-block!important}.d-lg-block{display:block!important}.d-lg-grid{display:grid!important}.d-lg-table{display:table!important}.d-lg-table-row{display:table-row!important}.d-lg-table-cell{display:table-cell!important}.d-lg-flex{display:flex!important}.d-lg-inline-flex{display:inline-flex!important}.d-lg-none{display:none!important}.flex-lg-fill{flex:1 1 auto!important}.flex-lg-row{flex-direction:row!important}.flex-lg-column{flex-direction:column!important}.flex-lg-row-reverse{flex-direction:row-reverse!important}.flex-lg-column-reverse{flex-direction:column-reverse!important}.flex-lg-grow-0{flex-grow:0!important}.flex-lg-grow-1{flex-grow:1!important}.flex-lg-shrink-0{flex-shrink:0!important}.flex-lg-shrink-1{flex-shrink:1!important}.flex-lg-wrap{flex-wrap:wrap!important}.flex-lg-nowrap{flex-wrap:nowrap!important}.flex-lg-wrap-reverse{flex-wrap:wrap-reverse!important}.gap-lg-0{gap:0!important}.gap-lg-1{gap:.25rem!important}.gap-lg-2{gap:.5rem!important}.gap-lg-3{gap:1rem!important}.gap-lg-4{gap:1.5rem!important}.gap-lg-5{gap:3rem!important}.justify-content-lg-start{justify-content:flex-start!important}.justify-content-lg-end{justify-content:flex-end!important}.justify-content-lg-center{justify-content:center!important}.justify-content-lg-between{justify-content:space-between!important}.justify-content-lg-around{justify-content:space-around!important}.justify-content-lg-evenly{justify-content:space-evenly!important}.align-items-lg-start{align-items:flex-start!important}.align-items-lg-end{align-items:flex-end!important}.align-items-lg-center{align-items:center!important}.align-items-lg-baseline{align-items:baseline!important}.align-items-lg-stretch{align-items:stretch!important}.align-content-lg-start{align-content:flex-start!important}.align-content-lg-end{align-content:flex-end!important}.align-content-lg-center{align-content:center!important}.align-content-lg-between{align-content:space-between!important}.align-content-lg-around{align-content:space-around!important}.align-content-lg-stretch{align-content:stretch!important}.align-self-lg-auto{align-self:auto!important}.align-self-lg-start{align-self:flex-start!important}.align-self-lg-end{align-self:flex-end!important}.align-self-lg-center{align-self:center!important}.align-self-lg-baseline{align-self:baseline!important}.align-self-lg-stretch{align-self:stretch!important}.order-lg-first{order:-1!important}.order-lg-0{order:0!important}.order-lg-1{order:1!important}.order-lg-2{order:2!important}.order-lg-3{order:3!important}.order-lg-4{order:4!important}.order-lg-5{order:5!important}.order-lg-last{order:6!important}.m-lg-0{margin:0!important}.m-lg-1{margin:.25rem!important}.m-lg-2{margin:.5rem!important}.m-lg-3{margin:1rem!important}.m-lg-4{margin:1.5rem!important}.m-lg-5{margin:3rem!important}.m-lg-auto{margin:auto!important}.mx-lg-0{margin-right:0!important;margin-left:0!important}.mx-lg-1{margin-right:.25rem!important;margin-left:.25rem!important}.mx-lg-2{margin-right:.5rem!important;margin-left:.5rem!important}.mx-lg-3{margin-right:1rem!important;margin-left:1rem!important}.mx-lg-4{margin-right:1.5rem!important;margin-left:1.5rem!important}.mx-lg-5{margin-right:3rem!important;margin-left:3rem!important}.mx-lg-auto{margin-right:auto!important;margin-left:auto!important}.my-lg-0{margin-top:0!important;margin-bottom:0!important}.my-lg-1{margin-top:.25rem!important;margin-bottom:.25rem!important}.my-lg-2{margin-top:.5rem!important;margin-bottom:.5rem!important}.my-lg-3{margin-top:1rem!important;margin-bottom:1rem!important}.my-lg-4{margin-top:1.5rem!important;margin-bottom:1.5rem!important}.my-lg-5{margin-top:3rem!important;margin-bottom:3rem!important}.my-lg-auto{margin-top:auto!important;margin-bottom:auto!important}.mt-lg-0{margin-top:0!important}.mt-lg-1{margin-top:.25rem!important}.mt-lg-2{margin-top:.5rem!important}.mt-lg-3{margin-top:1rem!important}.mt-lg-4{margin-top:1.5rem!important}.mt-lg-5{margin-top:3rem!important}.mt-lg-auto{margin-top:auto!important}.me-lg-0{margin-right:0!important}.me-lg-1{margin-right:.25rem!important}.me-lg-2{margin-right:.5rem!important}.me-lg-3{margin-right:1rem!important}.me-lg-4{margin-right:1.5rem!important}.me-lg-5{margin-right:3rem!important}.me-lg-auto{margin-right:auto!important}.mb-lg-0{margin-bottom:0!important}.mb-lg-1{margin-bottom:.25rem!important}.mb-lg-2{margin-bottom:.5rem!important}.mb-lg-3{margin-bottom:1rem!important}.mb-lg-4{margin-bottom:1.5rem!important}.mb-lg-5{margin-bottom:3rem!important}.mb-lg-auto{margin-bottom:auto!important}.ms-lg-0{margin-left:0!important}.ms-lg-1{margin-left:.25rem!important}.ms-lg-2{margin-left:.5rem!important}.ms-lg-3{margin-left:1rem!important}.ms-lg-4{margin-left:1.5rem!important}.ms-lg-5{margin-left:3rem!important}.ms-lg-auto{margin-left:auto!important}.p-lg-0{padding:0!important}.p-lg-1{padding:.25rem!important}.p-lg-2{padding:.5rem!important}.p-lg-3{padding:1rem!important}.p-lg-4{padding:1.5rem!important}.p-lg-5{padding:3rem!important}.px-lg-0{padding-right:0!important;padding-left:0!important}.px-lg-1{padding-right:.25rem!important;padding-left:.25rem!important}.px-lg-2{padding-right:.5rem!important;padding-left:.5rem!important}.px-lg-3{padding-right:1rem!important;padding-left:1rem!important}.px-lg-4{padding-right:1.5rem!important;padding-left:1.5rem!important}.px-lg-5{padding-right:3rem!important;padding-left:3rem!important}.py-lg-0{padding-top:0!important;padding-bottom:0!important}.py-lg-1{padding-top:.25rem!important;padding-bottom:.25rem!important}.py-lg-2{padding-top:.5rem!important;padding-bottom:.5rem!important}.py-lg-3{padding-top:1rem!important;padding-bottom:1rem!important}.py-lg-4{padding-top:1.5rem!important;padding-bottom:1.5rem!important}.py-lg-5{padding-top:3rem!important;padding-bottom:3rem!important}.pt-lg-0{padding-top:0!important}.pt-lg-1{padding-top:.25rem!important}.pt-lg-2{padding-top:.5rem!important}.pt-lg-3{padding-top:1rem!important}.pt-lg-4{padding-top:1.5rem!important}.pt-lg-5{padding-top:3rem!important}.pe-lg-0{padding-right:0!important}.pe-lg-1{padding-right:.25rem!important}.pe-lg-2{padding-right:.5rem!important}.pe-lg-3{padding-right:1rem!important}.pe-lg-4{padding-right:1.5rem!important}.pe-lg-5{padding-right:3rem!important}.pb-lg-0{padding-bottom:0!important}.pb-lg-1{padding-bottom:.25rem!important}.pb-lg-2{padding-bottom:.5rem!important}.pb-lg-3{padding-bottom:1rem!important}.pb-lg-4{padding-bottom:1.5rem!important}.pb-lg-5{padding-bottom:3rem!important}.ps-lg-0{padding-left:0!important}.ps-lg-1{padding-left:.25rem!important}.ps-lg-2{padding-left:.5rem!important}.ps-lg-3{padding-left:1rem!important}.ps-lg-4{padding-left:1.5rem!important}.ps-lg-5{padding-left:3rem!important}.text-lg-start{text-align:left!important}.text-lg-end{text-align:right!important}.text-lg-center{text-align:center!important}}@media (min-width:1200px){.float-xl-start{float:left!important}.float-xl-end{float:right!important}.float-xl-none{float:none!important}.d-xl-inline{display:inline!important}.d-xl-inline-block{display:inline-block!important}.d-xl-block{display:block!important}.d-xl-grid{display:grid!important}.d-xl-table{display:table!important}.d-xl-table-row{display:table-row!important}.d-xl-table-cell{display:table-cell!important}.d-xl-flex{display:flex!important}.d-xl-inline-flex{display:inline-flex!important}.d-xl-none{display:none!important}.flex-xl-fill{flex:1 1 auto!important}.flex-xl-row{flex-direction:row!important}.flex-xl-column{flex-direction:column!important}.flex-xl-row-reverse{flex-direction:row-reverse!important}.flex-xl-column-reverse{flex-direction:column-reverse!important}.flex-xl-grow-0{flex-grow:0!important}.flex-xl-grow-1{flex-grow:1!important}.flex-xl-shrink-0{flex-shrink:0!important}.flex-xl-shrink-1{flex-shrink:1!important}.flex-xl-wrap{flex-wrap:wrap!important}.flex-xl-nowrap{flex-wrap:nowrap!important}.flex-xl-wrap-reverse{flex-wrap:wrap-reverse!important}.gap-xl-0{gap:0!important}.gap-xl-1{gap:.25rem!important}.gap-xl-2{gap:.5rem!important}.gap-xl-3{gap:1rem!important}.gap-xl-4{gap:1.5rem!important}.gap-xl-5{gap:3rem!important}.justify-content-xl-start{justify-content:flex-start!important}.justify-content-xl-end{justify-content:flex-end!important}.justify-content-xl-center{justify-content:center!important}.justify-content-xl-between{justify-content:space-between!important}.justify-content-xl-around{justify-content:space-around!important}.justify-content-xl-evenly{justify-content:space-evenly!important}.align-items-xl-start{align-items:flex-start!important}.align-items-xl-end{align-items:flex-end!important}.align-items-xl-center{align-items:center!important}.align-items-xl-baseline{align-items:baseline!important}.align-items-xl-stretch{align-items:stretch!important}.align-content-xl-start{align-content:flex-start!important}.align-content-xl-end{align-content:flex-end!important}.align-content-xl-center{align-content:center!important}.align-content-xl-between{align-content:space-between!important}.align-content-xl-around{align-content:space-around!important}.align-content-xl-stretch{align-content:stretch!important}.align-self-xl-auto{align-self:auto!important}.align-self-xl-start{align-self:flex-start!important}.align-self-xl-end{align-self:flex-end!important}.align-self-xl-center{align-self:center!important}.align-self-xl-baseline{align-self:baseline!important}.align-self-xl-stretch{align-self:stretch!important}.order-xl-first{order:-1!important}.order-xl-0{order:0!important}.order-xl-1{order:1!important}.order-xl-2{order:2!important}.order-xl-3{order:3!important}.order-xl-4{order:4!important}.order-xl-5{order:5!important}.order-xl-last{order:6!important}.m-xl-0{margin:0!important}.m-xl-1{margin:.25rem!important}.m-xl-2{margin:.5rem!important}.m-xl-3{margin:1rem!important}.m-xl-4{margin:1.5rem!important}.m-xl-5{margin:3rem!important}.m-xl-auto{margin:auto!important}.mx-xl-0{margin-right:0!important;margin-left:0!important}.mx-xl-1{margin-right:.25rem!important;margin-left:.25rem!important}.mx-xl-2{margin-right:.5rem!important;margin-left:.5rem!important}.mx-xl-3{margin-right:1rem!important;margin-left:1rem!important}.mx-xl-4{margin-right:1.5rem!important;margin-left:1.5rem!important}.mx-xl-5{margin-right:3rem!important;margin-left:3rem!important}.mx-xl-auto{margin-right:auto!important;margin-left:auto!important}.my-xl-0{margin-top:0!important;margin-bottom:0!important}.my-xl-1{margin-top:.25rem!important;margin-bottom:.25rem!important}.my-xl-2{margin-top:.5rem!important;margin-bottom:.5rem!important}.my-xl-3{margin-top:1rem!important;margin-bottom:1rem!important}.my-xl-4{margin-top:1.5rem!important;margin-bottom:1.5rem!important}.my-xl-5{margin-top:3rem!important;margin-bottom:3rem!important}.my-xl-auto{margin-top:auto!important;margin-bottom:auto!important}.mt-xl-0{margin-top:0!important}.mt-xl-1{margin-top:.25rem!important}.mt-xl-2{margin-top:.5rem!important}.mt-xl-3{margin-top:1rem!important}.mt-xl-4{margin-top:1.5rem!important}.mt-xl-5{margin-top:3rem!important}.mt-xl-auto{margin-top:auto!important}.me-xl-0{margin-right:0!important}.me-xl-1{margin-right:.25rem!important}.me-xl-2{margin-right:.5rem!important}.me-xl-3{margin-right:1rem!important}.me-xl-4{margin-right:1.5rem!important}.me-xl-5{margin-right:3rem!important}.me-xl-auto{margin-right:auto!important}.mb-xl-0{margin-bottom:0!important}.mb-xl-1{margin-bottom:.25rem!important}.mb-xl-2{margin-bottom:.5rem!important}.mb-xl-3{margin-bottom:1rem!important}.mb-xl-4{margin-bottom:1.5rem!important}.mb-xl-5{margin-bottom:3rem!important}.mb-xl-auto{margin-bottom:auto!important}.ms-xl-0{margin-left:0!important}.ms-xl-1{margin-left:.25rem!important}.ms-xl-2{margin-left:.5rem!important}.ms-xl-3{margin-left:1rem!important}.ms-xl-4{margin-left:1.5rem!important}.ms-xl-5{margin-left:3rem!important}.ms-xl-auto{margin-left:auto!important}.p-xl-0{padding:0!important}.p-xl-1{padding:.25rem!important}.p-xl-2{padding:.5rem!important}.p-xl-3{padding:1rem!important}.p-xl-4{padding:1.5rem!important}.p-xl-5{padding:3rem!important}.px-xl-0{padding-right:0!important;padding-left:0!important}.px-xl-1{padding-right:.25rem!important;padding-left:.25rem!important}.px-xl-2{padding-right:.5rem!important;padding-left:.5rem!important}.px-xl-3{padding-right:1rem!important;padding-left:1rem!important}.px-xl-4{padding-right:1.5rem!important;padding-left:1.5rem!important}.px-xl-5{padding-right:3rem!important;padding-left:3rem!important}.py-xl-0{padding-top:0!important;padding-bottom:0!important}.py-xl-1{padding-top:.25rem!important;padding-bottom:.25rem!important}.py-xl-2{padding-top:.5rem!important;padding-bottom:.5rem!important}.py-xl-3{padding-top:1rem!important;padding-bottom:1rem!important}.py-xl-4{padding-top:1.5rem!important;padding-bottom:1.5rem!important}.py-xl-5{padding-top:3rem!important;padding-bottom:3rem!important}.pt-xl-0{padding-top:0!important}.pt-xl-1{padding-top:.25rem!important}.pt-xl-2{padding-top:.5rem!important}.pt-xl-3{padding-top:1rem!important}.pt-xl-4{padding-top:1.5rem!important}.pt-xl-5{padding-top:3rem!important}.pe-xl-0{padding-right:0!important}.pe-xl-1{padding-right:.25rem!important}.pe-xl-2{padding-right:.5rem!important}.pe-xl-3{padding-right:1rem!important}.pe-xl-4{padding-right:1.5rem!important}.pe-xl-5{padding-right:3rem!important}.pb-xl-0{padding-bottom:0!important}.pb-xl-1{padding-bottom:.25rem!important}.pb-xl-2{padding-bottom:.5rem!important}.pb-xl-3{padding-bottom:1rem!important}.pb-xl-4{padding-bottom:1.5rem!important}.pb-xl-5{padding-bottom:3rem!important}.ps-xl-0{padding-left:0!important}.ps-xl-1{padding-left:.25rem!important}.ps-xl-2{padding-left:.5rem!important}.ps-xl-3{padding-left:1rem!important}.ps-xl-4{padding-left:1.5rem!important}.ps-xl-5{padding-left:3rem!important}.text-xl-start{text-align:left!important}.text-xl-end{text-align:right!important}.text-xl-center{text-align:center!important}}@media (min-width:1400px){.float-xxl-start{float:left!important}.float-xxl-end{float:right!important}.float-xxl-none{float:none!important}.d-xxl-inline{display:inline!important}.d-xxl-inline-block{display:inline-block!important}.d-xxl-block{display:block!important}.d-xxl-grid{display:grid!important}.d-xxl-table{display:table!important}.d-xxl-table-row{display:table-row!important}.d-xxl-table-cell{display:table-cell!important}.d-xxl-flex{display:flex!important}.d-xxl-inline-flex{display:inline-flex!important}.d-xxl-none{display:none!important}.flex-xxl-fill{flex:1 1 auto!important}.flex-xxl-row{flex-direction:row!important}.flex-xxl-column{flex-direction:column!important}.flex-xxl-row-reverse{flex-direction:row-reverse!important}.flex-xxl-column-reverse{flex-direction:column-reverse!important}.flex-xxl-grow-0{flex-grow:0!important}.flex-xxl-grow-1{flex-grow:1!important}.flex-xxl-shrink-0{flex-shrink:0!important}.flex-xxl-shrink-1{flex-shrink:1!important}.flex-xxl-wrap{flex-wrap:wrap!important}.flex-xxl-nowrap{flex-wrap:nowrap!important}.flex-xxl-wrap-reverse{flex-wrap:wrap-reverse!important}.gap-xxl-0{gap:0!important}.gap-xxl-1{gap:.25rem!important}.gap-xxl-2{gap:.5rem!important}.gap-xxl-3{gap:1rem!important}.gap-xxl-4{gap:1.5rem!important}.gap-xxl-5{gap:3rem!important}.justify-content-xxl-start{justify-content:flex-start!important}.justify-content-xxl-end{justify-content:flex-end!important}.justify-content-xxl-center{justify-content:center!important}.justify-content-xxl-between{justify-content:space-between!important}.justify-content-xxl-around{justify-content:space-around!important}.justify-content-xxl-evenly{justify-content:space-evenly!important}.align-items-xxl-start{align-items:flex-start!important}.align-items-xxl-end{align-items:flex-end!important}.align-items-xxl-center{align-items:center!important}.align-items-xxl-baseline{align-items:baseline!important}.align-items-xxl-stretch{align-items:stretch!important}.align-content-xxl-start{align-content:flex-start!important}.align-content-xxl-end{align-content:flex-end!important}.align-content-xxl-center{align-content:center!important}.align-content-xxl-between{align-content:space-between!important}.align-content-xxl-around{align-content:space-around!important}.align-content-xxl-stretch{align-content:stretch!important}.align-self-xxl-auto{align-self:auto!important}.align-self-xxl-start{align-self:flex-start!important}.align-self-xxl-end{align-self:flex-end!important}.align-self-xxl-center{align-self:center!important}.align-self-xxl-baseline{align-self:baseline!important}.align-self-xxl-stretch{align-self:stretch!important}.order-xxl-first{order:-1!important}.order-xxl-0{order:0!important}.order-xxl-1{order:1!important}.order-xxl-2{order:2!important}.order-xxl-3{order:3!important}.order-xxl-4{order:4!important}.order-xxl-5{order:5!important}.order-xxl-last{order:6!important}.m-xxl-0{margin:0!important}.m-xxl-1{margin:.25rem!important}.m-xxl-2{margin:.5rem!important}.m-xxl-3{margin:1rem!important}.m-xxl-4{margin:1.5rem!important}.m-xxl-5{margin:3rem!important}.m-xxl-auto{margin:auto!important}.mx-xxl-0{margin-right:0!important;margin-left:0!important}.mx-xxl-1{margin-right:.25rem!important;margin-left:.25rem!important}.mx-xxl-2{margin-right:.5rem!important;margin-left:.5rem!important}.mx-xxl-3{margin-right:1rem!important;margin-left:1rem!important}.mx-xxl-4{margin-right:1.5rem!important;margin-left:1.5rem!important}.mx-xxl-5{margin-right:3rem!important;margin-left:3rem!important}.mx-xxl-auto{margin-right:auto!important;margin-left:auto!important}.my-xxl-0{margin-top:0!important;margin-bottom:0!important}.my-xxl-1{margin-top:.25rem!important;margin-bottom:.25rem!important}.my-xxl-2{margin-top:.5rem!important;margin-bottom:.5rem!important}.my-xxl-3{margin-top:1rem!important;margin-bottom:1rem!important}.my-xxl-4{margin-top:1.5rem!important;margin-bottom:1.5rem!important}.my-xxl-5{margin-top:3rem!important;margin-bottom:3rem!important}.my-xxl-auto{margin-top:auto!important;margin-bottom:auto!important}.mt-xxl-0{margin-top:0!important}.mt-xxl-1{margin-top:.25rem!important}.mt-xxl-2{margin-top:.5rem!important}.mt-xxl-3{margin-top:1rem!important}.mt-xxl-4{margin-top:1.5rem!important}.mt-xxl-5{margin-top:3rem!important}.mt-xxl-auto{margin-top:auto!important}.me-xxl-0{margin-right:0!important}.me-xxl-1{margin-right:.25rem!important}.me-xxl-2{margin-right:.5rem!important}.me-xxl-3{margin-right:1rem!important}.me-xxl-4{margin-right:1.5rem!important}.me-xxl-5{margin-right:3rem!important}.me-xxl-auto{margin-right:auto!important}.mb-xxl-0{margin-bottom:0!important}.mb-xxl-1{margin-bottom:.25rem!important}.mb-xxl-2{margin-bottom:.5rem!important}.mb-xxl-3{margin-bottom:1rem!important}.mb-xxl-4{margin-bottom:1.5rem!important}.mb-xxl-5{margin-bottom:3rem!important}.mb-xxl-auto{margin-bottom:auto!important}.ms-xxl-0{margin-left:0!important}.ms-xxl-1{margin-left:.25rem!important}.ms-xxl-2{margin-left:.5rem!important}.ms-xxl-3{margin-left:1rem!important}.ms-xxl-4{margin-left:1.5rem!important}.ms-xxl-5{margin-left:3rem!important}.ms-xxl-auto{margin-left:auto!important}.p-xxl-0{padding:0!important}.p-xxl-1{padding:.25rem!important}.p-xxl-2{padding:.5rem!important}.p-xxl-3{padding:1rem!important}.p-xxl-4{padding:1.5rem!important}.p-xxl-5{padding:3rem!important}.px-xxl-0{padding-right:0!important;padding-left:0!important}.px-xxl-1{padding-right:.25rem!important;padding-left:.25rem!important}.px-xxl-2{padding-right:.5rem!important;padding-left:.5rem!important}.px-xxl-3{padding-right:1rem!important;padding-left:1rem!important}.px-xxl-4{padding-right:1.5rem!important;padding-left:1.5rem!important}.px-xxl-5{padding-right:3rem!important;padding-left:3rem!important}.py-xxl-0{padding-top:0!important;padding-bottom:0!important}.py-xxl-1{padding-top:.25rem!important;padding-bottom:.25rem!important}.py-xxl-2{padding-top:.5rem!important;padding-bottom:.5rem!important}.py-xxl-3{padding-top:1rem!important;padding-bottom:1rem!important}.py-xxl-4{padding-top:1.5rem!important;padding-bottom:1.5rem!important}.py-xxl-5{padding-top:3rem!important;padding-bottom:3rem!important}.pt-xxl-0{padding-top:0!important}.pt-xxl-1{padding-top:.25rem!important}.pt-xxl-2{padding-top:.5rem!important}.pt-xxl-3{padding-top:1rem!important}.pt-xxl-4{padding-top:1.5rem!important}.pt-xxl-5{padding-top:3rem!important}.pe-xxl-0{padding-right:0!important}.pe-xxl-1{padding-right:.25rem!important}.pe-xxl-2{padding-right:.5rem!important}.pe-xxl-3{padding-right:1rem!important}.pe-xxl-4{padding-right:1.5rem!important}.pe-xxl-5{padding-right:3rem!important}.pb-xxl-0{padding-bottom:0!important}.pb-xxl-1{padding-bottom:.25rem!important}.pb-xxl-2{padding-bottom:.5rem!important}.pb-xxl-3{padding-bottom:1rem!important}.pb-xxl-4{padding-bottom:1.5rem!important}.pb-xxl-5{padding-bottom:3rem!important}.ps-xxl-0{padding-left:0!important}.ps-xxl-1{padding-left:.25rem!important}.ps-xxl-2{padding-left:.5rem!important}.ps-xxl-3{padding-left:1rem!important}.ps-xxl-4{padding-left:1.5rem!important}.ps-xxl-5{padding-left:3rem!important}.text-xxl-start{text-align:left!important}.text-xxl-end{text-align:right!important}.text-xxl-center{text-align:center!important}}@media (min-width:1200px){.fs-1{font-size:2.5rem!important}.fs-2{font-size:2rem!important}.fs-3{font-size:1.75rem!important}.fs-4{font-size:1.5rem!important}}@media print{.d-print-inline{display:inline!important}.d-print-inline-block{display:inline-block!important}.d-print-block{display:block!important}.d-print-grid{display:grid!important}.d-print-table{display:table!important}.d-print-table-row{display:table-row!important}.d-print-table-cell{display:table-cell!important}.d-print-flex{display:flex!important}.d-print-inline-flex{display:inline-flex!important}.d-print-none{display:none!important}} +/*# sourceMappingURL=bootstrap.min.css.map */ \ No newline at end of file diff --git a/BlazorTestApp/wwwroot/css/bootstrap/bootstrap.min.css.map b/BlazorTestApp/wwwroot/css/bootstrap/bootstrap.min.css.map new file mode 100644 index 00000000..afcd9e33 --- /dev/null +++ b/BlazorTestApp/wwwroot/css/bootstrap/bootstrap.min.css.map @@ -0,0 +1 @@ +{"version":3,"sources":["../../scss/bootstrap.scss","../../scss/_root.scss","../../scss/_reboot.scss","dist/css/bootstrap.css","../../scss/vendor/_rfs.scss","../../scss/mixins/_border-radius.scss","../../scss/_type.scss","../../scss/mixins/_lists.scss","../../scss/_images.scss","../../scss/mixins/_image.scss","../../scss/_containers.scss","../../scss/mixins/_container.scss","../../scss/mixins/_breakpoints.scss","../../scss/_grid.scss","../../scss/mixins/_grid.scss","../../scss/_tables.scss","../../scss/mixins/_table-variants.scss","../../scss/forms/_labels.scss","../../scss/forms/_form-text.scss","../../scss/forms/_form-control.scss","../../scss/mixins/_transition.scss","../../scss/mixins/_gradients.scss","../../scss/forms/_form-select.scss","../../scss/forms/_form-check.scss","../../scss/forms/_form-range.scss","../../scss/forms/_floating-labels.scss","../../scss/forms/_input-group.scss","../../scss/mixins/_forms.scss","../../scss/_buttons.scss","../../scss/mixins/_buttons.scss","../../scss/_transitions.scss","../../scss/_dropdown.scss","../../scss/mixins/_caret.scss","../../scss/_button-group.scss","../../scss/_nav.scss","../../scss/_navbar.scss","../../scss/_card.scss","../../scss/_accordion.scss","../../scss/_breadcrumb.scss","../../scss/_pagination.scss","../../scss/mixins/_pagination.scss","../../scss/_badge.scss","../../scss/_alert.scss","../../scss/mixins/_alert.scss","../../scss/_progress.scss","../../scss/_list-group.scss","../../scss/mixins/_list-group.scss","../../scss/_close.scss","../../scss/_toasts.scss","../../scss/_modal.scss","../../scss/mixins/_backdrop.scss","../../scss/_tooltip.scss","../../scss/mixins/_reset-text.scss","../../scss/_popover.scss","../../scss/_carousel.scss","../../scss/mixins/_clearfix.scss","../../scss/_spinners.scss","../../scss/_offcanvas.scss","../../scss/_placeholders.scss","../../scss/helpers/_colored-links.scss","../../scss/helpers/_ratio.scss","../../scss/helpers/_position.scss","../../scss/helpers/_stacks.scss","../../scss/helpers/_visually-hidden.scss","../../scss/mixins/_visually-hidden.scss","../../scss/helpers/_stretched-link.scss","../../scss/helpers/_text-truncation.scss","../../scss/mixins/_text-truncate.scss","../../scss/helpers/_vr.scss","../../scss/mixins/_utilities.scss","../../scss/utilities/_api.scss"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Bootstrap v5.1.0 (https://getbootstrap.com/)\n * Copyright 2011-2021 The Bootstrap Authors\n * Copyright 2011-2021 Twitter, Inc.\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n */\n\n// scss-docs-start import-stack\n// Configuration\n@import \"functions\";\n@import \"variables\";\n@import \"mixins\";\n@import \"utilities\";\n\n// Layout & components\n@import \"root\";\n@import \"reboot\";\n@import \"type\";\n@import \"images\";\n@import \"containers\";\n@import \"grid\";\n@import \"tables\";\n@import \"forms\";\n@import \"buttons\";\n@import \"transitions\";\n@import \"dropdown\";\n@import \"button-group\";\n@import \"nav\";\n@import \"navbar\";\n@import \"card\";\n@import \"accordion\";\n@import \"breadcrumb\";\n@import \"pagination\";\n@import \"badge\";\n@import \"alert\";\n@import \"progress\";\n@import \"list-group\";\n@import \"close\";\n@import \"toasts\";\n@import \"modal\";\n@import \"tooltip\";\n@import \"popover\";\n@import \"carousel\";\n@import \"spinners\";\n@import \"offcanvas\";\n@import \"placeholders\";\n\n// Helpers\n@import \"helpers\";\n\n// Utilities\n@import \"utilities/api\";\n// scss-docs-end import-stack\n",":root {\n // Note: Custom variable values only support SassScript inside `#{}`.\n\n // Colors\n //\n // Generate palettes for full colors, grays, and theme colors.\n\n @each $color, $value in $colors {\n --#{$variable-prefix}#{$color}: #{$value};\n }\n\n @each $color, $value in $grays {\n --#{$variable-prefix}gray-#{$color}: #{$value};\n }\n\n @each $color, $value in $theme-colors {\n --#{$variable-prefix}#{$color}: #{$value};\n }\n\n @each $color, $value in $theme-colors-rgb {\n --#{$variable-prefix}#{$color}-rgb: #{$value};\n }\n\n --#{$variable-prefix}white-rgb: #{to-rgb($white)};\n --#{$variable-prefix}black-rgb: #{to-rgb($black)};\n --#{$variable-prefix}body-rgb: #{to-rgb($body-color)};\n\n // Fonts\n\n // Note: Use `inspect` for lists so that quoted items keep the quotes.\n // See https://github.com/sass/sass/issues/2383#issuecomment-336349172\n --#{$variable-prefix}font-sans-serif: #{inspect($font-family-sans-serif)};\n --#{$variable-prefix}font-monospace: #{inspect($font-family-monospace)};\n --#{$variable-prefix}gradient: #{$gradient};\n\n // Root and body\n // stylelint-disable custom-property-empty-line-before\n // scss-docs-start root-body-variables\n @if $font-size-root != null {\n --#{$variable-prefix}root-font-size: #{$font-size-root};\n }\n --#{$variable-prefix}body-font-family: #{$font-family-base};\n --#{$variable-prefix}body-font-size: #{$font-size-base};\n --#{$variable-prefix}body-font-weight: #{$font-weight-base};\n --#{$variable-prefix}body-line-height: #{$line-height-base};\n --#{$variable-prefix}body-color: #{$body-color};\n @if $body-text-align != null {\n --#{$variable-prefix}body-text-align: #{$body-text-align};\n }\n --#{$variable-prefix}body-bg: #{$body-bg};\n // scss-docs-end root-body-variables\n // stylelint-enable custom-property-empty-line-before\n}\n","// stylelint-disable declaration-no-important, selector-no-qualifying-type, property-no-vendor-prefix\n\n\n// Reboot\n//\n// Normalization of HTML elements, manually forked from Normalize.css to remove\n// styles targeting irrelevant browsers while applying new styles.\n//\n// Normalize is licensed MIT. https://github.com/necolas/normalize.css\n\n\n// Document\n//\n// Change from `box-sizing: content-box` so that `width` is not affected by `padding` or `border`.\n\n*,\n*::before,\n*::after {\n box-sizing: border-box;\n}\n\n\n// Root\n//\n// Ability to the value of the root font sizes, affecting the value of `rem`.\n// null by default, thus nothing is generated.\n\n:root {\n @if $font-size-root != null {\n font-size: var(--#{$variable-prefix}-root-font-size);\n }\n\n @if $enable-smooth-scroll {\n @media (prefers-reduced-motion: no-preference) {\n scroll-behavior: smooth;\n }\n }\n}\n\n\n// Body\n//\n// 1. Remove the margin in all browsers.\n// 2. As a best practice, apply a default `background-color`.\n// 3. Prevent adjustments of font size after orientation changes in iOS.\n// 4. Change the default tap highlight to be completely transparent in iOS.\n\n// scss-docs-start reboot-body-rules\nbody {\n margin: 0; // 1\n font-family: var(--#{$variable-prefix}body-font-family);\n @include font-size(var(--#{$variable-prefix}body-font-size));\n font-weight: var(--#{$variable-prefix}body-font-weight);\n line-height: var(--#{$variable-prefix}body-line-height);\n color: var(--#{$variable-prefix}body-color);\n text-align: var(--#{$variable-prefix}body-text-align);\n background-color: var(--#{$variable-prefix}body-bg); // 2\n -webkit-text-size-adjust: 100%; // 3\n -webkit-tap-highlight-color: rgba($black, 0); // 4\n}\n// scss-docs-end reboot-body-rules\n\n\n// Content grouping\n//\n// 1. Reset Firefox's gray color\n// 2. Set correct height and prevent the `size` attribute to make the `hr` look like an input field\n\nhr {\n margin: $hr-margin-y 0;\n color: $hr-color; // 1\n background-color: currentColor;\n border: 0;\n opacity: $hr-opacity;\n}\n\nhr:not([size]) {\n height: $hr-height; // 2\n}\n\n\n// Typography\n//\n// 1. Remove top margins from headings\n// By default, `

`-`

` all receive top and bottom margins. We nuke the top\n// margin for easier control within type scales as it avoids margin collapsing.\n\n%heading {\n margin-top: 0; // 1\n margin-bottom: $headings-margin-bottom;\n font-family: $headings-font-family;\n font-style: $headings-font-style;\n font-weight: $headings-font-weight;\n line-height: $headings-line-height;\n color: $headings-color;\n}\n\nh1 {\n @extend %heading;\n @include font-size($h1-font-size);\n}\n\nh2 {\n @extend %heading;\n @include font-size($h2-font-size);\n}\n\nh3 {\n @extend %heading;\n @include font-size($h3-font-size);\n}\n\nh4 {\n @extend %heading;\n @include font-size($h4-font-size);\n}\n\nh5 {\n @extend %heading;\n @include font-size($h5-font-size);\n}\n\nh6 {\n @extend %heading;\n @include font-size($h6-font-size);\n}\n\n\n// Reset margins on paragraphs\n//\n// Similarly, the top margin on `

`s get reset. However, we also reset the\n// bottom margin to use `rem` units instead of `em`.\n\np {\n margin-top: 0;\n margin-bottom: $paragraph-margin-bottom;\n}\n\n\n// Abbreviations\n//\n// 1. Duplicate behavior to the data-bs-* attribute for our tooltip plugin\n// 2. Add the correct text decoration in Chrome, Edge, Opera, and Safari.\n// 3. Add explicit cursor to indicate changed behavior.\n// 4. Prevent the text-decoration to be skipped.\n\nabbr[title],\nabbr[data-bs-original-title] { // 1\n text-decoration: underline dotted; // 2\n cursor: help; // 3\n text-decoration-skip-ink: none; // 4\n}\n\n\n// Address\n\naddress {\n margin-bottom: 1rem;\n font-style: normal;\n line-height: inherit;\n}\n\n\n// Lists\n\nol,\nul {\n padding-left: 2rem;\n}\n\nol,\nul,\ndl {\n margin-top: 0;\n margin-bottom: 1rem;\n}\n\nol ol,\nul ul,\nol ul,\nul ol {\n margin-bottom: 0;\n}\n\ndt {\n font-weight: $dt-font-weight;\n}\n\n// 1. Undo browser default\n\ndd {\n margin-bottom: .5rem;\n margin-left: 0; // 1\n}\n\n\n// Blockquote\n\nblockquote {\n margin: 0 0 1rem;\n}\n\n\n// Strong\n//\n// Add the correct font weight in Chrome, Edge, and Safari\n\nb,\nstrong {\n font-weight: $font-weight-bolder;\n}\n\n\n// Small\n//\n// Add the correct font size in all browsers\n\nsmall {\n @include font-size($small-font-size);\n}\n\n\n// Mark\n\nmark {\n padding: $mark-padding;\n background-color: $mark-bg;\n}\n\n\n// Sub and Sup\n//\n// Prevent `sub` and `sup` elements from affecting the line height in\n// all browsers.\n\nsub,\nsup {\n position: relative;\n @include font-size($sub-sup-font-size);\n line-height: 0;\n vertical-align: baseline;\n}\n\nsub { bottom: -.25em; }\nsup { top: -.5em; }\n\n\n// Links\n\na {\n color: $link-color;\n text-decoration: $link-decoration;\n\n &:hover {\n color: $link-hover-color;\n text-decoration: $link-hover-decoration;\n }\n}\n\n// And undo these styles for placeholder links/named anchors (without href).\n// It would be more straightforward to just use a[href] in previous block, but that\n// causes specificity issues in many other styles that are too complex to fix.\n// See https://github.com/twbs/bootstrap/issues/19402\n\na:not([href]):not([class]) {\n &,\n &:hover {\n color: inherit;\n text-decoration: none;\n }\n}\n\n\n// Code\n\npre,\ncode,\nkbd,\nsamp {\n font-family: $font-family-code;\n @include font-size(1em); // Correct the odd `em` font sizing in all browsers.\n direction: ltr #{\"/* rtl:ignore */\"};\n unicode-bidi: bidi-override;\n}\n\n// 1. Remove browser default top margin\n// 2. Reset browser default of `1em` to use `rem`s\n// 3. Don't allow content to break outside\n\npre {\n display: block;\n margin-top: 0; // 1\n margin-bottom: 1rem; // 2\n overflow: auto; // 3\n @include font-size($code-font-size);\n color: $pre-color;\n\n // Account for some code outputs that place code tags in pre tags\n code {\n @include font-size(inherit);\n color: inherit;\n word-break: normal;\n }\n}\n\ncode {\n @include font-size($code-font-size);\n color: $code-color;\n word-wrap: break-word;\n\n // Streamline the style when inside anchors to avoid broken underline and more\n a > & {\n color: inherit;\n }\n}\n\nkbd {\n padding: $kbd-padding-y $kbd-padding-x;\n @include font-size($kbd-font-size);\n color: $kbd-color;\n background-color: $kbd-bg;\n @include border-radius($border-radius-sm);\n\n kbd {\n padding: 0;\n @include font-size(1em);\n font-weight: $nested-kbd-font-weight;\n }\n}\n\n\n// Figures\n//\n// Apply a consistent margin strategy (matches our type styles).\n\nfigure {\n margin: 0 0 1rem;\n}\n\n\n// Images and content\n\nimg,\nsvg {\n vertical-align: middle;\n}\n\n\n// Tables\n//\n// Prevent double borders\n\ntable {\n caption-side: bottom;\n border-collapse: collapse;\n}\n\ncaption {\n padding-top: $table-cell-padding-y;\n padding-bottom: $table-cell-padding-y;\n color: $table-caption-color;\n text-align: left;\n}\n\n// 1. Removes font-weight bold by inheriting\n// 2. Matches default `` alignment by inheriting `text-align`.\n// 3. Fix alignment for Safari\n\nth {\n font-weight: $table-th-font-weight; // 1\n text-align: inherit; // 2\n text-align: -webkit-match-parent; // 3\n}\n\nthead,\ntbody,\ntfoot,\ntr,\ntd,\nth {\n border-color: inherit;\n border-style: solid;\n border-width: 0;\n}\n\n\n// Forms\n//\n// 1. Allow labels to use `margin` for spacing.\n\nlabel {\n display: inline-block; // 1\n}\n\n// Remove the default `border-radius` that macOS Chrome adds.\n// See https://github.com/twbs/bootstrap/issues/24093\n\nbutton {\n // stylelint-disable-next-line property-disallowed-list\n border-radius: 0;\n}\n\n// Explicitly remove focus outline in Chromium when it shouldn't be\n// visible (e.g. as result of mouse click or touch tap). It already\n// should be doing this automatically, but seems to currently be\n// confused and applies its very visible two-tone outline anyway.\n\nbutton:focus:not(:focus-visible) {\n outline: 0;\n}\n\n// 1. Remove the margin in Firefox and Safari\n\ninput,\nbutton,\nselect,\noptgroup,\ntextarea {\n margin: 0; // 1\n font-family: inherit;\n @include font-size(inherit);\n line-height: inherit;\n}\n\n// Remove the inheritance of text transform in Firefox\nbutton,\nselect {\n text-transform: none;\n}\n// Set the cursor for non-` *@ - @* } *@ - @* else *@ - @* { *@ - @* Untitled *@ - @* } *@ @{ @@ -53,8 +46,6 @@ { - - //Delete } else { @@ -98,10 +89,14 @@ private async Task DownloadArchiveAsync(Guid archiveId) { + var archive = await Service.OpenTok.GetArchiveAsync(archiveId.ToString()); + await JavascriptRuntime.InvokeVoidAsync("open", archive.Url, "_blank"); } private async Task DeleteArchiveAsync(Guid archiveId) { + await Service.OpenTok.DeleteArchiveAsync(archiveId.ToString()); + NavigationManager.NavigateTo(NavigationManager.Uri, true); } } \ No newline at end of file diff --git a/BlazorTestApp/Pages/ArchivesManagement/Delete.razor b/BlazorTestApp/Pages/ArchivesManagement/Delete.razor deleted file mode 100644 index 51ac04c0..00000000 --- a/BlazorTestApp/Pages/ArchivesManagement/Delete.razor +++ /dev/null @@ -1,25 +0,0 @@ -@page "/archives/delete" -@page "/archives/delete/{id:guid}" -@using BlazorTestApp.Data -@inject OpenTokService Service -@inject NavigationManager NavigationManager -@inject IJSRuntime JavascriptRuntime -Delete -

Deleting your archive...

- -@code { - - [Parameter] - public Guid Id { get; set; } - - protected override async Task OnInitializedAsync() - { - await base.OnInitializedAsync(); - if (Id != Guid.Empty) - { - await Service.OpenTok.DeleteArchiveAsync(Id.ToString()); - } - NavigationManager.NavigateTo("/archives"); - } - -} \ No newline at end of file diff --git a/BlazorTestApp/Pages/ArchivesManagement/Download.razor b/BlazorTestApp/Pages/ArchivesManagement/Download.razor deleted file mode 100644 index 2d81a98b..00000000 --- a/BlazorTestApp/Pages/ArchivesManagement/Download.razor +++ /dev/null @@ -1,26 +0,0 @@ -@page "/archives/download" -@page "/archives/download/{id:guid}" -@using BlazorTestApp.Data -@inject OpenTokService Service -@inject NavigationManager NavigationManager -@inject IJSRuntime JavascriptRuntime -Download -

Redirecting to your archive...

- -@code { - - [Parameter] - public Guid Id { get; set; } - - protected override async Task OnInitializedAsync() - { - await base.OnInitializedAsync(); - if (Id != Guid.Empty) - { - var archive = await Service.OpenTok.GetArchiveAsync(Id.ToString()); - await JavascriptRuntime.InvokeVoidAsync("open", archive.Url, "_blank"); - } - NavigationManager.NavigateTo("/archives"); - } - -} \ No newline at end of file From 343dc5270e9ead5cf8348f2c80142ef70143c7a1 Mon Sep 17 00:00:00 2001 From: Tr00d Date: Tue, 29 Nov 2022 15:13:56 +0100 Subject: [PATCH 19/23] Refactoring & simplification --- BlazorTestApp/Data/IVideoService.cs | 20 +++++++ BlazorTestApp/Data/OpenTokService.cs | 17 ------ BlazorTestApp/Data/VideoService.cs | 38 +++++++++++++ .../Pages/ArchivesManagement/Archives.razor | 47 ++++++---------- BlazorTestApp/Pages/HostManagement/Host.razor | 56 ++++++------------- .../Pages/HostManagement/HostInput.cs | 8 --- .../ParticipantManagement/Participant.razor | 11 ++-- BlazorTestApp/Program.cs | 2 +- 8 files changed, 98 insertions(+), 101 deletions(-) create mode 100644 BlazorTestApp/Data/IVideoService.cs delete mode 100644 BlazorTestApp/Data/OpenTokService.cs create mode 100644 BlazorTestApp/Data/VideoService.cs delete mode 100644 BlazorTestApp/Pages/HostManagement/HostInput.cs diff --git a/BlazorTestApp/Data/IVideoService.cs b/BlazorTestApp/Data/IVideoService.cs new file mode 100644 index 00000000..61ece3c4 --- /dev/null +++ b/BlazorTestApp/Data/IVideoService.cs @@ -0,0 +1,20 @@ +using OpenTokSDK; + +namespace BlazorTestApp.Data; + +public interface IVideoService +{ + Session CreateSession(); + + Task DeleteArchiveAsync(Guid archiveId); + + Task StopArchiveAsync(Guid archiveId); + + Task GetArchiveAsync(Guid archiveId); + + Task ListArchivesAsync(); + + Task StartArchiveAsync(string sessionId); + + int GetApiKey(); +} \ No newline at end of file diff --git a/BlazorTestApp/Data/OpenTokService.cs b/BlazorTestApp/Data/OpenTokService.cs deleted file mode 100644 index a559147a..00000000 --- a/BlazorTestApp/Data/OpenTokService.cs +++ /dev/null @@ -1,17 +0,0 @@ -using System.Net; -using OpenTokSDK; - -namespace BlazorTestApp.Data; - -public class OpenTokService -{ - public OpenTokService(OpenTokOptions options) - { - ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12; - this.OpenTok = new OpenTok(Convert.ToInt32(options.ApiKey), options.ApiSecret); - } - - public OpenTok OpenTok { get; } - - public Session CreateSession() => this.OpenTok.CreateSession(mediaMode: MediaMode.ROUTED); -} \ No newline at end of file diff --git a/BlazorTestApp/Data/VideoService.cs b/BlazorTestApp/Data/VideoService.cs new file mode 100644 index 00000000..c2235107 --- /dev/null +++ b/BlazorTestApp/Data/VideoService.cs @@ -0,0 +1,38 @@ +using System.Net; +using OpenTokSDK; + +namespace BlazorTestApp.Data; + +public class VideoService : IVideoService +{ + private readonly OpenTok openTok; + + public VideoService(OpenTokOptions options) + { + ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12; + this.openTok = new OpenTok(Convert.ToInt32(options.ApiKey), options.ApiSecret); + } + + public Session CreateSession() => this.openTok.CreateSession(mediaMode: MediaMode.ROUTED); + + public async Task DeleteArchiveAsync(Guid archiveId) => await this.openTok.DeleteArchiveAsync(archiveId.ToString()); + + public int GetApiKey() => this.openTok.ApiKey; + + public async Task StopArchiveAsync(Guid archiveId) => await this.openTok.StopArchiveAsync(archiveId.ToString()); + + public async Task GetArchiveAsync(Guid archiveId) => + await this.openTok.GetArchiveAsync(archiveId.ToString()); + + public async Task ListArchivesAsync() => await this.openTok.ListArchivesAsync(); + + public async Task StartArchiveAsync(string sessionId) => await this.openTok.StartArchiveAsync( + sessionId, + "Blazor Sample App", + true, + true, + OutputMode.COMPOSED, + "1920x1080", + new ArchiveLayout {Type = LayoutType.bestFit, ScreenShareType = ScreenShareLayoutType.BestFit} + ); +} \ No newline at end of file diff --git a/BlazorTestApp/Pages/ArchivesManagement/Archives.razor b/BlazorTestApp/Pages/ArchivesManagement/Archives.razor index 95d860d8..69be582c 100644 --- a/BlazorTestApp/Pages/ArchivesManagement/Archives.razor +++ b/BlazorTestApp/Pages/ArchivesManagement/Archives.razor @@ -1,7 +1,8 @@ @page "/archives" @using BlazorTestApp.Data @using OpenTokSDK -@inject OpenTokService Service +@using System.Globalization +@inject IVideoService Service @inject NavigationManager NavigationManager @inject IJSRuntime JavascriptRuntime Archives @@ -30,26 +31,20 @@ @foreach (var archive in archives) { - - @archive.Name - - - @{ - var epoch = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc); - @epoch.AddMilliseconds(archive.CreatedAt).ToString() - } - + @archive.Name + @GetMinimumDate().AddMilliseconds(archive.CreatedAt).ToString(CultureInfo.InvariantCulture) @archive.Duration seconds @archive.Status - @if (archive.Status == ArchiveStatus.AVAILABLE) + @if (archive.Status == ArchiveStatus.EXPIRED) { - - + @:Expired } - else + + @if (archive.Status == ArchiveStatus.AVAILABLE) { - @:   + + } @@ -60,9 +55,7 @@ } else { -

- Loading archives... -

+

Loading archives...

} @@ -73,30 +66,26 @@ private IEnumerable archives = new List(); private int archiveCount; - private string showPrevious = string.Empty; - private string showNext = string.Empty; protected override async Task OnInitializedAsync() { await base.OnInitializedAsync(); - var openTokArchives = await Service.OpenTok.ListArchivesAsync(count: 1000); - if (openTokArchives != null) - { - archiveCount = openTokArchives.TotalCount; - archives = openTokArchives.ToList(); - } + var openTokArchives = await Service.ListArchivesAsync(); + archiveCount = openTokArchives.TotalCount; + archives = openTokArchives.ToList(); } - private async Task DownloadArchiveAsync(Guid archiveId) + private async Task OpenArchiveAsync(Guid archiveId) { - var archive = await Service.OpenTok.GetArchiveAsync(archiveId.ToString()); + var archive = await Service.GetArchiveAsync(archiveId); await JavascriptRuntime.InvokeVoidAsync("open", archive.Url, "_blank"); } private async Task DeleteArchiveAsync(Guid archiveId) { - await Service.OpenTok.DeleteArchiveAsync(archiveId.ToString()); + await Service.DeleteArchiveAsync(archiveId); NavigationManager.NavigateTo(NavigationManager.Uri, true); } + private static DateTime GetMinimumDate() => new(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc); } \ No newline at end of file diff --git a/BlazorTestApp/Pages/HostManagement/Host.razor b/BlazorTestApp/Pages/HostManagement/Host.razor index ef6029f5..4c0b1e43 100644 --- a/BlazorTestApp/Pages/HostManagement/Host.razor +++ b/BlazorTestApp/Pages/HostManagement/Host.razor @@ -1,8 +1,7 @@ @page "/host" @using BlazorTestApp.Data -@using OpenTokSDK -@inject IJSRuntime JS -@inject OpenTokService service +@inject IJSRuntime JavascriptRuntime +@inject IVideoService VideoService Host
@@ -23,27 +22,8 @@
@@ -60,7 +40,7 @@

Click Stop archiving to end archiving this session. - You can then go to past archives to + You can then go to past archives to view your archive (once its status changes to available).

@@ -99,38 +79,34 @@ private string sessionId = string.Empty; private Guid archiveId = Guid.Empty; - private HostInput UserInput { get; } = new(); + private bool isArchiving; protected override async Task OnAfterRenderAsync(bool firstRender) { await base.OnAfterRenderAsync(firstRender); if (!firstRender) return; - var session = service.CreateSession(); + var session = VideoService.CreateSession(); sessionId = session.Id; - var apiKey = service.OpenTok.ApiKey.ToString(); - var token = session.GenerateToken(); - await JS.InvokeVoidAsync("initializeSession", apiKey, sessionId, token); + await JavascriptRuntime.InvokeVoidAsync( + "initializeSession", + VideoService.GetApiKey().ToString(), + sessionId, + session.GenerateToken()); } private async Task StartArchivingAsync() { - var archive = await service.OpenTok.StartArchiveAsync( - sessionId, - ".NET Archiving Sample App", - UserInput.HasVideo, - UserInput.HasAudio, - GetOutputMode(UserInput.OutputMode) - ); + isArchiving = true; + var archive = await VideoService.StartArchiveAsync(sessionId); archiveId = archive.Id; } - private OutputMode GetOutputMode(string value) => value == "composed" ? OutputMode.COMPOSED : OutputMode.INDIVIDUAL; - private async Task StopArchivingAsync() { + isArchiving = false; if (archiveId != Guid.Empty) { - await service.OpenTok.StopArchiveAsync(archiveId.ToString()); + await VideoService.StopArchiveAsync(archiveId); } } diff --git a/BlazorTestApp/Pages/HostManagement/HostInput.cs b/BlazorTestApp/Pages/HostManagement/HostInput.cs deleted file mode 100644 index 594d19a1..00000000 --- a/BlazorTestApp/Pages/HostManagement/HostInput.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace BlazorTestApp.Pages.HostManagement; - -public class HostInput -{ - public bool HasAudio { get; set; } = true; - public bool HasVideo { get; set; } = true; - public string OutputMode { get; set; } = "composed"; -} \ No newline at end of file diff --git a/BlazorTestApp/Pages/ParticipantManagement/Participant.razor b/BlazorTestApp/Pages/ParticipantManagement/Participant.razor index c51248e5..ec338abe 100644 --- a/BlazorTestApp/Pages/ParticipantManagement/Participant.razor +++ b/BlazorTestApp/Pages/ParticipantManagement/Participant.razor @@ -1,7 +1,7 @@ @page "/participant" @using BlazorTestApp.Data -@inject IJSRuntime JS -@inject OpenTokService service +@inject IJSRuntime JavascriptRuntime +@inject IVideoService VideoService Participant
@@ -72,18 +72,17 @@
@code { - private string sessionId = string.Empty; protected override async Task OnAfterRenderAsync(bool firstRender) { await base.OnAfterRenderAsync(firstRender); if (!firstRender) return; - var session = service.CreateSession(); + var session = VideoService.CreateSession(); sessionId = session.Id; - var apiKey = service.OpenTok.ApiKey.ToString(); + var apiKey = VideoService.GetApiKey().ToString(); var token = session.GenerateToken(); - await JS.InvokeVoidAsync("initializeSession", apiKey, sessionId, token); + await JavascriptRuntime.InvokeVoidAsync("initializeSession", apiKey, sessionId, token); } } \ No newline at end of file diff --git a/BlazorTestApp/Program.cs b/BlazorTestApp/Program.cs index 3f6032f2..7d284aa2 100644 --- a/BlazorTestApp/Program.cs +++ b/BlazorTestApp/Program.cs @@ -5,7 +5,7 @@ builder.Services.AddRazorPages(); builder.Services.AddServerSideBlazor(); builder.Services.AddSingleton(); -builder.Services.AddSingleton(_ => new OpenTokService(options)); +builder.Services.AddSingleton(_ => new VideoService(options)); var app = builder.Build(); app.UseHttpsRedirection(); app.UseStaticFiles(); From 8fbb4996911c86e6aeeb13fe10070ea1697c29e2 Mon Sep 17 00:00:00 2001 From: Tr00d Date: Wed, 30 Nov 2022 14:20:46 +0100 Subject: [PATCH 20/23] Refactoring and simlplification --- BlazorTestApp/BlazorTestApp.csproj | 8 +- BlazorTestApp/Data/IVideoService.cs | 9 +- BlazorTestApp/Data/OpenTokOptions.cs | 8 +- BlazorTestApp/Data/SessionCredentials.cs | 18 ++++ BlazorTestApp/Data/SessionInformation.cs | 3 + BlazorTestApp/Data/VideoService.cs | 15 +++- BlazorTestApp/Data/WeatherForecast.cs | 12 --- BlazorTestApp/Data/WeatherForecastService.cs | 19 ---- BlazorTestApp/Pages/Index.razor | 65 +++++++++++++- BlazorTestApp/Pages/Index.razor.css | 33 +++++++ .../ParticipantManagement/Participant.razor | 88 ------------------- .../Stream.razor} | 81 ++++++++++------- BlazorTestApp/Pages/_Layout.cshtml | 1 - BlazorTestApp/Program.cs | 1 - BlazorTestApp/Properties/launchSettings.json | 7 -- BlazorTestApp/Shared/MainLayout.razor | 2 - BlazorTestApp/Shared/NavMenu.razor | 9 +- BlazorTestApp/appsettings.json | 3 +- BlazorTestApp/wwwroot/content/js/host.js | 23 +++-- BlazorTestApp/wwwroot/css/sample.css | 22 ----- 20 files changed, 214 insertions(+), 213 deletions(-) create mode 100644 BlazorTestApp/Data/SessionCredentials.cs create mode 100644 BlazorTestApp/Data/SessionInformation.cs delete mode 100644 BlazorTestApp/Data/WeatherForecast.cs delete mode 100644 BlazorTestApp/Data/WeatherForecastService.cs create mode 100644 BlazorTestApp/Pages/Index.razor.css delete mode 100644 BlazorTestApp/Pages/ParticipantManagement/Participant.razor rename BlazorTestApp/Pages/{HostManagement/Host.razor => StreamManagement/Stream.razor} (57%) delete mode 100644 BlazorTestApp/wwwroot/css/sample.css diff --git a/BlazorTestApp/BlazorTestApp.csproj b/BlazorTestApp/BlazorTestApp.csproj index 0d827ac8..2f00683b 100644 --- a/BlazorTestApp/BlazorTestApp.csproj +++ b/BlazorTestApp/BlazorTestApp.csproj @@ -20,9 +20,6 @@ Always - - Always - @@ -35,6 +32,11 @@ <_ContentIncludedByDefault Remove="Pages\Host.razor"/> <_ContentIncludedByDefault Remove="Pages\Index.razor"/> <_ContentIncludedByDefault Remove="Pages\Participant.razor"/> + <_ContentIncludedByDefault Remove="Pages\ParticipantManagement\Participant.razor"/> + + + + diff --git a/BlazorTestApp/Data/IVideoService.cs b/BlazorTestApp/Data/IVideoService.cs index 61ece3c4..bf6a4568 100644 --- a/BlazorTestApp/Data/IVideoService.cs +++ b/BlazorTestApp/Data/IVideoService.cs @@ -1,10 +1,13 @@ +using LanguageExt; using OpenTokSDK; namespace BlazorTestApp.Data; public interface IVideoService { - Session CreateSession(); + void CreateSession(); + + void JoinSession(SessionCredentials sessionCredentials); Task DeleteArchiveAsync(Guid archiveId); @@ -17,4 +20,8 @@ public interface IVideoService Task StartArchiveAsync(string sessionId); int GetApiKey(); + + Option GetCredentials(); + + Option GetSessionInformation(); } \ No newline at end of file diff --git a/BlazorTestApp/Data/OpenTokOptions.cs b/BlazorTestApp/Data/OpenTokOptions.cs index b547015b..a1667af7 100644 --- a/BlazorTestApp/Data/OpenTokOptions.cs +++ b/BlazorTestApp/Data/OpenTokOptions.cs @@ -2,18 +2,16 @@ namespace BlazorTestApp.Data; public class OpenTokOptions { - public OpenTokOptions(string apiKey, string apiSecret, string sessionId) + public OpenTokOptions(string apiKey, string apiSecret) { this.ApiKey = apiKey; this.ApiSecret = apiSecret; - this.SessionId = sessionId; } public OpenTokOptions() { } - public string ApiKey { get; set; } - public string ApiSecret { get; set; } - public string SessionId { get; set; } + public string ApiKey { get; set; } = string.Empty; + public string ApiSecret { get; set; } = string.Empty; } \ No newline at end of file diff --git a/BlazorTestApp/Data/SessionCredentials.cs b/BlazorTestApp/Data/SessionCredentials.cs new file mode 100644 index 00000000..aac9022a --- /dev/null +++ b/BlazorTestApp/Data/SessionCredentials.cs @@ -0,0 +1,18 @@ +using LanguageExt; +using OpenTokSDK; + +namespace BlazorTestApp.Data; + +public record SessionCredentials(string SessionId, string Token, bool IsNewSession) +{ + public static Option FromNewSession(string sessionId, string token) => + ParseCredentials(sessionId, token, true); + + private static Option ParseCredentials(string sessionId, string token, bool isNewSession) => + string.IsNullOrEmpty(sessionId) && string.IsNullOrEmpty(token) + ? Option.None + : new SessionCredentials(sessionId, token, isNewSession); + + public static Option FromExistingSession(Session session) => + ParseCredentials(session.Id, session.GenerateToken(), false); +} \ No newline at end of file diff --git a/BlazorTestApp/Data/SessionInformation.cs b/BlazorTestApp/Data/SessionInformation.cs new file mode 100644 index 00000000..23d17297 --- /dev/null +++ b/BlazorTestApp/Data/SessionInformation.cs @@ -0,0 +1,3 @@ +namespace BlazorTestApp.Data; + +public record SessionInformation(SessionCredentials Credentials, string ApiKey); \ No newline at end of file diff --git a/BlazorTestApp/Data/VideoService.cs b/BlazorTestApp/Data/VideoService.cs index c2235107..0c1c512c 100644 --- a/BlazorTestApp/Data/VideoService.cs +++ b/BlazorTestApp/Data/VideoService.cs @@ -1,11 +1,14 @@ using System.Net; +using LanguageExt; using OpenTokSDK; +using static LanguageExt.Prelude; namespace BlazorTestApp.Data; public class VideoService : IVideoService { private readonly OpenTok openTok; + private Option credentials = Option.None; public VideoService(OpenTokOptions options) { @@ -13,12 +16,22 @@ public VideoService(OpenTokOptions options) this.openTok = new OpenTok(Convert.ToInt32(options.ApiKey), options.ApiSecret); } - public Session CreateSession() => this.openTok.CreateSession(mediaMode: MediaMode.ROUTED); + public void CreateSession() => + Some(this.openTok.CreateSession(mediaMode: MediaMode.ROUTED)) + .Bind(SessionCredentials.FromExistingSession) + .IfSome(this.JoinSession); + + public void JoinSession(SessionCredentials sessionCredentials) => this.credentials = sessionCredentials; public async Task DeleteArchiveAsync(Guid archiveId) => await this.openTok.DeleteArchiveAsync(archiveId.ToString()); public int GetApiKey() => this.openTok.ApiKey; + public Option GetCredentials() => this.credentials; + + public Option GetSessionInformation() => this.credentials + .Map(cred => new SessionInformation(cred, this.GetApiKey().ToString())); + public async Task StopArchiveAsync(Guid archiveId) => await this.openTok.StopArchiveAsync(archiveId.ToString()); public async Task GetArchiveAsync(Guid archiveId) => diff --git a/BlazorTestApp/Data/WeatherForecast.cs b/BlazorTestApp/Data/WeatherForecast.cs deleted file mode 100644 index f42c3b2b..00000000 --- a/BlazorTestApp/Data/WeatherForecast.cs +++ /dev/null @@ -1,12 +0,0 @@ -namespace BlazorTestApp.Data; - -public class WeatherForecast -{ - public DateTime Date { get; set; } - - public int TemperatureC { get; set; } - - public int TemperatureF => 32 + (int) (TemperatureC / 0.5556); - - public string? Summary { get; set; } -} \ No newline at end of file diff --git a/BlazorTestApp/Data/WeatherForecastService.cs b/BlazorTestApp/Data/WeatherForecastService.cs deleted file mode 100644 index 636653c2..00000000 --- a/BlazorTestApp/Data/WeatherForecastService.cs +++ /dev/null @@ -1,19 +0,0 @@ -namespace BlazorTestApp.Data; - -public class WeatherForecastService -{ - private static readonly string[] Summaries = - { - "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching", - }; - - public Task GetForecastAsync(DateTime startDate) - { - return Task.FromResult(Enumerable.Range(1, 5).Select(index => new WeatherForecast - { - Date = startDate.AddDays(index), - TemperatureC = Random.Shared.Next(-20, 55), - Summary = Summaries[Random.Shared.Next(Summaries.Length)], - }).ToArray()); - } -} \ No newline at end of file diff --git a/BlazorTestApp/Pages/Index.razor b/BlazorTestApp/Pages/Index.razor index 66ce12c8..9b94e796 100644 --- a/BlazorTestApp/Pages/Index.razor +++ b/BlazorTestApp/Pages/Index.razor @@ -1,9 +1,66 @@ @page "/" +@using BlazorTestApp.Data +@using LanguageExt +@inject IVideoService VideoService +Video Sample App -Index +
+
+

Welcome to Vonage's Video Sample App!

+
+ + + +
-

Hello, world!

-Welcome to your new app. +@code { + private Option sessionId = Option.None; + private string joinSessionId = "1_MX40NzU4MTQyMX5-MTY2OTc5NjcyMTcxNX4za1ZwbVhMNHpBd09GdnBTNG50K201eTh-fg"; + private string joinToken = "T1==cGFydG5lcl9pZD00NzU4MTQyMSZzaWc9ZDVhY2EyNWNhM2JlMDU5MDE5MDA2N2MxZjYyODEyZGZkZDNmMTRkYzpzZXNzaW9uX2lkPTFfTVg0ME56VTRNVFF5TVg1LU1UWTJPVGM1TmpjeU1UY3hOWDR6YTFad2JWaE1OSHBCZDA5R2RuQlRORzUwSzIwMWVUaC1mZyZjcmVhdGVfdGltZT0xNjY5Nzk4MTk5Jm5vbmNlPTAuNTQ2OTkxNDQ3MTc0NzQ2OCZyb2xlPXB1Ymxpc2hlciZleHBpcmVfdGltZT0xNjY5ODAxNzk4JmluaXRpYWxfbGF5b3V0X2NsYXNzX2xpc3Q9"; - \ No newline at end of file + private bool IsSessionAvailable => sessionId.IsSome; + private string SessionId => sessionId.Match(session => session, () => string.Empty); + + protected override void OnInitialized() + { + base.OnInitialized(); + sessionId = VideoService.GetCredentials().Map(credentials => credentials.SessionId); + } + + private void CreateSession() + { + VideoService.CreateSession(); + AssignSessionId(); + } + + private void JoinSession() => SessionCredentials + .FromNewSession(joinSessionId, joinToken) + .Do(VideoService.JoinSession) + .Do(_ => AssignSessionId()); + + private void AssignSessionId() => sessionId = VideoService + .GetCredentials() + .Map(credentials => credentials.SessionId); + +} \ No newline at end of file diff --git a/BlazorTestApp/Pages/Index.razor.css b/BlazorTestApp/Pages/Index.razor.css new file mode 100644 index 00000000..1c4b8779 --- /dev/null +++ b/BlazorTestApp/Pages/Index.razor.css @@ -0,0 +1,33 @@ +.container { + display: grid; + grid-template-columns: 50% 50%; + grid-template-rows: auto auto auto 100%; +} + +.item-title { + grid-column-start: 1; + grid-column-end: 3; + grid-row-start: 1; + grid-row-end: 1; +} + +.item-create { + grid-column-start: 1; + grid-column-end: 1; + grid-row-start: 2; + grid-row-end: 2; +} + +.item-join { + grid-column-start: 2; + grid-column-end: 2; + grid-row-start: 2; + grid-row-end: 2; +} + +.item-session { + grid-column-start: 1; + grid-column-end: 3; + grid-row-start: 3; + grid-row-end: 3; +} \ No newline at end of file diff --git a/BlazorTestApp/Pages/ParticipantManagement/Participant.razor b/BlazorTestApp/Pages/ParticipantManagement/Participant.razor deleted file mode 100644 index ec338abe..00000000 --- a/BlazorTestApp/Pages/ParticipantManagement/Participant.razor +++ /dev/null @@ -1,88 +0,0 @@ -@page "/participant" -@using BlazorTestApp.Data -@inject IJSRuntime JavascriptRuntime -@inject IVideoService VideoService -Participant - -
- -
- -
-
-

Participant

-
-
- Publishers -
-
-
- Subscribers -
-
-
-
-
- -
-
-

Instructions

-
-
-

- Click Start archiving to begin archiving this session. - All publishers in the session will be included, and all publishers that - join the session will be included as well. -

-

- Click Stop archiving to end archiving this session. - You can then go to past archives to - view your archive (once its status changes to available). -

-
- - - - - - - - - - - - - - - - - - - - -
WhenYou will see
Archiving is started - -
Archiving remains on - -
Archiving is stopped - -
- - - - -@code { - private string sessionId = string.Empty; - - protected override async Task OnAfterRenderAsync(bool firstRender) - { - await base.OnAfterRenderAsync(firstRender); - if (!firstRender) return; - var session = VideoService.CreateSession(); - sessionId = session.Id; - var apiKey = VideoService.GetApiKey().ToString(); - var token = session.GenerateToken(); - await JavascriptRuntime.InvokeVoidAsync("initializeSession", apiKey, sessionId, token); - } - -} \ No newline at end of file diff --git a/BlazorTestApp/Pages/HostManagement/Host.razor b/BlazorTestApp/Pages/StreamManagement/Stream.razor similarity index 57% rename from BlazorTestApp/Pages/HostManagement/Host.razor rename to BlazorTestApp/Pages/StreamManagement/Stream.razor index 4c0b1e43..c8ba7b18 100644 --- a/BlazorTestApp/Pages/HostManagement/Host.razor +++ b/BlazorTestApp/Pages/StreamManagement/Stream.razor @@ -1,5 +1,7 @@ -@page "/host" +@page "/stream" @using BlazorTestApp.Data +@using OpenTokSDK +@using LanguageExt @inject IJSRuntime JavascriptRuntime @inject IVideoService VideoService Host @@ -8,6 +10,9 @@
+ + +

Host

@@ -22,13 +27,12 @@
-
+