diff --git a/common/build.rs b/common/build.rs index 20be794..2440bb0 100644 --- a/common/build.rs +++ b/common/build.rs @@ -12,6 +12,10 @@ fn main() -> Result<(), Box> { ".komp_ac.table_validation.CharacterLimits", "#[derive(serde::Serialize, serde::Deserialize)]", ) + .type_attribute( + ".komp_ac.table_validation.DisplayMask", + "#[derive(serde::Serialize, serde::Deserialize)]", + ) .type_attribute( ".komp_ac.table_validation.TableValidationResponse", "#[derive(serde::Serialize, serde::Deserialize)]", diff --git a/common/proto/table_validation.proto b/common/proto/table_validation.proto index 1952307..f7ef833 100644 --- a/common/proto/table_validation.proto +++ b/common/proto/table_validation.proto @@ -23,9 +23,10 @@ message FieldValidation { CharacterLimits limits = 10; // Future expansion: // PatternRules pattern = 11; - // DisplayMask mask = 12; + DisplayMask mask = 3; // ExternalValidation external = 13; // CustomFormatter formatter = 14; + bool required = 4; } // Character length counting mode @@ -49,6 +50,13 @@ message CharacterLimits { CountMode countMode = 4; // defaults to CHARS if unspecified } +// Mask for pretty display +message DisplayMask { + string pattern = 1; // e.g., "(###) ###-####" or "####-##-##" + string input_char = 2; // e.g., "#" + optional string template_char = 3; // e.g., "_" +} + // Service to fetch validations for a table service TableValidationService { rpc GetTableValidation(GetTableValidationRequest) diff --git a/common/src/proto/descriptor.bin b/common/src/proto/descriptor.bin index d552ef0..61967eb 100644 Binary files a/common/src/proto/descriptor.bin and b/common/src/proto/descriptor.bin differ diff --git a/common/src/proto/komp_ac.table_validation.rs b/common/src/proto/komp_ac.table_validation.rs index 2fc6e6f..dbd6ba4 100644 --- a/common/src/proto/komp_ac.table_validation.rs +++ b/common/src/proto/komp_ac.table_validation.rs @@ -23,14 +23,16 @@ pub struct FieldValidation { #[prost(string, tag = "1")] pub data_key: ::prost::alloc::string::String, /// Current: only CharacterLimits. More rules can be added later. - /// - /// Future expansion: - /// PatternRules pattern = 11; - /// DisplayMask mask = 12; - /// ExternalValidation external = 13; - /// CustomFormatter formatter = 14; #[prost(message, optional, tag = "10")] pub limits: ::core::option::Option, + /// Future expansion: + /// PatternRules pattern = 11; + #[prost(message, optional, tag = "3")] + pub mask: ::core::option::Option, + /// ExternalValidation external = 13; + /// CustomFormatter formatter = 14; + #[prost(bool, tag = "4")] + pub required: bool, } /// Character limit validation (Validation 1) #[derive(serde::Serialize, serde::Deserialize)] @@ -49,6 +51,20 @@ pub struct CharacterLimits { #[prost(enumeration = "CountMode", tag = "4")] pub count_mode: i32, } +/// Mask for pretty display +#[derive(serde::Serialize, serde::Deserialize)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct DisplayMask { + /// e.g., "(###) ###-####" or "####-##-##" + #[prost(string, tag = "1")] + pub pattern: ::prost::alloc::string::String, + /// e.g., "#" + #[prost(string, tag = "2")] + pub input_char: ::prost::alloc::string::String, + /// e.g., "_" + #[prost(string, optional, tag = "3")] + pub template_char: ::core::option::Option<::prost::alloc::string::String>, +} #[derive(serde::Serialize, serde::Deserialize)] #[derive(Clone, PartialEq, ::prost::Message)] pub struct UpdateFieldValidationRequest { diff --git a/server/src/table_validation/get/service.rs b/server/src/table_validation/get/service.rs index a04807f..43e82c7 100644 --- a/server/src/table_validation/get/service.rs +++ b/server/src/table_validation/get/service.rs @@ -40,12 +40,16 @@ impl TableValidationService for TableValidationSvc { // Set the data_key from the database row fv.data_key = r.data_key; - // Skip if limits are all zero - if let Some(lims) = &fv.limits { - if lims.min == 0 && lims.max == 0 && lims.warn_at.is_none() { - continue; - } - } + // Keep entries that have either meaningful limits or a mask + let has_meaningful_limits = fv + .limits + .as_ref() + .map_or(false, |l| l.min > 0 || l.max > 0 || l.warn_at.is_some()); + let has_mask = fv.mask.is_some(); + if !has_meaningful_limits && !has_mask { + continue; + } + fields_out.push(fv); } Err(e) => {