Изменяем тип карточки через расширение на метаинформацию
Изменяем тип карточки через расширение на метаинформацию¶
В некоторых случаях тип карточки (или задания) из типового решения требуется изменить таким образом, чтобы не требовалось объединение изменений при переходе на новые сборки платформы. Или же требуется в конкретном типе карточки указать контрол или валидатор со ссылкой на поля виртуальной секции, которая добавляется расширением. Например, это содержимое вкладки “Процесс согласования” для типов карточек, добавленных в типовое решение. Для того, чтобы модифицировать таким образом тип карточки, необходимо написать расширение на метаинформацию.
Рассмотрим следующий пример. Пусть в типовом решении поле “Согласующие” в этапе согласования не связано с валидатором “Непустая секция”, т.е. возможны этапы без согласующих. Для конкретного типа карточки “Договор” необходимо добавить такой валидатор, чтобы у любого этапа были согласующие. Поле “Согласующие” связано с виртуальной секцией KrApproversVirtual, которая добавляется расширением типового решения. Поэтому напишем расширение на метаинформацию, добавляющее такой валидатор.
Расширение напишем в сборке Tessa.Extensions.Shared
, т.к. оно потребуется и на сервере (для работы с пользователями TessaClient и web-клиента, а также в плагинах Chronos), и на клиенте (для предпросмотра типа карточки с расширениями в TessaAdmin).
using System;
using System.Linq;
using System.Threading.Tasks;
using Tessa.Cards;
using Tessa.Cards.Extensions;
using Tessa.Cards.Validation;
using Tessa.Extensions.Default.Shared;
using Tessa.Platform.Storage;
namespace Tessa.Extensions.Shared.Metadata
{
public sealed class MyApproversMetadataExtension : CardTypeMetadataExtension
{
public MyApproversMetadataExtension(ICardMetadata clientCardMetadata)
: base(clientCardMetadata)
{
}
public MyApproversMetadataExtension()
: base()
{
}
private static readonly Guid approversSectionID = new Guid("b47d668e-7bf0-4165-a10c-6fe22ee10882");
public override async Task ModifyTypes(ICardMetadataExtensionContext context)
{
// в типе карточки "Договор"
CardType cardType = await this.TryGetCardTypeAsync(context, DefaultCardTypes.ContractTypeID,
useServerMetadataOnClient: false);
if (cardType == null || cardType.IsSealed)
{
return;
}
// на всякий случай проверим, что нужного валидатора нет, например, он не был добавлен в новой версии платформы
if (cardType.Validators.Any(x =>
x.ValidatorSettings.TryGet<Guid?>(CardValidatorSettings.SectionIDSetting)
== approversSectionID))
{
return;
}
// добавляем валидатор "Непустая секция" для коллекционной секции KrApproversVirtual
cardType.Validators.Add(
new CardTypeValidator
{
Type = CardValidatorTypes.NotNullTable,
ValidatorSettings =
{
{ CardValidatorSettings.SectionIDSetting, approversSectionID },
// сообщение может быть строкой локализации
{ CardValidatorSettings.ErrorMessageSetting, "Согласующие не указаны." },
{ CardValidatorSettings.WarningSetting, false },
},
});
}
}
}
Класс Registrator для регистрации на сервере добавим в сборку Tessa.Extensions.Server
.
using Tessa.Cards.Extensions;
using Tessa.Extensions.Shared.Metadata;
using Unity.Injection;
using Unity.Lifetime;
namespace Tessa.Extensions.Server.Metadata
{
[Registrator]
public sealed class Registrator : RegistratorBase
{
public override void RegisterUnity()
{
this.UnityContainer
.RegisterType<MyApproversMetadataExtension>(
new ContainerControlledLifetimeManager(),
new InjectionConstructor())
;
}
public override void RegisterExtensions(IExtensionContainer extensionContainer)
{
extensionContainer
.RegisterExtension<ICardMetadataExtension, MyApproversMetadataExtension>(x => x
.WithOrder(ExtensionStage.AfterPlatform, 100)
.WithUnity(this.UnityContainer))
;
}
}
}
Класс Registrator для регистрации на клиенте добавим в сборку Tessa.Extensions.Client
.
using Tessa.Cards;
using Tessa.Cards.Extensions;
using Tessa.Extensions.Shared.Metadata;
using Unity.Injection;
using Unity.Lifetime;
namespace Tessa.Extensions.Client.Metadata
{
[Registrator]
public sealed class Registrator : RegistratorBase
{
public override void RegisterUnity()
{
this.UnityContainer
.RegisterType<MyApproversMetadataExtension>(
new ContainerControlledLifetimeManager(),
new InjectionConstructor(typeof(ICardMetadata)))
;
}
public override void RegisterExtensions(IExtensionContainer extensionContainer)
{
extensionContainer
.RegisterExtension<ICardMetadataExtension, MyApproversMetadataExtension>(x => x
.WithOrder(ExtensionStage.AfterPlatform, 100)
.WithUnity(this.UnityContainer))
;
}
}
}
Теперь надо проверить работу валидатора.
-
В Tessa Admin откройте предпросмотр типа карточки
Contract
(тип договора) и убедитесь, что в режиме “Показать с расширениями” в строке с этапом в таблице с согласующими поле “Согласующие” отмечено звёздочкой как обязательное, а при сохранении строки без согласующих выводится окно с ошибкой. -
Теперь откройте предпросмотр с расширениями для любого другого типа карточки и убедитесь, что не возникает ошибок, а для карточек с согласованием поле “Согласующие” не отмечено как обязательное.
-
В Tessa Client аналогично создайте или откройте карточки типа
Contract
и другую карточку с согласованием, и убедитесь, что валидатор добавился только в типContract
, а другие типы карточек остались без изменений.