From d4930abe4512a5cb703ea476cef0f2e9c0740b84 Mon Sep 17 00:00:00 2001 From: Paul Vaneveld Date: Sat, 22 Jun 2024 11:31:39 +0200 Subject: [PATCH] feat: add support for condition settings --- internal/component_model.go | 159 ++++++++++++++++++++++++--------- internal/component_resource.go | 49 ++++++++++ 2 files changed, 167 insertions(+), 41 deletions(-) diff --git a/internal/component_model.go b/internal/component_model.go index d0cf912..3f994a0 100644 --- a/internal/component_model.go +++ b/internal/component_model.go @@ -32,47 +32,65 @@ type fieldModel struct { Type types.String `tfsdk:"type"` Position types.Int64 `tfsdk:"position"` - AddHttps types.Bool `tfsdk:"add_https"` - AllowTargetBlank types.Bool `tfsdk:"allow_target_blank"` - AssetFolderId types.Int64 `tfsdk:"asset_folder_id"` - CanSync types.Bool `tfsdk:"can_sync"` - ComponentWhitelist []types.String `tfsdk:"component_whitelist"` - CustomizeToolbar types.Bool `tfsdk:"customize_toolbar"` - DatasourceSlug types.String `tfsdk:"datasource_slug"` - DefaultValue types.String `tfsdk:"default_value"` - Description types.String `tfsdk:"description"` - DisableTime types.Bool `tfsdk:"disable_time"` - DisplayName types.String `tfsdk:"display_name"` - ExternalDatasource types.String `tfsdk:"external_datasource"` - FieldType types.String `tfsdk:"field_type"` - Filetypes []types.String `tfsdk:"filetypes"` - FilterContentType []types.String `tfsdk:"filter_content_type"` - FolderSlug types.String `tfsdk:"folder_slug"` - ForceLinkScope types.Bool `tfsdk:"force_link_scope"` - ImageCrop types.Bool `tfsdk:"image_crop"` - ImageHeight types.String `tfsdk:"image_height"` - ImageWidth types.String `tfsdk:"image_width"` - KeepImageSize types.Bool `tfsdk:"keep_image_size"` - Keys []types.String `tfsdk:"keys"` - LinkScope types.String `tfsdk:"link_scope"` - Maximum types.Int64 `tfsdk:"maximum"` - MaxLength types.Int64 `tfsdk:"max_length"` - MaxOptions types.Int64 `tfsdk:"max_options"` - Minimum types.Int64 `tfsdk:"minimum"` - MinOptions types.Int64 `tfsdk:"min_options"` - NoTranslate types.Bool `tfsdk:"no_translate"` - Options []optionModel `tfsdk:"options"` - Regex types.String `tfsdk:"regex"` - Required types.Bool `tfsdk:"required"` - RestrictComponents types.Bool `tfsdk:"restrict_components"` - RestrictContentTypes types.Bool `tfsdk:"restrict_content_types"` - RichMarkdown types.Bool `tfsdk:"rich_markdown"` - Rtl types.Bool `tfsdk:"rtl"` - Source types.String `tfsdk:"source"` - Toolbar []types.String `tfsdk:"toolbar"` - Tooltip types.Bool `tfsdk:"tooltip"` - Translatable types.Bool `tfsdk:"translatable"` - UseUuid types.Bool `tfsdk:"use_uuid"` + AddHttps types.Bool `tfsdk:"add_https"` + AllowTargetBlank types.Bool `tfsdk:"allow_target_blank"` + AssetFolderId types.Int64 `tfsdk:"asset_folder_id"` + CanSync types.Bool `tfsdk:"can_sync"` + ComponentWhitelist []types.String `tfsdk:"component_whitelist"` + ConditionalSettings []conditionalSettingsModel `tfsdk:"conditional_settings"` + CustomizeToolbar types.Bool `tfsdk:"customize_toolbar"` + DatasourceSlug types.String `tfsdk:"datasource_slug"` + DefaultValue types.String `tfsdk:"default_value"` + Description types.String `tfsdk:"description"` + DisableTime types.Bool `tfsdk:"disable_time"` + DisplayName types.String `tfsdk:"display_name"` + ExternalDatasource types.String `tfsdk:"external_datasource"` + FieldType types.String `tfsdk:"field_type"` + Filetypes []types.String `tfsdk:"filetypes"` + FilterContentType []types.String `tfsdk:"filter_content_type"` + FolderSlug types.String `tfsdk:"folder_slug"` + ForceLinkScope types.Bool `tfsdk:"force_link_scope"` + ImageCrop types.Bool `tfsdk:"image_crop"` + ImageHeight types.String `tfsdk:"image_height"` + ImageWidth types.String `tfsdk:"image_width"` + KeepImageSize types.Bool `tfsdk:"keep_image_size"` + Keys []types.String `tfsdk:"keys"` + LinkScope types.String `tfsdk:"link_scope"` + Maximum types.Int64 `tfsdk:"maximum"` + MaxLength types.Int64 `tfsdk:"max_length"` + MaxOptions types.Int64 `tfsdk:"max_options"` + Minimum types.Int64 `tfsdk:"minimum"` + MinOptions types.Int64 `tfsdk:"min_options"` + NoTranslate types.Bool `tfsdk:"no_translate"` + Options []optionModel `tfsdk:"options"` + Regex types.String `tfsdk:"regex"` + Required types.Bool `tfsdk:"required"` + RestrictComponents types.Bool `tfsdk:"restrict_components"` + RestrictContentTypes types.Bool `tfsdk:"restrict_content_types"` + RichMarkdown types.Bool `tfsdk:"rich_markdown"` + Rtl types.Bool `tfsdk:"rtl"` + Source types.String `tfsdk:"source"` + Toolbar []types.String `tfsdk:"toolbar"` + Tooltip types.Bool `tfsdk:"tooltip"` + Translatable types.Bool `tfsdk:"translatable"` + UseUuid types.Bool `tfsdk:"use_uuid"` +} + +type conditionalSettingsModel struct { + Modifications []modificationModel `tfsdk:"modifications"` + RuleMatch types.String `tfsdk:"rule_match"` + RuleConditions []ruleConditionModel `tfsdk:"rule_conditions"` +} + +type ruleConditionModel struct { + Validation types.String `tfsdk:"validation"` + Value types.String `tfsdk:"value"` + FieldKey types.String `tfsdk:"field_key"` +} + +type modificationModel struct { + Display types.String `tfsdk:"display"` + Required types.Bool `tfsdk:"required"` } type optionModel struct { @@ -151,6 +169,7 @@ func toFieldInput(item fieldModel) sbmgmt.FieldInput { AssetFolderId: item.AssetFolderId.ValueInt64Pointer(), CanSync: item.CanSync.ValueBoolPointer(), ComponentWhitelist: utils.ConvertToPointerStringSlice(item.ComponentWhitelist), + ConditionalSettings: deserializeConditionalSettingsModel(item.ConditionalSettings), CustomizeToolbar: item.CustomizeToolbar.ValueBoolPointer(), DatasourceSlug: item.DatasourceSlug.ValueStringPointer(), DefaultValue: item.DefaultValue.ValueStringPointer(), @@ -368,3 +387,61 @@ func deserializeOptionsModel(options []optionModel) *[]sbmgmt.FieldOption { return &optionModels } + +func deserializeConditionalSettingsModel(conditionalSettings []conditionalSettingsModel) *[]sbmgmt.ConditionalSettings { + if conditionalSettings == nil { + return nil + } + + deserializedConditionalSettings := make([]sbmgmt.ConditionalSettings, len(conditionalSettings)) + + for i, setting := range conditionalSettings { + + deserializedConditionalSettings[i] = sbmgmt.ConditionalSettings{ + RuleMatch: (*sbmgmt.ConditionalSettingsRuleMatch)(setting.RuleMatch.ValueStringPointer()), + Modifications: deserializeConditionalSettingsModificationsModel(setting.Modifications), + RuleConditions: deserializeRuleConditions(setting.RuleConditions), + } + } + + return &deserializedConditionalSettings +} + +func deserializeConditionalSettingsModificationsModel(conditionalSettingsModifications []modificationModel) *[]sbmgmt.Modification { + deserializedModifications := make([]sbmgmt.Modification, len(conditionalSettingsModifications)) + + for i, modification := range conditionalSettingsModifications { + if !modification.Display.IsNull() { + deserializedModifications[i] = sbmgmt.Modification{ + Display: (*sbmgmt.ModificationDisplay)(modification.Display.ValueStringPointer()), + } + } else { + deserializedModifications[i] = sbmgmt.Modification{ + Required: modification.Required.ValueBoolPointer(), + } + } + } + + return &deserializedModifications +} + +func deserializeRuleConditions(ruleConditions []ruleConditionModel) *[]sbmgmt.RuleCondition { + deserializedRuleConditions := make([]sbmgmt.RuleCondition, len(ruleConditions)) + + validatedObjectFieldAttrValue := sbmgmt.ValidatedObjectFieldAttr("value") + validatedValidatedObjectType := sbmgmt.ValidatedObjectType("field") + + for i, ruleCondition := range ruleConditions { + deserializedRuleConditions[i] = sbmgmt.RuleCondition{ + Validation: (*sbmgmt.RuleConditionValidation)(ruleCondition.Validation.ValueStringPointer()), + Value: ruleCondition.Validation.ValueStringPointer(), + ValidatedObject: &sbmgmt.ValidatedObject{ + FieldKey: ruleCondition.FieldKey.ValueStringPointer(), + FieldAttr: &validatedObjectFieldAttrValue, + Type: &validatedValidatedObjectType, + }, + } + } + + return &deserializedRuleConditions +} diff --git a/internal/component_resource.go b/internal/component_resource.go index dff01c9..2b4403f 100644 --- a/internal/component_resource.go +++ b/internal/component_resource.go @@ -168,6 +168,55 @@ func (r *componentResource) Schema(_ context.Context, _ resource.SchemaRequest, Optional: true, ElementType: types.StringType, }, + "conditional_settings": schema.ListNestedAttribute{ + Description: "Array containing the object with information about conditions set on the field", + Optional: true, + NestedObject: schema.NestedAttributeObject{ + Attributes: map[string]schema.Attribute{ + "modifications": schema.ListNestedAttribute{ + Optional: false, + Description: "List of modifications to be applied to the field. Only 1 modification can be applied at a time (display OR required)", + NestedObject: schema.NestedAttributeObject{ + Attributes: map[string]schema.Attribute{ + "display": schema.StringAttribute{ + Optional: true, + Description: "Hide the target field if the rule conditions are met", + Validators: []validator.String{stringvalidator.OneOf("hide")}, + }, + "required": schema.BoolAttribute{ + Optional: true, + Description: "Make the target field required / optional if the rule conditions are met", + }, + }, + }, + }, + "rule_match": schema.StringAttribute{ + Description: "Define if all or any of the conditions should be met to apply the modifications", + Optional: false, + Validators: []validator.String{stringvalidator.OneOf("any", "all")}, + }, + "rule_conditions": schema.ListNestedAttribute{ + Description: "Conditional rules to be applied to the target field", + Optional: false, + NestedObject: schema.NestedAttributeObject{ + Attributes: map[string]schema.Attribute{ + "validation": schema.StringAttribute{ + Optional: false, + Validators: []validator.String{stringvalidator.OneOf("empty", "not_empty", "equals", "not_equals")}, + }, + "value": schema.StringAttribute{ + Optional: true, + Default: nil, + }, + "field_key": schema.StringAttribute{ + Optional: false, + }, + }, + }, + }, + }, + }, + }, "datasource_slug": schema.StringAttribute{ Description: "Define selectable datasources string; Effects editor only if source=internal", Optional: true,