validation1 for the form
This commit is contained in:
@@ -26,6 +26,14 @@ use common::proto::komp_ac::tables_data::{
|
||||
};
|
||||
use crate::search::SearchGrpc;
|
||||
use common::proto::komp_ac::search::SearchResponse;
|
||||
use common::proto::komp_ac::table_validation::{
|
||||
table_validation_service_client::TableValidationServiceClient,
|
||||
GetTableValidationRequest,
|
||||
TableValidationResponse,
|
||||
CountMode as PbCountMode,
|
||||
FieldValidation as PbFieldValidation,
|
||||
CharacterLimits as PbCharacterLimits,
|
||||
};
|
||||
use anyhow::{Context, Result};
|
||||
use std::collections::HashMap;
|
||||
use tonic::transport::{Channel, Endpoint};
|
||||
@@ -40,6 +48,7 @@ pub struct GrpcClient {
|
||||
table_script_client: TableScriptClient<Channel>,
|
||||
tables_data_client: TablesDataClient<Channel>,
|
||||
search_client: SearchGrpc,
|
||||
table_validation_client: TableValidationServiceClient<Channel>,
|
||||
}
|
||||
|
||||
impl GrpcClient {
|
||||
@@ -63,6 +72,8 @@ impl GrpcClient {
|
||||
let table_script_client = TableScriptClient::new(channel.clone());
|
||||
let tables_data_client = TablesDataClient::new(channel.clone());
|
||||
let search_client = SearchGrpc::new(channel.clone());
|
||||
let table_validation_client =
|
||||
TableValidationServiceClient::new(channel.clone());
|
||||
|
||||
Ok(Self {
|
||||
channel,
|
||||
@@ -71,6 +82,7 @@ impl GrpcClient {
|
||||
table_script_client,
|
||||
tables_data_client,
|
||||
search_client,
|
||||
table_validation_client,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -79,6 +91,24 @@ impl GrpcClient {
|
||||
self.channel.clone()
|
||||
}
|
||||
|
||||
// Fetch validation rules for a table. Absence of a field in response = no validation.
|
||||
pub async fn get_table_validation(
|
||||
&mut self,
|
||||
profile_name: String,
|
||||
table_name: String,
|
||||
) -> Result<TableValidationResponse> {
|
||||
let req = GetTableValidationRequest {
|
||||
profile_name,
|
||||
table_name,
|
||||
};
|
||||
let resp = self
|
||||
.table_validation_client
|
||||
.get_table_validation(tonic::Request::new(req))
|
||||
.await
|
||||
.context("gRPC GetTableValidation call failed")?;
|
||||
Ok(resp.into_inner())
|
||||
}
|
||||
|
||||
pub async fn get_table_structure(
|
||||
&mut self,
|
||||
profile_name: String,
|
||||
|
||||
@@ -6,6 +6,8 @@ use crate::pages::admin_panel::add_logic::state::AddLogicState;
|
||||
use crate::pages::forms::logic::SaveOutcome;
|
||||
use crate::utils::columns::filter_user_columns;
|
||||
use crate::pages::forms::{FieldDefinition, FormState};
|
||||
use common::proto::komp_ac::table_validation::CountMode as PbCountMode;
|
||||
use canvas::validation::limits::CountMode;
|
||||
use anyhow::{anyhow, Context, Result};
|
||||
use std::sync::Arc;
|
||||
|
||||
@@ -314,4 +316,60 @@ impl UiService {
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Fetch and apply "Validation 1" (character limits) rules for this form.
|
||||
pub async fn apply_validation1_for_form(
|
||||
grpc_client: &mut GrpcClient,
|
||||
app_state: &mut AppState,
|
||||
path: &str,
|
||||
) -> Result<()> {
|
||||
let (profile, table) = path
|
||||
.split_once('/')
|
||||
.context("Invalid form path for validation")?;
|
||||
|
||||
let resp = grpc_client
|
||||
.get_table_validation(profile.to_string(), table.to_string())
|
||||
.await
|
||||
.context("Failed to fetch table validation")?;
|
||||
|
||||
if let Some(fs) = app_state.form_state_for_path(path) {
|
||||
let mut rules: Vec<Option<crate::pages::forms::state::CharLimitsRule>> =
|
||||
vec![None; fs.fields.len()];
|
||||
|
||||
for f in resp.fields {
|
||||
if let Some(idx) = fs.fields.iter().position(|fd| fd.data_key == f.data_key) {
|
||||
if let Some(limits) = f.limits {
|
||||
let has_any =
|
||||
limits.min != 0 || limits.max != 0 || limits.warn_at.is_some();
|
||||
if has_any {
|
||||
let cm = match PbCountMode::from_i32(limits.count_mode) {
|
||||
Some(PbCountMode::Unspecified) | None => CountMode::Characters, // protobuf default → fallback
|
||||
Some(PbCountMode::Chars) => CountMode::Characters,
|
||||
Some(PbCountMode::Bytes) => CountMode::Bytes,
|
||||
Some(PbCountMode::DisplayWidth) => CountMode::DisplayWidth,
|
||||
};
|
||||
|
||||
let min = if limits.min == 0 { None } else { Some(limits.min as usize) };
|
||||
let max = if limits.max == 0 { None } else { Some(limits.max as usize) };
|
||||
let warn_at = limits.warn_at.map(|w| w as usize);
|
||||
|
||||
rules[idx] = Some(crate::pages::forms::state::CharLimitsRule {
|
||||
min,
|
||||
max,
|
||||
warn_at,
|
||||
count_mode: cm,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
fs.set_character_limits_rules(rules);
|
||||
}
|
||||
|
||||
if let Some(editor) = app_state.editor_for_path(path) {
|
||||
editor.set_validation_enabled(true);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user