From f7c2973bbaf335d229628fde27b5155132c8c8a4 Mon Sep 17 00:00:00 2001 From: AlexNDRmac Date: Thu, 10 Oct 2024 13:47:29 +0300 Subject: [PATCH 01/14] update actions --- .github/workflows/build_and_test.yml | 10 +++++----- .github/workflows/release.yml | 6 +++--- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/.github/workflows/build_and_test.yml b/.github/workflows/build_and_test.yml index 814e0b96..54adc131 100644 --- a/.github/workflows/build_and_test.yml +++ b/.github/workflows/build_and_test.yml @@ -53,7 +53,7 @@ jobs: shell: pwsh steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: fetch-depth: 1 @@ -66,12 +66,12 @@ jobs: } - name: Setup .NET SDK - uses: actions/setup-dotnet@v3 + uses: actions/setup-dotnet@v4 with: dotnet-version: ${{ env.DOTNET_SDK_VERSION }} - name: Setup Nuget Cache - uses: actions/cache@v3 + uses: actions/cache@v4 id: nuget-cache with: path: ~/.nuget @@ -103,7 +103,7 @@ jobs: /p:CollectCoverage=true - name: Save Code Coverage Results - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: CoverageReports-${{ runner.os }}-${{ matrix.framework }}.zip path: SignNow.Net.Test/bin/Debug/**/coverage* @@ -126,7 +126,7 @@ jobs: - name: Upload Code Coverage Report (Codecov.io) continue-on-error: true - uses: codecov/codecov-action@v3 + uses: codecov/codecov-action@v4 with: name: ${{ runner.os }}-codecov-${{ matrix.framework }} flags: ${{ runner.os }},${{ env.TARGET_FRAMEWORK }} diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 02a2216d..840fce85 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -17,17 +17,17 @@ jobs: NUGET_XMLDOC_MODE: skip # prevent the download of the XML documentation for the packages steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Setup .NET 5 - uses: actions/setup-dotnet@v3 + uses: actions/setup-dotnet@v4 with: dotnet-version: | 3.1.x 5.0.x - name: Setup Nuget Cache - uses: actions/cache@v3 + uses: actions/cache@v4 id: nuget-cache with: path: ~/.nuget From 181d145c37ef6f2795bcbf4ebe349e556ad9ebc6 Mon Sep 17 00:00:00 2001 From: AlexNDRmac Date: Thu, 10 Oct 2024 13:47:45 +0300 Subject: [PATCH 02/14] add dependabot for github actions --- .github/dependabot.yml | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 .github/dependabot.yml diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 00000000..f196cdd5 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,8 @@ +version: 2 +updates: + +# Set update schedule for GitHub Actions + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "weekly" From 83a09b72b1524d166442284eac2d05308559aff1 Mon Sep 17 00:00:00 2001 From: AlexNDRmac Date: Thu, 10 Oct 2024 14:54:06 +0300 Subject: [PATCH 03/14] use macos 13 for CI --- .github/workflows/build_and_test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build_and_test.yml b/.github/workflows/build_and_test.yml index 54adc131..54e1f177 100644 --- a/.github/workflows/build_and_test.yml +++ b/.github/workflows/build_and_test.yml @@ -32,7 +32,7 @@ jobs: # Ubuntu - { name: 'Linux .NET 5', os: ubuntu-22.04, framework: 'net5' } # macOs - - { name: 'macOS .NET 5', os: macOS-latest, framework: 'net5' } + - { name: 'macOS .NET 5', os: macos-13, framework: 'net5' } # Windows - { name: 'Windows .NET Core 3', os: windows-latest, framework: 'netcoreapp3.1' } - { name: 'Windows .NET 5', os: windows-latest, framework: 'net5' } From 2538142a4e40402b82890c8cef45acee4f042e36 Mon Sep 17 00:00:00 2001 From: AlexNDRmac Date: Thu, 10 Oct 2024 15:13:38 +0300 Subject: [PATCH 04/14] add macos versions to runtime info --- .../_Internal/Infrastructure/RuntimeInfo.cs | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/SignNow.Net/_Internal/Infrastructure/RuntimeInfo.cs b/SignNow.Net/_Internal/Infrastructure/RuntimeInfo.cs index 8971f895..8aa0342e 100644 --- a/SignNow.Net/_Internal/Infrastructure/RuntimeInfo.cs +++ b/SignNow.Net/_Internal/Infrastructure/RuntimeInfo.cs @@ -236,6 +236,18 @@ public static string GetMacOsVersion(string kernel) version = "12.0"; break; + case (int)MacOsVersions.macOS1300: + version = "13.0"; + break; + + case (int)MacOsVersions.macOS1400: + version = "14.0"; + break; + + case (int)MacOsVersions.macOS1500: + version = "15.0"; + break; + default: break; } @@ -265,7 +277,10 @@ internal enum MacOsVersions macOS1014, macOS1015, macOS1100, - macOS1200 + macOS1200, + macOS1300, + macOS1400, + macOS1500 } } } From 3fa87aeda12e8100a9275e991b65806b1ffac6e4 Mon Sep 17 00:00:00 2001 From: AlexNDRmac Date: Fri, 11 Oct 2024 10:10:37 +0300 Subject: [PATCH 05/14] update runtime info test for macos --- SignNow.Net.Test/UnitTests/Infrastructure/RuntimeInfoTest.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/SignNow.Net.Test/UnitTests/Infrastructure/RuntimeInfoTest.cs b/SignNow.Net.Test/UnitTests/Infrastructure/RuntimeInfoTest.cs index e8a5166e..2fabdd71 100644 --- a/SignNow.Net.Test/UnitTests/Infrastructure/RuntimeInfoTest.cs +++ b/SignNow.Net.Test/UnitTests/Infrastructure/RuntimeInfoTest.cs @@ -44,6 +44,9 @@ public void ShouldProperParseLinuxOsDetails(string kernelStr, string expected) [DataRow("19.0.0", "10.15", DisplayName = "Catalina")] [DataRow("20.0.0", "11.0", DisplayName = "Big Sur")] [DataRow("21.0.0", "12.0", DisplayName = "Monterey")] + [DataRow("22.0.0", "13.0", DisplayName = "Ventura")] + [DataRow("23.0.0", "14.0", DisplayName = "Sonoma")] + [DataRow("24.0.0", "15.0", DisplayName = "Sequoia")] [DataRow("99.0.0", "", DisplayName = "Unknown")] public void ShouldProperParseMacOsDetails(string kernelVer, string expected) { From de929d9ad5adcd5e67e1654136be3f56f9d7e2f2 Mon Sep 17 00:00:00 2001 From: AlexNDRmac Date: Fri, 11 Oct 2024 10:21:24 +0300 Subject: [PATCH 06/14] Add resend invite interface --- SignNow.Net/Interfaces/ISignInvite.cs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/SignNow.Net/Interfaces/ISignInvite.cs b/SignNow.Net/Interfaces/ISignInvite.cs index e0381162..13a57ec0 100644 --- a/SignNow.Net/Interfaces/ISignInvite.cs +++ b/SignNow.Net/Interfaces/ISignInvite.cs @@ -63,5 +63,13 @@ public interface ISignInvite /// Propagates notification that operations should be canceled. /// Task CancelEmbeddedInviteAsync(string documentId, CancellationToken cancellationToken = default); + + /// + /// Resends an invite to sign a document. + /// + /// The role identity to resend the invitation to. + /// Propagates notification that operations should be canceled. + /// + Task ResendEmailInviteAsync(string fieldInviteId, CancellationToken cancellationToken = default); } } From cec22d6422083672bdd8168f7ab3fe09ac1cf5e0 Mon Sep 17 00:00:00 2001 From: AlexNDRmac Date: Fri, 11 Oct 2024 10:53:42 +0300 Subject: [PATCH 07/14] Implement resend invite --- SignNow.Net/Service/UserService.cs | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/SignNow.Net/Service/UserService.cs b/SignNow.Net/Service/UserService.cs index 14063bc1..d6dd2c9b 100644 --- a/SignNow.Net/Service/UserService.cs +++ b/SignNow.Net/Service/UserService.cs @@ -235,6 +235,20 @@ public async Task> GetUserDocumentsAsync(int perPag .ConfigureAwait(false); } + /// + /// /// Invalid format of . + public async Task ResendEmailInviteAsync(string fieldInviteId, CancellationToken cancellationToken = default) + { + Token.TokenType = TokenType.Bearer; + var requestOptions = new PutHttpRequestOptions + { + RequestUrl = new Uri(ApiBaseUrl, $"/fieldinvite/{fieldInviteId.ValidateId()}/resend"), + Token = Token + }; + + await SignNowClient.RequestAsync(requestOptions, cancellationToken).ConfigureAwait(false); + } + /// /// Returns an enumerable of user's documents. /// From 41732024eee92a42fc178cd63c92d4739195d4b8 Mon Sep 17 00:00:00 2001 From: AlexNDRmac Date: Wed, 16 Oct 2024 17:08:49 +0300 Subject: [PATCH 08/14] Add resend invite feature --- SignNow.Net.Examples/ExamplesRunner.cs | 7 +++++++ SignNow.Net.Examples/SignNow.Net.Examples.csproj | 2 +- SignNow.Net.Test/TestData/FakeModels/FieldFaker.cs | 2 ++ SignNow.Net/Interfaces/ISignInvite.cs | 2 -- SignNow.Net/Interfaces/ISignNowField.cs | 5 +++++ SignNow.Net/Model/Field.cs | 6 ++++++ SignNow.Net/SignNow.Net.csproj | 1 - 7 files changed, 21 insertions(+), 4 deletions(-) diff --git a/SignNow.Net.Examples/ExamplesRunner.cs b/SignNow.Net.Examples/ExamplesRunner.cs index fa4af699..99719a7c 100644 --- a/SignNow.Net.Examples/ExamplesRunner.cs +++ b/SignNow.Net.Examples/ExamplesRunner.cs @@ -545,6 +545,13 @@ public async Task CreateRoleBasedInviteToSignTheDocumentTest() var documentWithInvite = await testContext.Documents.GetDocumentAsync(document.Id).ConfigureAwait(false); var createdInvite = documentWithInvite.FieldInvites.FirstOrDefault(); + var fieldInvite = documentWithInvite.Fields.FirstOrDefault(); + Assert.IsNotNull(fieldInvite?.FieldRequestId); + + await testContext.Invites + .ResendEmailInviteAsync(fieldInvite?.FieldRequestId) + .ConfigureAwait(false); + Assert.AreEqual("noreply@signnow.com", createdInvite?.SignerEmail); Assert.AreEqual("Signer 1", createdInvite?.RoleName, "Signer role mismatch."); Assert.AreEqual(InviteStatus.Pending, createdInvite?.Status); diff --git a/SignNow.Net.Examples/SignNow.Net.Examples.csproj b/SignNow.Net.Examples/SignNow.Net.Examples.csproj index 8b10325d..0335af9a 100644 --- a/SignNow.Net.Examples/SignNow.Net.Examples.csproj +++ b/SignNow.Net.Examples/SignNow.Net.Examples.csproj @@ -2,7 +2,7 @@ - netcoreapp3.1 + net5 false diff --git a/SignNow.Net.Test/TestData/FakeModels/FieldFaker.cs b/SignNow.Net.Test/TestData/FakeModels/FieldFaker.cs index 6d0a26f4..f324dd82 100644 --- a/SignNow.Net.Test/TestData/FakeModels/FieldFaker.cs +++ b/SignNow.Net.Test/TestData/FakeModels/FieldFaker.cs @@ -34,6 +34,7 @@ public sealed class FieldFaker : Faker /// }, /// "originator": "owner@gmail.com", /// "fulfiller": "signer1@gmail.com", + /// "field_request_id": "cbf5df90807e41d79bfda22b7ab6f57b2ed51ee3", /// "element_id": null /// } /// @@ -57,6 +58,7 @@ public FieldFaker() }); o.Owner = f.Internet.Email(); o.Signer = f.Internet.Email(); + o.FieldRequestId = f.Random.Hash(40); // A nullable Id? with 80% probability of being null. o.ElementId = (string)f.Random.Hash(40).OrNull(f, .8f); }) diff --git a/SignNow.Net/Interfaces/ISignInvite.cs b/SignNow.Net/Interfaces/ISignInvite.cs index 13a57ec0..38ce9bdb 100644 --- a/SignNow.Net/Interfaces/ISignInvite.cs +++ b/SignNow.Net/Interfaces/ISignInvite.cs @@ -1,5 +1,3 @@ -using System; -using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; using SignNow.Net.Model; diff --git a/SignNow.Net/Interfaces/ISignNowField.cs b/SignNow.Net/Interfaces/ISignNowField.cs index aeeac07b..81f3c841 100644 --- a/SignNow.Net/Interfaces/ISignNowField.cs +++ b/SignNow.Net/Interfaces/ISignNowField.cs @@ -22,5 +22,10 @@ public interface ISignNowField /// Field attributes: name, label, x/y coordinates, width, height... /// FieldJsonAttributes JsonAttributes { get; } + + /// + /// Field request ID + /// + string FieldRequestId { get; } } } diff --git a/SignNow.Net/Model/Field.cs b/SignNow.Net/Model/Field.cs index af7b9397..d9c2720b 100644 --- a/SignNow.Net/Model/Field.cs +++ b/SignNow.Net/Model/Field.cs @@ -56,6 +56,12 @@ public class Field: ISignNowField [JsonProperty("fulfiller")] internal string Signer { get; set; } + /// + /// Field request ID + /// + [JsonProperty("field_request_id")] + public string FieldRequestId { get; internal set; } + /// /// Identity of specific element for corresponding field type. /// diff --git a/SignNow.Net/SignNow.Net.csproj b/SignNow.Net/SignNow.Net.csproj index 92a822bb..fbbdc91f 100644 --- a/SignNow.Net/SignNow.Net.csproj +++ b/SignNow.Net/SignNow.Net.csproj @@ -31,7 +31,6 @@ - From 9ea4d8a00d213ebc2cc7e8c5800c6128435b3a02 Mon Sep 17 00:00:00 2001 From: AlexNDRmac Date: Wed, 16 Oct 2024 17:21:11 +0300 Subject: [PATCH 09/14] update changelog --- CHANGELOG.md | 2 ++ .../Model/Responses/SuccessStatusResponse.cs | 16 ++++++++++++++++ 2 files changed, 18 insertions(+) create mode 100644 SignNow.Net/Model/Responses/SuccessStatusResponse.cs diff --git a/CHANGELOG.md b/CHANGELOG.md index 68c22852..a7ad96b8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,8 @@ The format is based on [Keep a Changelog](http://keepachangelog.com) and this project adheres to [Semantic Versioning](http://semver.org). ## [Unreleased] - TBD +### Added +- Resend Invite feature [#153](https://github.com/signnow/SignNow.NET/issues/153) ## [1.2.3] - 2023-10-15 diff --git a/SignNow.Net/Model/Responses/SuccessStatusResponse.cs b/SignNow.Net/Model/Responses/SuccessStatusResponse.cs new file mode 100644 index 00000000..da75df96 --- /dev/null +++ b/SignNow.Net/Model/Responses/SuccessStatusResponse.cs @@ -0,0 +1,16 @@ +using Newtonsoft.Json; + +namespace SignNow.Net.Model.Responses +{ + /// + /// Represents successful status response from signNow API. + /// + public class SuccessStatusResponse + { + /// + /// Operation status + /// + [JsonProperty("status")] + public string Status { get; set; } + } +} From a69021950ca523e7d8700382388192b2f5f3f9e4 Mon Sep 17 00:00:00 2001 From: AlexNDRmac Date: Wed, 16 Oct 2024 17:26:02 +0300 Subject: [PATCH 10/14] update packages --- SignNow.Net.Examples/SignNow.Net.Examples.csproj | 4 ++-- SignNow.Net.Test/SignNow.Net.Test.csproj | 4 ++-- SignNow.Net/SignNow.Net.csproj | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/SignNow.Net.Examples/SignNow.Net.Examples.csproj b/SignNow.Net.Examples/SignNow.Net.Examples.csproj index 0335af9a..4881413f 100644 --- a/SignNow.Net.Examples/SignNow.Net.Examples.csproj +++ b/SignNow.Net.Examples/SignNow.Net.Examples.csproj @@ -12,11 +12,11 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive - + diff --git a/SignNow.Net.Test/SignNow.Net.Test.csproj b/SignNow.Net.Test/SignNow.Net.Test.csproj index 650c4269..838d2156 100644 --- a/SignNow.Net.Test/SignNow.Net.Test.csproj +++ b/SignNow.Net.Test/SignNow.Net.Test.csproj @@ -18,7 +18,7 @@ - + @@ -28,7 +28,7 @@ all runtime; build; native; contentfiles; analyzers; buildtransitive - + diff --git a/SignNow.Net/SignNow.Net.csproj b/SignNow.Net/SignNow.Net.csproj index fbbdc91f..1379f9b6 100644 --- a/SignNow.Net/SignNow.Net.csproj +++ b/SignNow.Net/SignNow.Net.csproj @@ -17,7 +17,7 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive From 058eb79d7d12ab19c80cb71ddda4528f11d4af85 Mon Sep 17 00:00:00 2001 From: AlexNDRmac Date: Wed, 16 Oct 2024 20:56:02 +0300 Subject: [PATCH 11/14] add options for embedded invite request --- .../FakeModels/EmbeddedInviteFaker.cs | 17 +++ SignNow.Net/Model/EmbeddedInvite.cs | 136 +++++++++++++++++- SignNow.Net/Model/Lang.cs | 16 +++ SignNow.Net/Model/RedirectTarget.cs | 19 +++ 4 files changed, 186 insertions(+), 2 deletions(-) create mode 100644 SignNow.Net/Model/Lang.cs create mode 100644 SignNow.Net/Model/RedirectTarget.cs diff --git a/SignNow.Net.Test/TestData/FakeModels/EmbeddedInviteFaker.cs b/SignNow.Net.Test/TestData/FakeModels/EmbeddedInviteFaker.cs index 7337d501..13048842 100644 --- a/SignNow.Net.Test/TestData/FakeModels/EmbeddedInviteFaker.cs +++ b/SignNow.Net.Test/TestData/FakeModels/EmbeddedInviteFaker.cs @@ -1,3 +1,4 @@ +using System; using Bogus; using SignNow.Net.Model; using SignNow.Net.Model.Requests; @@ -17,7 +18,15 @@ public class EmbeddedInviteFaker : Faker /// /// { /// "email": "Jesus_Monahan@gmail.com", + /// "language": "en", /// "auth_method": "none", + /// "first_name": "Jesus", + /// "last_name": "Monahan", + /// "prefill_signature_name": "Jesus Monahan prefill signature", + /// "force_new_signature": "1", + /// "redirect_uri": "https://signnow.com", + /// "decline_redirect_uri": "https://signnow.com", + /// "redirect_target": "self", /// "role_id": "c376990ca7e1e84ea7f6e252144e435f314bb63b", /// "order": 1 /// } @@ -28,7 +37,15 @@ public EmbeddedInviteFaker() Rules((f, o) => { o.Email = f.Internet.Email(); + o.Language = f.PickRandom(); o.AuthMethod = f.PickRandom(); + o.Firstname = f.Person.FirstName; + o.Lastname = f.Person.LastName; + o.PrefillSignatureName = $"{f.Person.FirstName} {f.Person.LastName} prefill signature"; + o.ForceNewSignature = f.Random.Bool(); + o.RedirectUrl = new Uri(f.Internet.Url()); + o.DeclineRedirectUrl = new Uri(f.Internet.Url()); + o.RedirectTarget = f.PickRandom(); o.RoleId = f.Random.Hash(40); o.SigningOrder = (uint)f.Random.Number(1, 10); }); diff --git a/SignNow.Net/Model/EmbeddedInvite.cs b/SignNow.Net/Model/EmbeddedInvite.cs index 32ace25e..93ab31a1 100644 --- a/SignNow.Net/Model/EmbeddedInvite.cs +++ b/SignNow.Net/Model/EmbeddedInvite.cs @@ -2,6 +2,7 @@ using Newtonsoft.Json; using Newtonsoft.Json.Converters; using SignNow.Net.Internal.Extensions; +using SignNow.Net.Internal.Helpers.Converters; using SignNow.Net.Model.Requests; namespace SignNow.Net.Model @@ -14,6 +15,20 @@ public class EmbeddedInvite private string email { get; set; } private uint signingOrder { get; set; } + private string prefillSignatureName { get; set; } + private bool forceNewSignature { get; set; } + + private string requiredPresetSignatureName { get; set; } + + /// + /// Prefilled text in the Signature field, disabled for editing by signer. + /// Cannot be used together with prefill_signature_name and/or force_new_signature. + /// + private bool isPrefilledSignatureName { get; set; } + + private bool isRequiredPresetEnabled { get; set; } + + /// /// Signer's email address. /// @@ -25,13 +40,13 @@ public string Email } /// - /// Signer's role ID. + /// Signer's role id in the document. /// [JsonProperty("role_id")] public string RoleId { get; set; } /// - /// Order of signing. Cannot be 0. + /// The order of signing. Cannot be 0. /// [JsonProperty("order")] public uint SigningOrder @@ -48,11 +63,128 @@ public uint SigningOrder } } + /// + /// Sets the language of the signing session for the signer. + /// + [JsonProperty("language")] + [JsonConverter(typeof(StringEnumConverter))] + public Lang Language { get; set; } + /// /// Signer authentication method. /// [JsonProperty("auth_method")] [JsonConverter(typeof(StringEnumConverter))] public EmbeddedAuthType AuthMethod { get; set; } = EmbeddedAuthType.None; + + /// + /// Signer's first name. + /// + [JsonProperty("first_name", NullValueHandling = NullValueHandling.Ignore)] + public string Firstname { get; set; } + + /// + /// Signer's last name. + /// + [JsonProperty("last_name", NullValueHandling = NullValueHandling.Ignore)] + public string Lastname { get; set; } + + /// + /// Prefilled text in the Signature field. + /// + /// String lenght cannot be greater than 255 characters + /// Cannot be used together with Required preset for Signature name + [JsonProperty("prefill_signature_name", NullValueHandling = NullValueHandling.Ignore)] + public string PrefillSignatureName + { + get { return prefillSignatureName; } + set + { + if (value.Length > 255) + { + throw new ArgumentException( + "Prefilled text in the Signature field can be maximum 255 characters.", + nameof(PrefillSignatureName)); + } + + if (isRequiredPresetEnabled) + { + throw new ArgumentException( + "Required preset for Signature name is set. Cannot be used together with", + nameof(PrefillSignatureName)); + } + + prefillSignatureName = value; + isPrefilledSignatureName = true; + } + } + + /// Cannot be used together with Required preset for Signature name + [JsonProperty("force_new_signature", NullValueHandling = NullValueHandling.Ignore)] + [JsonConverter(typeof(BoolToIntJsonConverter))] + public bool ForceNewSignature + { + get { return forceNewSignature; } + set + { + if (isRequiredPresetEnabled) + { + throw new ArgumentException( + "Required preset for Signature name is set. Cannot be used together with", + nameof(ForceNewSignature)); + } + + forceNewSignature = value; + + if (value) + { + isPrefilledSignatureName = true; + } + } + } + + /// + /// Prefilled text in the Signature field, disabled for editing by signer. + /// + /// Cannot be used together with prefill for Signature name + [JsonProperty("required_preset_signature_name", NullValueHandling = NullValueHandling.Ignore)] + public string RequiredPresetSignatureName + { + get { return requiredPresetSignatureName; } + set + { + if (isPrefilledSignatureName) + { + throw new ArgumentException( + "Prefill for Signature name or Force new signature is set. Cannot be used together with", + nameof(RequiredPresetSignatureName)); + } + + requiredPresetSignatureName = value; + isRequiredPresetEnabled = true; + } + } + + /// + /// The link that opens after the signing session has been completed. + /// + [JsonProperty("redirect_uri", NullValueHandling = NullValueHandling.Ignore)] + [JsonConverter(typeof(StringToUriJsonConverter))] + public Uri RedirectUrl { get; set; } + + /// + /// The link that opens after the signing session has been declined by the signer. + /// + [JsonProperty("decline_redirect_uri", NullValueHandling = NullValueHandling.Ignore)] + [JsonConverter(typeof(StringToUriJsonConverter))] + public Uri DeclineRedirectUrl { get; set; } + + /// + /// Determines whether to open the redirect link in the new tab in the browser, or in the same tab after the signing session. + /// Possible values: blank - opens the link in the new tab, self - opens the link in the same tab, default value. + /// + [JsonProperty("redirect_target", NullValueHandling = NullValueHandling.Ignore)] + [JsonConverter(typeof(StringEnumConverter))] + public RedirectTarget RedirectTarget { get; set; } } } diff --git a/SignNow.Net/Model/Lang.cs b/SignNow.Net/Model/Lang.cs new file mode 100644 index 00000000..9c59ee12 --- /dev/null +++ b/SignNow.Net/Model/Lang.cs @@ -0,0 +1,16 @@ +using System.Runtime.Serialization; + +namespace SignNow.Net.Model +{ + public enum Lang + { + [EnumMember(Value = "en")] + English, + + [EnumMember(Value = "es")] + Spanish, + + [EnumMember(Value = "fr")] + French + } +} diff --git a/SignNow.Net/Model/RedirectTarget.cs b/SignNow.Net/Model/RedirectTarget.cs new file mode 100644 index 00000000..f49c04ef --- /dev/null +++ b/SignNow.Net/Model/RedirectTarget.cs @@ -0,0 +1,19 @@ +using System.Runtime.Serialization; + +namespace SignNow.Net.Model +{ + public enum RedirectTarget + { + /// + /// opens the link in the new tab + /// + [EnumMember(Value = "blank")] + Blank, + + /// + /// opens the link in the same tab. + /// + [EnumMember(Value = "self")] + Self + } +} From b1bb6df06d0c8db9d597d94164b891259e44756b Mon Sep 17 00:00:00 2001 From: AlexNDRmac Date: Wed, 16 Oct 2024 21:36:45 +0300 Subject: [PATCH 12/14] Fx tests --- CHANGELOG.md | 1 + SignNow.Net/Model/EmbeddedInvite.cs | 8 ++++---- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a7ad96b8..03b79b9f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ and this project adheres to [Semantic Versioning](http://semver.org). ## [Unreleased] - TBD ### Added - Resend Invite feature [#153](https://github.com/signnow/SignNow.NET/issues/153) +- Options for Embedded invite [#160](https://github.com/signnow/SignNow.NET/issues/160) ## [1.2.3] - 2023-10-15 diff --git a/SignNow.Net/Model/EmbeddedInvite.cs b/SignNow.Net/Model/EmbeddedInvite.cs index 93ab31a1..5bcb21f3 100644 --- a/SignNow.Net/Model/EmbeddedInvite.cs +++ b/SignNow.Net/Model/EmbeddedInvite.cs @@ -16,7 +16,7 @@ public class EmbeddedInvite private uint signingOrder { get; set; } private string prefillSignatureName { get; set; } - private bool forceNewSignature { get; set; } + private bool? forceNewSignature { get; set; } private string requiredPresetSignatureName { get; set; } @@ -122,7 +122,7 @@ public string PrefillSignatureName /// Cannot be used together with Required preset for Signature name [JsonProperty("force_new_signature", NullValueHandling = NullValueHandling.Ignore)] [JsonConverter(typeof(BoolToIntJsonConverter))] - public bool ForceNewSignature + public bool? ForceNewSignature { get { return forceNewSignature; } set @@ -136,7 +136,7 @@ public bool ForceNewSignature forceNewSignature = value; - if (value) + if (value != null && (bool) value) { isPrefilledSignatureName = true; } @@ -185,6 +185,6 @@ public string RequiredPresetSignatureName /// [JsonProperty("redirect_target", NullValueHandling = NullValueHandling.Ignore)] [JsonConverter(typeof(StringEnumConverter))] - public RedirectTarget RedirectTarget { get; set; } + public RedirectTarget? RedirectTarget { get; set; } } } From 9530dac10c63fa9ae7536816e6218c3f59e6e6bf Mon Sep 17 00:00:00 2001 From: AlexNDRmac Date: Wed, 16 Oct 2024 21:59:20 +0300 Subject: [PATCH 13/14] add tests --- .../UnitTests/Models/EmbeddedInviteTest.cs | 50 ++++++++++++++++++- 1 file changed, 49 insertions(+), 1 deletion(-) diff --git a/SignNow.Net.Test/UnitTests/Models/EmbeddedInviteTest.cs b/SignNow.Net.Test/UnitTests/Models/EmbeddedInviteTest.cs index 17e7e1f2..06c92ec0 100644 --- a/SignNow.Net.Test/UnitTests/Models/EmbeddedInviteTest.cs +++ b/SignNow.Net.Test/UnitTests/Models/EmbeddedInviteTest.cs @@ -7,7 +7,7 @@ namespace UnitTests.Models { [TestClass] - public class EmbeddedInviteTest + public class EmbeddedInviteTest : SignNowTestBase { [TestMethod] public void ThrowsExceptionForInvalidEmail() @@ -33,5 +33,53 @@ public void ThrowsExceptionForNotAllowedRange() StringAssert.Contains(exception.Message, "Value cannot be 0"); Assert.AreEqual("SigningOrder", exception.ParamName); } + + [TestMethod] + public void ThrowsExceptionForSignatureFieldCharsMore255Symbols() + { + var invite = new EmbeddedInvite(); + + var exception = Assert.ThrowsException( + () => invite.PrefillSignatureName = Faker.Random.String(300)); + + StringAssert.Contains(exception.Message, "Prefilled text in the Signature field can be maximum 255 characters."); + Assert.AreEqual("PrefillSignatureName", exception.ParamName); + } + + [TestMethod] + public void ThrowsExceptionIfRequiredSignatureNameEnabled() + { + var invite = new EmbeddedInvite + { + RequiredPresetSignatureName = "test" + }; + + var exception = Assert.ThrowsException( + () => invite.PrefillSignatureName = "prefill"); + + StringAssert.Contains(exception.Message, "Required preset for Signature name is set. Cannot be used together with"); + Assert.AreEqual("PrefillSignatureName", exception.ParamName); + + exception = Assert.ThrowsException( + () => invite.ForceNewSignature = true); + + StringAssert.Contains(exception.Message, "Required preset for Signature name is set. Cannot be used together with"); + Assert.AreEqual("ForceNewSignature", exception.ParamName); + } + + [TestMethod] + public void ThrowsExceptionIfPrefilledSignatureName() + { + var invite = new EmbeddedInvite + { + PrefillSignatureName = "test" + }; + + var exception = Assert.ThrowsException( + () => invite.RequiredPresetSignatureName = "prefill"); + + StringAssert.Contains(exception.Message, "Prefill for Signature name or Force new signature is set. Cannot be used together with"); + Assert.AreEqual("RequiredPresetSignatureName", exception.ParamName); + } } } From e0839b3aa3114f60eb0d3204357bc2ccdf577ed8 Mon Sep 17 00:00:00 2001 From: AlexNDRmac Date: Wed, 16 Oct 2024 22:01:43 +0300 Subject: [PATCH 14/14] bump version --- SignNow.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SignNow.props b/SignNow.props index d305c597..021bf273 100644 --- a/SignNow.props +++ b/SignNow.props @@ -1,6 +1,6 @@ - 1.2.3 + 1.3.0 signNow signNow SignNow.NET