Skip to content

Commit

Permalink
Merge pull request #1 from kentico-ericd/29-support
Browse files Browse the repository at this point in the history
Support Xperience by Kentico 29
  • Loading branch information
kentico-ericd authored Dec 2, 2024
2 parents 841f928 + b71fae1 commit 460a15a
Show file tree
Hide file tree
Showing 33 changed files with 1,758 additions and 1,781 deletions.
352 changes: 352 additions & 0 deletions .editorconfig

Large diffs are not rendered by default.

5 changes: 5 additions & 0 deletions .markdownlint.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"MD013": false,
"MD024": false,
"no-inline-html": false
}
47 changes: 47 additions & 0 deletions Directory.Build.props
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
<Project>

<PropertyGroup>
<Authors>Eric Dugre</Authors>
<VersionPrefix>2.0.0</VersionPrefix>
<VersionSuffix></VersionSuffix>
<Description>A collection of Xperience by Kentico form components whose visibility depend on the value of another field</Description>
<PackageLicenseExpression>MIT</PackageLicenseExpression>
<PackageProjectUrl>https://github.com/kentico-ericd/xperience-depending-field-components</PackageProjectUrl>
<PackageReleaseNotes>https://github.com/kentico-ericd/xperience-depending-field-components/releases</PackageReleaseNotes>
<PackageIcon>icon.png</PackageIcon>
<PackageReadmeFile>README.md</PackageReadmeFile>
<PackageTags>kentico;xperience;tasks</PackageTags>
</PropertyGroup>

<ItemGroup>
<None Include="$(MSBuildThisFileDirectory)\img\icon.png" Pack="true" Visible="false" PackagePath="" />
<None Include="$(MSBuildThisFileDirectory)\README.md" Pack="true" Visible="false" PackagePath=""/>
</ItemGroup>

<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<WarningsAsErrors>nullable</WarningsAsErrors>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<CopyDocumentationFilesFromPackages>true</CopyDocumentationFilesFromPackages>
<CopyDebugSymbolFilesFromPackages>true</CopyDebugSymbolFilesFromPackages>
<NoWarn>$(NoWarn);1591;S3267</NoWarn>
<EnableDefaultEmbeddedResourceItems>false</EnableDefaultEmbeddedResourceItems>
</PropertyGroup>

<PropertyGroup Condition=" $(Configuration) == 'Release' ">
<ContinuousIntegrationBuild>true</ContinuousIntegrationBuild>
<IncludeSymbols>true</IncludeSymbols>
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
</PropertyGroup>

<ItemGroup Label="StaticCodeAnalysis">
<PackageReference Include="SonarAnalyzer.CSharp">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
</ItemGroup>

