diff --git a/backend/src/Notifo.Domain.Integrations.Abstractions/IntegrationProperty.cs b/backend/src/Notifo.Domain.Integrations.Abstractions/IntegrationProperty.cs
index 3d618875..80db4098 100644
--- a/backend/src/Notifo.Domain.Integrations.Abstractions/IntegrationProperty.cs
+++ b/backend/src/Notifo.Domain.Integrations.Abstractions/IntegrationProperty.cs
@@ -39,6 +39,8 @@ public sealed record IntegrationProperty(string Name, PropertyType Type)
public string? Pattern { get; init; }
+ public PropertyFormat Format { get; init; } = PropertyFormat.None;
+
public bool IsValid(string? input, [MaybeNullWhen(true)] out string error)
{
switch (Type)
@@ -170,6 +172,32 @@ private bool TryGetString(string? input, [MaybeNullWhen(true)] out string error,
}
}
+ if (!string.IsNullOrWhiteSpace(input) && Format != PropertyFormat.None)
+ {
+ switch (Format)
+ {
+ case PropertyFormat.Email:
+ if (!Regex.IsMatch(input, ValidationPatterns.Email))
+ {
+ error = Texts.IntegrationPropertyFormatEmail;
+ return false;
+ }
+
+ break;
+ case PropertyFormat.HttpUrl:
+ // We only allow "http" and "https" schemas to enable the usage of URL field for HttpClient requests.
+ if (!Uri.TryCreate(input, UriKind.Absolute, out var uri)
+ || (!string.Equals(uri.Scheme, "http", StringComparison.OrdinalIgnoreCase) && !string.Equals(uri.Scheme, "https", StringComparison.OrdinalIgnoreCase))
+ )
+ {
+ error = Texts.IntegrationPropertyFormatHttpUrl;
+ return false;
+ }
+
+ break;
+ }
+ }
+
return true;
}
diff --git a/backend/src/Notifo.Domain.Integrations.Abstractions/PropertyFormat.cs b/backend/src/Notifo.Domain.Integrations.Abstractions/PropertyFormat.cs
new file mode 100644
index 00000000..d66549c6
--- /dev/null
+++ b/backend/src/Notifo.Domain.Integrations.Abstractions/PropertyFormat.cs
@@ -0,0 +1,15 @@
+// ==========================================================================
+// Notifo.io
+// ==========================================================================
+// Copyright (c) Sebastian Stehle
+// All rights reserved. Licensed under the MIT license.
+// ==========================================================================
+
+namespace Notifo.Domain.Integrations;
+
+public enum PropertyFormat
+{
+ None,
+ Email,
+ HttpUrl
+}
diff --git a/backend/src/Notifo.Domain.Integrations.Abstractions/Resources/Texts.Designer.cs b/backend/src/Notifo.Domain.Integrations.Abstractions/Resources/Texts.Designer.cs
index 0f9c22cd..a9c1d200 100644
--- a/backend/src/Notifo.Domain.Integrations.Abstractions/Resources/Texts.Designer.cs
+++ b/backend/src/Notifo.Domain.Integrations.Abstractions/Resources/Texts.Designer.cs
@@ -69,6 +69,24 @@ internal static string IntegrationPropertyAllowedValue {
}
}
+ ///
+ /// Looks up a localized string similar to Field is not a valid e-mail..
+ ///
+ internal static string IntegrationPropertyFormatEmail {
+ get {
+ return ResourceManager.GetString("IntegrationPropertyFormatEmail", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Field is not a valid URL (remember about the protocol - http or https)..
+ ///
+ internal static string IntegrationPropertyFormatHttpUrl {
+ get {
+ return ResourceManager.GetString("IntegrationPropertyFormatHttpUrl", resourceCulture);
+ }
+ }
+
///
/// Looks up a localized string similar to Not a valid boolean value..
///
diff --git a/backend/src/Notifo.Domain.Integrations.Abstractions/Resources/Texts.resx b/backend/src/Notifo.Domain.Integrations.Abstractions/Resources/Texts.resx
index acbb057b..3e20ce90 100644
--- a/backend/src/Notifo.Domain.Integrations.Abstractions/Resources/Texts.resx
+++ b/backend/src/Notifo.Domain.Integrations.Abstractions/Resources/Texts.resx
@@ -120,6 +120,12 @@
Field is not an allowed value.
+
+ Field is not a valid e-mail.
+
+
+ Field is not a valid URL (remember about the protocol - http or https).
+
Not a valid boolean value.
diff --git a/backend/src/Notifo.Domain.Integrations.Abstractions/ValidationPatterns.cs b/backend/src/Notifo.Domain.Integrations.Abstractions/ValidationPatterns.cs
new file mode 100644
index 00000000..11218c73
--- /dev/null
+++ b/backend/src/Notifo.Domain.Integrations.Abstractions/ValidationPatterns.cs
@@ -0,0 +1,14 @@
+// ==========================================================================
+// Notifo.io
+// ==========================================================================
+// Copyright (c) Sebastian Stehle
+// All rights reserved. Licensed under the MIT license.
+// ==========================================================================
+
+namespace Notifo.Domain.Integrations;
+
+public static class ValidationPatterns
+{
+ // Taken from Yup's source code (validation library used on the front-end side).
+ public const string Email = @"^[a-zA-Z0-9.!#$%&'*+\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$";
+}
diff --git a/backend/src/Notifo.Domain.Integrations/AmazonSES/IntegratedAmazonSESIntegration.cs b/backend/src/Notifo.Domain.Integrations/AmazonSES/IntegratedAmazonSESIntegration.cs
index 27c9b83f..49db6aed 100644
--- a/backend/src/Notifo.Domain.Integrations/AmazonSES/IntegratedAmazonSESIntegration.cs
+++ b/backend/src/Notifo.Domain.Integrations/AmazonSES/IntegratedAmazonSESIntegration.cs
@@ -29,11 +29,11 @@ public sealed class IntegratedAmazonSESIntegration : IIntegration, IInitializabl
public static readonly IntegrationProperty FromEmailProperty = new IntegrationProperty("fromEmail", PropertyType.Text)
{
- Pattern = Patterns.Email,
EditorLabel = Texts.Email_FromEmailLabel,
EditorDescription = Texts.Email_FromEmailDescription,
IsRequired = true,
- Summary = true
+ Summary = true,
+ Format = PropertyFormat.Email
};
public static readonly IntegrationProperty FromNameProperty = new IntegrationProperty("fromName", PropertyType.Text)
diff --git a/backend/src/Notifo.Domain.Integrations/Http/HttpIntegration.cs b/backend/src/Notifo.Domain.Integrations/Http/HttpIntegration.cs
index 78790411..dea8ce2b 100644
--- a/backend/src/Notifo.Domain.Integrations/Http/HttpIntegration.cs
+++ b/backend/src/Notifo.Domain.Integrations/Http/HttpIntegration.cs
@@ -18,7 +18,8 @@ public sealed partial class HttpIntegration : IIntegration
EditorLabel = Texts.Webhook_URLLabel,
EditorDescription = Texts.Webhook_URLHints,
IsRequired = true,
- Summary = true
+ Summary = true,
+ Format = PropertyFormat.HttpUrl,
};
private static readonly IntegrationProperty HttpMethodProperty = new IntegrationProperty("Method", PropertyType.Text)
diff --git a/backend/src/Notifo.Domain.Integrations/Mailchimp/MailchimpIntegration.cs b/backend/src/Notifo.Domain.Integrations/Mailchimp/MailchimpIntegration.cs
index 8639ceb4..6e6e815b 100644
--- a/backend/src/Notifo.Domain.Integrations/Mailchimp/MailchimpIntegration.cs
+++ b/backend/src/Notifo.Domain.Integrations/Mailchimp/MailchimpIntegration.cs
@@ -22,11 +22,11 @@ public sealed partial class MailchimpIntegration : IIntegration
public static readonly IntegrationProperty FromEmailProperty = new IntegrationProperty("fromEmail", PropertyType.Text)
{
- Pattern = Patterns.Email,
EditorLabel = Texts.Email_FromEmailLabel,
EditorDescription = Texts.Email_FromEmailDescription,
IsRequired = true,
- Summary = true
+ Summary = true,
+ Format = PropertyFormat.Email
};
public static readonly IntegrationProperty FromNameProperty = new IntegrationProperty("fromName", PropertyType.Text)
diff --git a/backend/src/Notifo.Domain.Integrations/Mailjet/MailjetIntegration.cs b/backend/src/Notifo.Domain.Integrations/Mailjet/MailjetIntegration.cs
index 28593841..02d0002a 100644
--- a/backend/src/Notifo.Domain.Integrations/Mailjet/MailjetIntegration.cs
+++ b/backend/src/Notifo.Domain.Integrations/Mailjet/MailjetIntegration.cs
@@ -29,11 +29,11 @@ public sealed partial class MailjetIntegration : IIntegration
public static readonly IntegrationProperty FromEmailProperty = new IntegrationProperty("fromEmail", PropertyType.Text)
{
- Pattern = Patterns.Email,
EditorLabel = Texts.Email_FromEmailLabel,
EditorDescription = Texts.Email_FromEmailDescription,
IsRequired = true,
- Summary = true
+ Summary = true,
+ Format = PropertyFormat.Email
};
public static readonly IntegrationProperty FromNameProperty = new IntegrationProperty("fromName", PropertyType.Text)
diff --git a/backend/src/Notifo.Domain.Integrations/Patterns.cs b/backend/src/Notifo.Domain.Integrations/Patterns.cs
deleted file mode 100644
index b0eb9100..00000000
--- a/backend/src/Notifo.Domain.Integrations/Patterns.cs
+++ /dev/null
@@ -1,13 +0,0 @@
-// ==========================================================================
-// Notifo.io
-// ==========================================================================
-// Copyright (c) Sebastian Stehle
-// All rights reserved. Licensed under the MIT license.
-// ==========================================================================
-
-namespace Notifo.Domain.Integrations;
-
-public static class Patterns
-{
- public const string Email = @"^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-||_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+([a-z]+|\d|-|\.{0,1}|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])?([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))$";
-}
diff --git a/backend/src/Notifo.Domain.Integrations/Resources/Texts.Designer.cs b/backend/src/Notifo.Domain.Integrations/Resources/Texts.Designer.cs
index e18d0bf9..60c00818 100644
--- a/backend/src/Notifo.Domain.Integrations/Resources/Texts.Designer.cs
+++ b/backend/src/Notifo.Domain.Integrations/Resources/Texts.Designer.cs
@@ -1017,7 +1017,7 @@ internal static string Webhook_SendNotificationsLabel {
}
///
- /// Looks up a localized string similar to The URL to your server endpoint..
+ /// Looks up a localized string similar to The URL to your server endpoint. Remember about the protocol (http, https)..
///
internal static string Webhook_URLHints {
get {
diff --git a/backend/src/Notifo.Domain.Integrations/Resources/Texts.resx b/backend/src/Notifo.Domain.Integrations/Resources/Texts.resx
index 8a738434..ed18f281 100644
--- a/backend/src/Notifo.Domain.Integrations/Resources/Texts.resx
+++ b/backend/src/Notifo.Domain.Integrations/Resources/Texts.resx
@@ -438,7 +438,7 @@ When you have done this send me an /update command.
Send Always
- The URL to your server endpoint.
+ The URL to your server endpoint. Remember about the protocol (http, https).
URL
diff --git a/backend/src/Notifo.Domain.Integrations/Smtp/SmtpIntegration.cs b/backend/src/Notifo.Domain.Integrations/Smtp/SmtpIntegration.cs
index b40735d3..4c406b65 100644
--- a/backend/src/Notifo.Domain.Integrations/Smtp/SmtpIntegration.cs
+++ b/backend/src/Notifo.Domain.Integrations/Smtp/SmtpIntegration.cs
@@ -42,11 +42,11 @@ public sealed partial class SmtpIntegration : IIntegration
public static readonly IntegrationProperty FromEmailProperty = new IntegrationProperty("fromEmail", PropertyType.Text)
{
- Pattern = Patterns.Email,
EditorLabel = Texts.Email_FromEmailLabel,
EditorDescription = Texts.Email_FromEmailDescription,
IsRequired = true,
- Summary = true
+ Summary = true,
+ Format = PropertyFormat.Email,
};
public static readonly IntegrationProperty FromNameProperty = new IntegrationProperty("fromName", PropertyType.Text)
diff --git a/backend/src/Notifo/Areas/Api/Controllers/Apps/Dtos/IntegrationPropertyDto.cs b/backend/src/Notifo/Areas/Api/Controllers/Apps/Dtos/IntegrationPropertyDto.cs
index c15e846e..e3ef3f6e 100644
--- a/backend/src/Notifo/Areas/Api/Controllers/Apps/Dtos/IntegrationPropertyDto.cs
+++ b/backend/src/Notifo/Areas/Api/Controllers/Apps/Dtos/IntegrationPropertyDto.cs
@@ -72,6 +72,11 @@ public sealed class IntegrationPropertyDto
///
public string? Pattern { get; set; }
+ ///
+ /// Format of the field, used to both validate the input and to provide hints to the user.
+ ///
+ public PropertyFormat Format { get; set; }
+
///
/// The default value.
///
diff --git a/backend/tests/Notifo.Domain.Tests/Integrations/IntegrationPropertyTests.cs b/backend/tests/Notifo.Domain.Tests/Integrations/IntegrationPropertyTests.cs
index 34b0c3a7..2e41cdc5 100644
--- a/backend/tests/Notifo.Domain.Tests/Integrations/IntegrationPropertyTests.cs
+++ b/backend/tests/Notifo.Domain.Tests/Integrations/IntegrationPropertyTests.cs
@@ -158,6 +158,77 @@ public void Should_not_fail_if_undefined_value_is_not_an_allowed_value(string? i
Assert.Equal("allowed", property.GetString(source));
}
+ [Theory]
+ [InlineData("localhost.com/test")]
+ [InlineData("192.168.0.101")]
+ [InlineData("randomString")]
+ public void Should_fail_if_url_is_invalid(string? input)
+ {
+ var source = new Dictionary
+ {
+ ["key"] = input!
+ };
+
+ var property = new IntegrationProperty("key", PropertyType.Text)
+ {
+ Format = PropertyFormat.HttpUrl
+ };
+
+ Assert.Throws(() => property.GetString(source));
+ }
+
+ [Theory]
+ [InlineData("http://192.168.0.101/")]
+ [InlineData("http://localhost/test")]
+ [InlineData("https://example.com/test?query=example")]
+ [InlineData("http://login:password@test.pl/random")]
+ public void Should_get_url_if_value_is_valid(string? input)
+ {
+ var source = new Dictionary
+ {
+ ["key"] = input!
+ };
+
+ var property = new IntegrationProperty("key", PropertyType.Text)
+ {
+ Format = PropertyFormat.HttpUrl
+ };
+
+ Assert.Equal(input, property.GetString(source));
+ }
+
+ [Fact]
+ public void Should_fail_if_email_is_invalid()
+ {
+ var source = new Dictionary
+ {
+ ["key"] = "invalidEmail"
+ };
+
+ var property = new IntegrationProperty("key", PropertyType.Text)
+ {
+ Format = PropertyFormat.Email
+ };
+
+ Assert.Throws(() => property.GetString(source));
+ }
+
+ [Fact]
+ public void Should_get_email_if_value_is_valid()
+ {
+ var source = new Dictionary
+ {
+ ["key"] = "john.doe@example.com"
+ };
+
+ var property = new IntegrationProperty("key", PropertyType.Text)
+ {
+ Format = PropertyFormat.Email
+ };
+
+ Assert.Equal(source["key"], property.GetString(source));
+ }
+
[Fact]
public void Should_get_value_if_all_requirements_are_met()
{
diff --git a/frontend/src/app/pages/app/AppAuth.tsx b/frontend/src/app/pages/app/AppAuth.tsx
index aad4b058..e6032748 100644
--- a/frontend/src/app/pages/app/AppAuth.tsx
+++ b/frontend/src/app/pages/app/AppAuth.tsx
@@ -86,7 +86,7 @@ const FormSchema = Yup.object().shape({
// Valid URL.
signoutRedirectUrl: Yup.string()
- .label(texts.auth.signoutRedirectUrl).urlI18n(),
+ .label(texts.auth.signoutRedirectUrl).httpUrlI18n(),
});
const AuthForm = ({ appDetails, scheme }: { scheme?: AuthSchemeDto } & AppAuthProps) => {
diff --git a/frontend/src/app/pages/app/AppSettings.tsx b/frontend/src/app/pages/app/AppSettings.tsx
index fd59e7bc..a0585399 100644
--- a/frontend/src/app/pages/app/AppSettings.tsx
+++ b/frontend/src/app/pages/app/AppSettings.tsx
@@ -28,7 +28,7 @@ const FormSchema = Yup.object().shape({
// Valid URL
confirmUrl: Yup.string().nullable()
- .label(texts.app.confirmUrl).urlI18n(),
+ .label(texts.app.confirmUrl).httpUrlI18n(),
});
export interface AppSettingsProps {
diff --git a/frontend/src/app/pages/integrations/IntegrationDialog.tsx b/frontend/src/app/pages/integrations/IntegrationDialog.tsx
index 66c4baf2..48786cab 100644
--- a/frontend/src/app/pages/integrations/IntegrationDialog.tsx
+++ b/frontend/src/app/pages/integrations/IntegrationDialog.tsx
@@ -124,6 +124,17 @@ export const IntegrationDialog = (props: IntegrationDialogProps) => {
propertyType = propertyType.max(property.maxLength, texts.validation.maxLengthFn);
}
+ if (property.format && property.format !== "None") {
+ switch (property.format) {
+ case "Email":
+ propertyType = propertyType.emailI18n();
+ break;
+ case "HttpUrl":
+ propertyType = propertyType.httpUrlI18n();
+ break;
+ }
+ }
+
if (property.pattern) {
propertyType = propertyType.matches(new RegExp(property.pattern), texts.validation.patternFn);
}
@@ -271,6 +282,20 @@ export const FormField = ({ property }: { property: IntegrationPropertyDto }) =>
label={label} hints={property.editorDescription} />
);
} else {
+ if (property.format && property.format !== 'None') {
+ switch (property.format) {
+ case 'Email':
+ return (
+
+ );
+ case 'HttpUrl':
+ return (
+
+ );
+ }
+ }
return (
diff --git a/frontend/src/app/pages/users/UserDialog.tsx b/frontend/src/app/pages/users/UserDialog.tsx
index 1f62e956..2e11bd1a 100644
--- a/frontend/src/app/pages/users/UserDialog.tsx
+++ b/frontend/src/app/pages/users/UserDialog.tsx
@@ -119,7 +119,7 @@ export const UserDialog = (props: UserDialogProps) => {
-
{
+ return (
+
+
+
+ );
+ }
+
export const Url = ({ placeholder, ...other }: FormEditorProps) => {
return (
diff --git a/frontend/src/app/shared/utils/model.ts b/frontend/src/app/shared/utils/model.ts
index 46f64dda..f4c4ef59 100644
--- a/frontend/src/app/shared/utils/model.ts
+++ b/frontend/src/app/shared/utils/model.ts
@@ -5,7 +5,7 @@
* Copyright (c) Sebastian Stehle. All rights reserved.
*/
-import { ChannelCondition, ChannelRequired, ChannelSend, ConfirmMode, IsoDayOfWeek, SchedulingType, TopicChannel } from '@app/service';
+import { ChannelCondition, ChannelRequired, ChannelSend, ConfirmMode, IsoDayOfWeek , SchedulingType, TopicChannel } from '@app/service';
import { texts } from '@app/texts';
export const CHANNELS = [
@@ -106,4 +106,4 @@ export const WEEK_DAYS: ReadonlyArray> = [{
}, {
value: 'Saturday',
label: texts.common.weekDays.saturday,
-}];
\ No newline at end of file
+}];
diff --git a/frontend/src/app/shared/utils/yup.ts b/frontend/src/app/shared/utils/yup.ts
index 420a6082..dfbc2c29 100644
--- a/frontend/src/app/shared/utils/yup.ts
+++ b/frontend/src/app/shared/utils/yup.ts
@@ -13,8 +13,11 @@ function emailI18n(this: Yup.StringSchema) {
return this.email(texts.validation.emailFn);
}
-function urlI18n(this: Yup.StringSchema) {
- return this.url(texts.validation.urlFn);
+function httpUrlI18n(this: Yup.StringSchema) {
+ // This regular expression is built on top of the one
+ // from Yup, but it also allows localhost.
+ // See: https://github.com/jquense/yup/issues/224
+ return this.matches(/^(?:(?:https?):\/\/|www\.)(?:\([-A-Z0-9+&@#\/%=~_|$?!:,.\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]*\)|[-A-Z0-9+&@#\/%=~_|$?!:,.\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*(?:\([-A-Z0-9+&@#\/%=~_|$?!:,.[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]*\)|[A-Z0-9+&@#\/%=~_|$[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])$/i , texts.validation.httpUrlFn);
}
function requiredI18nNumber(this: Yup.NumberSchema) {
@@ -61,7 +64,7 @@ export function extendYup() {
Yup.addMethod(Yup.object, 'atLeastOneStringI18n', atLeastOneStringI18n);
Yup.addMethod(Yup.string, 'emailI18n', emailI18n);
- Yup.addMethod(Yup.string, 'urlI18n', urlI18n);
+ Yup.addMethod(Yup.string, 'httpUrlI18n', httpUrlI18n);
Yup.addMethod(Yup.string, 'requiredI18n', requiredI18n);
Yup.addMethod(Yup.string, 'topicI18n', topicI18n);
diff --git a/frontend/src/app/texts/en.ts b/frontend/src/app/texts/en.ts
index 57f6d443..641ab342 100644
--- a/frontend/src/app/texts/en.ts
+++ b/frontend/src/app/texts/en.ts
@@ -433,6 +433,7 @@ export const EN = {
validation: {
atLeastOnString: (p: { label?: string }) => `${p.label} needs at least one value.`,
emailFn: (p: { label?: string }) => `${p.label} must be a valid email address.`,
+ httpUrlFn: (p: { label?: string }) => `${p.label} must be a valid HTTP URL (include the protocol - http or https).`,
lessThanFn: (p: { label?: string; less: number }) => `${p.label} must be less than ${p.less || 0}.`,
maxFn: (p: { label?: string; max: number }) => `${p.label} must not greater than ${p.max}.`,
maxItemsFn: (p: { label?: string; max: number }) => `${p.label} must not have more than ${p.max}.`,
@@ -444,6 +445,5 @@ export const EN = {
patternFn: (p: { label?: string }) => `${p.label} is not in a valid format.`,
requiredFn: (p: { label?: string }) => `${p.label} is required.`,
topicFn: (p: { label?: string }) => `${p.label} must be a valid topic.`,
- urlFn: (p: { label?: string }) => `${p.label} must be a valid URL.`,
},
};
diff --git a/frontend/src/app/texts/tr.ts b/frontend/src/app/texts/tr.ts
index 70158e04..f2a3ff3e 100644
--- a/frontend/src/app/texts/tr.ts
+++ b/frontend/src/app/texts/tr.ts
@@ -417,6 +417,7 @@ export const TR = {
validation: {
atLeastOnString: (p: { label?: string }) => `${p.label} en az bir değere sahip olmalıdır.`,
emailFn: (p: { label?: string }) => `${p.label} geçerli bir e-posta adresi olmalıdır.`,
+ httpUrlFn: (p: { label?: string }) => `${p.label} geçerli bir HTTP URL'si olmalı (protokolü ekleyin - http veya https).`,
lessThanFn: (p: { label?: string; less: number }) => `${p.label} ${p.less || 0}\`dan küçük olmalıdır.`,
maxFn: (p: { label?: string; max: number }) => `${p.label} ${p.max}\`dan büyük olmamalıdır.`,
maxItemsFn: (p: { label?: string; max: number }) => `${p.label} en fazla ${p.max} öğeye sahip olmalıdır.`,
@@ -428,6 +429,5 @@ export const TR = {
patternFn: (p: { label?: string }) => `${p.label} geçerli bir formatta değil.`,
requiredFn: (p: { label?: string }) => `${p.label} zorunludur.`,
topicFn: (p: { label?: string }) => `${p.label} geçerli bir konu olmalıdır.`,
- urlFn: (p: { label?: string }) => `${p.label} geçerli bir URL olmalıdır.`,
},
};
diff --git a/frontend/src/app/typings/yup.d.ts b/frontend/src/app/typings/yup.d.ts
index 5ed7c560..2e831209 100644
--- a/frontend/src/app/typings/yup.d.ts
+++ b/frontend/src/app/typings/yup.d.ts
@@ -6,17 +6,20 @@
*/
/* eslint-disable @typescript-eslint/no-unused-vars */
+import { PropertyFormat } from '@app/service';
import { NumberSchema, ObjectSchema, StringSchema } from 'yup';
declare module 'yup' {
interface StringSchema {
emailI18n(): StringSchema;
- urlI18n(): StringSchema;
+ httpUrlI18n(): StringSchema;
requiredI18n(): StringSchema;
topicI18n(): StringSchema;
+
+ formatI18n(format: PropertyFormat): StringSchema;
}
interface NumberSchema {
diff --git a/tools/sdk/Notifo.SDK/Generated.cs b/tools/sdk/Notifo.SDK/Generated.cs
index 9c778de3..1c72de99 100644
--- a/tools/sdk/Notifo.SDK/Generated.cs
+++ b/tools/sdk/Notifo.SDK/Generated.cs
@@ -17858,6 +17858,12 @@ public partial class IntegrationPropertyDto
[Newtonsoft.Json.JsonProperty("pattern", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)]
public string Pattern { get; set; }
+ ///
+ /// Format of the field, used to both validate the input and to provide hints to the user.
+ ///
+ [Newtonsoft.Json.JsonProperty("format", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)]
+ public PropertyFormat Format { get; set; }
+
///
/// The default value.
///
@@ -17887,6 +17893,21 @@ public enum PropertyType
}
+ [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.8.0 (NJsonSchema v11.0.1.0 (Newtonsoft.Json v13.0.0.0))")]
+ public enum PropertyFormat
+ {
+
+ [System.Runtime.Serialization.EnumMember(Value = @"None")]
+ None = 0,
+
+ [System.Runtime.Serialization.EnumMember(Value = @"Email")]
+ Email = 1,
+
+ [System.Runtime.Serialization.EnumMember(Value = @"HttpUrl")]
+ HttpUrl = 2,
+
+ }
+
[System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.3.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")]
public partial class IntegrationCreatedDto
{