Skip to content

Commit

Permalink
Email & phone contact types, @username links accepted for Telegram\Tw…
Browse files Browse the repository at this point in the history
…itter. Closes #278. Closes #275.
  • Loading branch information
impworks committed Jan 27, 2024
1 parent de90684 commit a2787ff
Show file tree
Hide file tree
Showing 8 changed files with 160 additions and 108 deletions.
9 changes: 9 additions & 0 deletions src/Bonsai/Areas/Admin/Scripts/page-facts.js
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,15 @@
getList: function() {
var root = this.data[this.def.key] || {};
return root['Values'] || [];
},
contactPlaceholder: function (type) {
if (type === 'Email')
return 'mailbox@example.com';
if (type === 'Phone')
return '+79251234567';
if (type === 'Telegram' || type === 'Twitter')
return '@username';
return 'https://';
}
}
});
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
@using Bonsai.Code.DomainModel.Facts.Models
@using Impworks.Utils.Format
@model SocialProfilesFactModel
@model ContactsFactModel

@Model.ShortTitle:
<ul>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
@using Bonsai.Code.DomainModel.Facts.Models
@using Impworks.Utils.Format
<script type="text/x-template" data-kind="fact-template" id="SocialProfilesFactModel">
<script type="text/x-template" data-kind="fact-template" id="ContactsFactModel">
<div class="fact-wrapper">
<h6>
{{def.title}}
Expand All @@ -15,7 +15,7 @@
<div class="form-group col-sm-4">
<label>Тип</label>
<select v-model="row.Type" class="form-control form-control-sm mr-2">
@foreach (var prof in EnumHelper.GetEnumDescriptions<SocialProfileType>())
@foreach (var prof in EnumHelper.GetEnumDescriptions<ContactType>())
{
<option value="@prof.Key">@prof.Value</option>
}
Expand All @@ -26,7 +26,7 @@
<i class="fa fa-remove"></i>
</button>
<label>Ссылка</label>
<input type="text" v-model="row.Value" class="form-control form-control-sm mr-2" />
<input type="text" v-model="row.Value" :placeholder="contactPlaceholder(row.Type)" class="form-control form-control-sm mr-2" />
</div>
</div>
</div>
Expand Down
36 changes: 36 additions & 0 deletions src/Bonsai/Areas/Front/Views/Page/Facts/ContactsFactModel.cshtml
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
@using Bonsai.Code.DomainModel.Facts.Models
@using Impworks.Utils.Format
@model ContactsFactModel

<tr class="fact">
<th class="fact-title">@Model.ShortTitle</th>
</tr>
<tr class="fact">
<td class="fact-value big-icons">
@foreach (var item in Model.Values)
{
<a class="big-icon" href="@item.GetLink()" target="_blank" title="@item.Type.GetEnumDescription()">
<span class="fa @(GetIcon(item.Type))"></span>
</a>
}
</td>
</tr>

@functions {
string GetIcon(ContactType type)
{
return type switch
{
ContactType.Facebook => "fa-facebook-square",
ContactType.Twitter => "fa-twitter-square",
ContactType.Github => "fa-github",
ContactType.Youtube => "fa-youtube-play",
ContactType.Telegram => "fa-telegram",
ContactType.Odnoklassniki => "fa-odnoklassniki-square",
ContactType.Vkontakte => "fa-vk",
ContactType.Email => "fa-envelope",
ContactType.Phone => "fa-phone-square",
_ => null
};
}
}

This file was deleted.

2 changes: 1 addition & 1 deletion src/Bonsai/Code/DomainModel/Facts/FactDefinitions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ static FactDefinitions()
"Meta",
"Прочее",
false,
new FactDefinition<SocialProfilesFactModel>("SocialProfiles", "Соцсети")
new FactDefinition<ContactsFactModel>("SocialProfiles", "Контакты")
)
},

Expand Down
110 changes: 110 additions & 0 deletions src/Bonsai/Code/DomainModel/Facts/Models/ContactsFactModel.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
using System;
using System.ComponentModel;
using System.Text.RegularExpressions;
using Bonsai.Code.Utils.Validation;
using Bonsai.Data.Models;

namespace Bonsai.Code.DomainModel.Facts.Models
{
/// <summary>
/// Template for specifying known social profile links.
/// </summary>
public class ContactsFactModel: FactListModelBase<ContactFactItem>
{
public override void Validate()
{
for (var i = 1; i <= Values.Length; i++)
{
var item = Values[i-1];
if (!Enum.IsDefined(item.Type))
throw new ValidationException(nameof(Page.Facts), $"Контакт #{i}: тип не указан");

if(string.IsNullOrEmpty(item.Value))
throw new ValidationException(nameof(Page.Facts), $"Контакт #{i}: значение не указано");

if (item.Type == ContactType.Email)
{
if(!Regex.IsMatch(item.Value, ".+@.+\\..+"))
throw new ValidationException(nameof(Page.Facts), $"Контакт #{i}: адрес почты имеет некорректный формат");
}
else if (item.Type == ContactType.Phone)
{
if (!Regex.IsMatch(item.Value, "\\+[0-9]+"))
throw new ValidationException(nameof(Page.Facts), $"Контакт #{i}: телефон должен начинаться с + и содержать только цифры");
}
else if (item.Type == ContactType.Telegram || item.Type == ContactType.Twitter)
{
if(!item.Value.StartsWith("https://"))
if(!Regex.IsMatch(item.Value, "@[a-z0-9_-]+"))
throw new ValidationException(nameof(Page.Facts), $"Контакт #{i}: значение должно быть ссылкой, либо начинаться с @");
}
else if (!item.Value.StartsWith("https://"))
throw new ValidationException(nameof(Page.Facts), $"Контакт #{i}: ссылка должна начинаться с 'https://'");
}
}
}

/// <summary>
/// Single social profile link.
/// </summary>
public class ContactFactItem
{
/// <summary>
/// Type of the profile.
/// </summary>
public ContactType Type { get; set; }

/// <summary>
/// Link to the profile.
/// </summary>
public string Value { get; set; }

/// <summary>
/// Returns the public hyperlink to this contact.
/// </summary>
public string GetLink()
{
return Type switch
{
ContactType.Phone => "tel:" + Value,
ContactType.Email => "mailto:" + Value,
ContactType.Telegram => Value.StartsWith('@') ? "https://t.me/" + Value.Substring(1) : Value,
ContactType.Twitter => Value.StartsWith('@') ? "https://twitter.com/" + Value.Substring(1) : Value,
_ => Value
};
}
}

/// <summary>
/// Known social profile links (to display icons properly).
/// </summary>
public enum ContactType
{
[Description("Facebook")]
Facebook,

[Description("Twitter")]
Twitter,

[Description("Одноклассники")]
Odnoklassniki,

[Description("Вконтакте")]
Vkontakte,

[Description("Telegram")]
Telegram,

[Description("Youtube")]
Youtube,

[Description("Github")]
Github,

[Description("E-mail")]
Email,

[Description("Телефон")]
Phone,
}
}

This file was deleted.

0 comments on commit a2787ff

Please sign in to comment.