</Project>
16 changes: 16 additions & 0 deletions Directory.Packages.props
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<Project>
<PropertyGroup>
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
<CentralPackageVersionOverrideEnabled>false</CentralPackageVersionOverrideEnabled>
<RestorePackagesWithLockFile>true</RestorePackagesWithLockFile>
<DisableImplicitNuGetFallbackFolder>true</DisableImplicitNuGetFallbackFolder>
</PropertyGroup>
<ItemGroup>
<PackageVersion Include="Kentico.Xperience.Admin" Version="[29.1.0,)" />
<PackageVersion Include="Kentico.Xperience.Azurestorage" Version="[29.1.0,)" />
<PackageVersion Include="Kentico.Xperience.Cloud" Version="[29.1.0,)" />
<PackageVersion Include="Kentico.Xperience.Imageprocessing" Version="[29.1.0,)" />
<PackageVersion Include="Kentico.Xperience.WebApp" Version="[29.1.0,)" />
<PackageVersion Include="SonarAnalyzer.CSharp" Version="9.6.0.74858" />
</ItemGroup>
</Project>
15 changes: 7 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,18 +1,17 @@
[![Nuget](https://img.shields.io/nuget/v/Xperience.DependingFieldComponents)](https://www.nuget.org/packages/Xperience.DependingFieldComponents#versions-body-tab)
[![build](https://github.com/kentico-ericd/xperience-depending-field-components/actions/workflows/build.yml/badge.svg)](https://github.com/kentico-ericd/xperience-depending-field-components/actions/workflows/build.yml)
# Xperience Community: Depending field components

# Xperience by Kentico depending field components
[![Nuget](https://img.shields.io/nuget/v/XperienceCommunity.DependingFieldComponents)](https://www.nuget.org/packages/XperienceCommunity.DependingFieldComponents#versions-body-tab)
[![build](https://github.com/kentico-ericd/xperience-community-depending-field-components/actions/workflows/build.yml/badge.svg)](https://github.com/kentico-ericd/xperience-community-depending-field-components/actions/workflows/build.yml)

When editing content, often developers will want to hide a field's input based on the value of another field. For example, if an article _might_ contain a link to an external site, there will be a checkbox called "Has external link." If the checkbox is not checked, the text input for the external link should be hidden.

This project adds custom form components to Xperience by Kentico which allows developers to configure depending field functionality directly in the UI or code. These form components can be used in content types and widget properties.

## Compatibility
## Library Version Matrix

The following Xperience by Kentico versions have been tested and are supported by this project:

- 27.y.z
- 28.y.z
| Xperience Version | Library Version |
| ------------------- | ----------------- |
| >= 29.1.0 | >= 2.0.0 |

## Components

Expand Down
7 changes: 7 additions & 0 deletions global.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"sdk": {
"version": "8.0.101",
"rollForward": "latestMajor",
"allowPrerelease": false
}
}
14 changes: 14 additions & 0 deletions nuget.config
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<packageSources>
<!--To inherit the global NuGet package sources remove the <clear/> line below -->
<clear />
<add key="nuget.org" value="https://api.nuget.org/v3/index.json" />
</packageSources>
<packageSourceMapping>
<!-- key value for <packageSource> should match key values from <packageSources> element -->
<packageSource key="nuget.org">
<package pattern="*" />
</packageSource>
</packageSourceMapping>
</configuration>
40 changes: 18 additions & 22 deletions src/DependingFieldComponentsConstants.cs
Original file line number Diff line number Diff line change
@@ -1,32 +1,28 @@
using CMS;
namespace XperienceCommunity.DependingFieldComponents;

[assembly: AssemblyDiscoverable]
namespace Xperience.DependingFieldComponents
public static class DependingFieldComponentsConstants
{
public static class DependingFieldComponentsConstants
{
public const string TEXTINPUT_IDENTIFIER = "Xperience.DependingFieldComponents.TextInput";
public const string TEXTINPUT_FIELDDESCRIPTION = "Text input with field dependency";
public const string TEXTINPUT_IDENTIFIER = "XperienceCommunity.DependingFieldComponents.TextInput";
public const string TEXTINPUT_FIELDDESCRIPTION = "Text input with field dependency";

public const string NUMBERINPUT_IDENTIFIER = "Xperience.DependingFieldComponents.NumberInput";
public const string NUMBERINPUT_FIELDDESCRIPTION = "Number input with field dependency";
public const string NUMBERINPUT_IDENTIFIER = "XperienceCommunity.DependingFieldComponents.NumberInput";
public const string NUMBERINPUT_FIELDDESCRIPTION = "Number input with field dependency";

public const string RADIOGROUP_IDENTIFIER = "Xperience.DependingFieldComponents.RadioGroupInput";
public const string RADIOGROUP_FIELDDESCRIPTION = "Radio button group with field dependency";
public const string RADIOGROUP_IDENTIFIER = "XperienceCommunity.DependingFieldComponents.RadioGroupInput";
public const string RADIOGROUP_FIELDDESCRIPTION = "Radio button group with field dependency";

public const string DROPDOWNINPUT_IDENTIFIER = "Xperience.DependingFieldComponents.DropdownInput";
public const string DROPDOWNINPUT_FIELDDESCRIPTION = "Dropdown selector with field dependency";
public const string DROPDOWNINPUT_IDENTIFIER = "XperienceCommunity.DependingFieldComponents.DropdownInput";
public const string DROPDOWNINPUT_FIELDDESCRIPTION = "Dropdown selector with field dependency";

public const string CHECKBOXINPUT_IDENTIFIER = "Xperience.DependingFieldComponents.CheckboxInput";
public const string CHECKBOXINPUT_FIELDDESCRIPTION = "Checkbox with field dependency";
public const string CHECKBOXINPUT_IDENTIFIER = "XperienceCommunity.DependingFieldComponents.CheckboxInput";
public const string CHECKBOXINPUT_FIELDDESCRIPTION = "Checkbox with field dependency";

public const string DATETIMEINPUT_IDENTIFIER = "Xperience.DependingFieldComponents.DateTimeInput";
public const string DATETIMEINPUT_FIELDDESCRIPTION = "Datetime input with field dependency";
public const string DATETIMEINPUT_IDENTIFIER = "XperienceCommunity.DependingFieldComponents.DateTimeInput";
public const string DATETIMEINPUT_FIELDDESCRIPTION = "Datetime input with field dependency";

public const string PROPERTY_DEPENDSON_LABEL = "Depends on";
public const string PROPERTY_DEPENDSON_TOOLTIP = "The name of the field that determines this field's visibility";
public const string PROPERTY_DEPENDSON_LABEL = "Depends on";
public const string PROPERTY_DEPENDSON_TOOLTIP = "The name of the field that determines this field's visibility";

public const string PROPERTY_EXPECTEDVALUE_LABEL = "Expected value";
public const string PROPERTY_EXPECTEDVALUE_TOOLTIP = "The value of the depending field which will reveal this field";
}
public const string PROPERTY_EXPECTEDVALUE_LABEL = "Expected value";
public const string PROPERTY_EXPECTEDVALUE_TOOLTIP = "The value of the depending field which will reveal this field";
}
8 changes: 0 additions & 8 deletions src/Directory.Build.props

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
using Kentico.Xperience.Admin.Base.FormAnnotations;

namespace Xperience.DependingFieldComponents.FormComponents.CheckboxInputDependsOnFieldComponent
namespace XperienceCommunity.DependingFieldComponents.FormComponents.CheckboxInputDependsOnFieldComponent;

public class CheckboxInputDependsOnFieldAttribute : FormComponentAttribute, IDependsOnPropertyProperties
{
public class CheckboxInputDependsOnFieldAttribute : FormComponentAttribute, IDependsOnPropertyProperties
{
public string? DependsOn { get; set; }
public string? DependsOn { get; set; }


public string? ExpectedValue { get; set; }
}
public string? ExpectedValue { get; set; }
}
Original file line number Diff line number Diff line change
@@ -1,34 +1,36 @@
using Kentico.Xperience.Admin.Base.Forms;

using Xperience.DependingFieldComponents;
using Xperience.DependingFieldComponents.FormComponents.CheckboxInputDependsOnFieldComponent;
using Xperience.DependingFieldComponents.VisibilityConditions;
using XperienceCommunity.DependingFieldComponents;
using XperienceCommunity.DependingFieldComponents.FormComponents.CheckboxInputDependsOnFieldComponent;
using XperienceCommunity.DependingFieldComponents.VisibilityConditions;

[assembly: RegisterFormComponent(DependingFieldComponentsConstants.CHECKBOXINPUT_IDENTIFIER, typeof(CheckboxInputDependsOnFieldComponent), DependingFieldComponentsConstants.CHECKBOXINPUT_FIELDDESCRIPTION)]
namespace Xperience.DependingFieldComponents.FormComponents.CheckboxInputDependsOnFieldComponent
[assembly: RegisterFormComponent(
DependingFieldComponentsConstants.CHECKBOXINPUT_IDENTIFIER,
typeof(CheckboxInputDependsOnFieldComponent),
DependingFieldComponentsConstants.CHECKBOXINPUT_FIELDDESCRIPTION)]
namespace XperienceCommunity.DependingFieldComponents.FormComponents.CheckboxInputDependsOnFieldComponent;

/// <summary>
/// A form component which can be configured to appear based on the value of another field.
/// </summary>
[ComponentAttribute(typeof(CheckboxInputDependsOnFieldAttribute))]
public class CheckboxInputDependsOnFieldComponent : FormComponent<DependsOnPropertyProperties, CheckBoxClientProperties, bool>
{
public override string ClientComponentName => "@kentico/xperience-admin-base/Checkbox";


/// <summary>
/// A form component which can be configured to appear based on the value of another field.
/// Initializes a new instance of <see cref="CheckboxInputDependsOnFieldComponent"/>
/// </summary>
[ComponentAttribute(typeof(CheckboxInputDependsOnFieldAttribute))]
public class CheckboxInputDependsOnFieldComponent : FormComponent<DependsOnPropertyProperties, CheckBoxClientProperties, bool>
public CheckboxInputDependsOnFieldComponent()
{
public override string ClientComponentName => "@kentico/xperience-admin-base/Checkbox";


/// <summary>
/// Initializes a new instance of <see cref="CheckboxInputDependsOnFieldComponent"/>
/// </summary>
public CheckboxInputDependsOnFieldComponent()
{
}
}


protected override void ConfigureComponent()
{
DependingFieldVisibilityCondition.Configure(this);
protected override void ConfigureComponent()
{
DependingFieldVisibilityCondition.Configure(this);

base.ConfigureComponent();
}
base.ConfigureComponent();
}
}
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
using Kentico.Xperience.Admin.Base.FormAnnotations;

namespace Xperience.DependingFieldComponents.FormComponents.DateTimeInputDependsOnFieldComponent
namespace XperienceCommunity.DependingFieldComponents.FormComponents.DateTimeInputDependsOnFieldComponent;

public class DateTimeInputDependsOnFieldAttribute : FormComponentAttribute, IDependsOnPropertyProperties
{
public class DateTimeInputDependsOnFieldAttribute : FormComponentAttribute, IDependsOnPropertyProperties
{
public string? DependsOn { get; set; }
public string? DependsOn { get; set; }


public string? ExpectedValue { get; set; }
}
public string? ExpectedValue { get; set; }
}
Original file line number Diff line number Diff line change
@@ -1,82 +1,33 @@
using CMS.Core;
using CMS.Core.Internal;

using Kentico.Xperience.Admin.Base;
using Kentico.Xperience.Admin.Base.Forms;
using Kentico.Xperience.Admin.Base.Forms.Internal;

using System.Globalization;

using Xperience.DependingFieldComponents;
using Xperience.DependingFieldComponents.FormComponents.DateTimeInputDependsOnFieldComponent;
using Xperience.DependingFieldComponents.VisibilityConditions;

[assembly: RegisterFormComponent(DependingFieldComponentsConstants.DATETIMEINPUT_IDENTIFIER, typeof(DateTimeInputDependsOnFieldComponent), DependingFieldComponentsConstants.DATETIMEINPUT_FIELDDESCRIPTION)]

namespace Xperience.DependingFieldComponents.FormComponents.DateTimeInputDependsOnFieldComponent
using XperienceCommunity.DependingFieldComponents;
using XperienceCommunity.DependingFieldComponents.FormComponents.DateTimeInputDependsOnFieldComponent;
using XperienceCommunity.DependingFieldComponents.VisibilityConditions;

[assembly: RegisterFormComponent(
DependingFieldComponentsConstants.DATETIMEINPUT_IDENTIFIER,
typeof(DateTimeInputDependsOnFieldComponent),
DependingFieldComponentsConstants.DATETIMEINPUT_FIELDDESCRIPTION)]
namespace XperienceCommunity.DependingFieldComponents.FormComponents.DateTimeInputDependsOnFieldComponent;

/// <summary>
/// A form component which can be configured to appear based on the value of another field.
/// </summary>
[ComponentAttribute(typeof(DateTimeInputDependsOnFieldAttribute))]
public class DateTimeInputDependsOnFieldComponent(ILocalizationService localizationService, IDateTimeNowService dateTimeService) :
DateTimeInputComponentBase<DependsOnPropertyProperties, DateTimeInputClientProperties, DateTime?>(localizationService, dateTimeService)
{
/// <summary>
/// A form component which can be configured to appear based on the value of another field.
/// </summary>
[ComponentAttribute(typeof(DateTimeInputDependsOnFieldAttribute))]
public class DateTimeInputDependsOnFieldComponent : DateInputComponentBase<DependsOnPropertyProperties, DateTimeInputClientProperties, DateTime?>
{
private const int YEARS_OFFSET = 2000;
private const string DATE_TIME_FORMAT = "MM/DD/YYYY hh:mm AM/PM";


public override string ClientComponentName => "@kentico/xperience-admin-base/DateTimeInput";


/// <summary>
/// Initializes a new instance of <see cref="DateTimeInputDependsOnFieldComponent"/>.
/// </summary>
public DateTimeInputDependsOnFieldComponent(ILocalizationService localizationService, IDateTimeNowService dateTimeService)
: base(localizationService, dateTimeService)
{
Properties.ExplanationText = string.Format(localizationService.GetString("base.forms.datetimeinput.explanation"), DATE_TIME_FORMAT);

AddValidationRule(new DateFormatValidationRule(localizationService, DATE_TIME_FORMAT));
}
public override string ClientComponentName => "@kentico/xperience-admin-base/DateTimeInput";


protected override void ConfigureComponent()
{
DependingFieldVisibilityCondition.Configure(this);

base.ConfigureComponent();
}


public override void AddValidationRule(IValidationRule validationRule)
{
if (validationRule is DateFormatValidationRule)
{
ValidationRules.Insert(0, validationRule);
}
else
{
base.AddValidationRule(validationRule);
}
}


public override void SetValue(DateTime? value)
{
if (value.HasValue && value.Value == default)
{
value = value.Value.AddYears(YEARS_OFFSET);
}

base.SetValue(value);
}


protected override Task<ICommandResponse<ValidateDateTimeValueCommandResult>> ValidateDateValueInternal(ValidateDateTimeValueCommandArguments arguments)
{
var result = DateTime.TryParseExact(arguments.Value, dateTimeFormatString.Value, CultureInfo.InvariantCulture, DateTimeStyles.AssumeLocal, out _);
protected override void ConfigureComponent()
{
DependingFieldVisibilityCondition.Configure(this);

return Task.FromResult(ResponseFrom(new ValidateDateTimeValueCommandResult { IsValid = result }));
}
base.ConfigureComponent();
}
}
Loading

0 comments on commit 460a15a

Please sign in to comment.