diff --git a/proto/feedback-fusion-v1.proto b/proto/feedback-fusion-v1.proto index 32dd0774..d7516832 100644 --- a/proto/feedback-fusion-v1.proto +++ b/proto/feedback-fusion-v1.proto @@ -169,12 +169,7 @@ message NumberOptions { string placeholder = 3; } -message CreateFieldRequest { - string prompt = 1; - string title = 2; - optional string description = 3; - FieldType field_type = 4; - +message FieldOptions { oneof options { TextOptions text = 5; RatingOptions rating = 6; @@ -185,21 +180,21 @@ message CreateFieldRequest { } } +message CreateFieldRequest { + string prompt = 1; + string title = 2; + optional string description = 3; + FieldType field_type = 4; + FieldOptions options = 5; +} + message Field { string id = 1; string prompt = 2; string title = 3; optional string description = 4; FieldType field_type = 13; - - oneof options { - TextOptions text = 5; - RatingOptions rating = 6; - CheckboxOptions checkbox = 7; - SelectionOptions selection = 8; - RangeOptions range = 9; - NumberOptions number = 10; - } + FieldOptions options = 5; google.protobuf.Timestamp created_at = 11; google.protobuf.Timestamp updated_at = 12; @@ -221,18 +216,10 @@ message FieldPage { } message UpdateFieldRequest { - oneof options { - TextOptions text = 1; - RatingOptions rating = 2; - CheckboxOptions checkbox = 3; - SelectionOptions selection = 4; - RangeOptions range = 5; - NumberOptions number = 6; - } - - optional string title = 8; - optional string description = 9; - string id = 10; + FieldOptions options = 1; + optional string title = 2; + optional string description = 3; + string id = 4; } message DeleteFieldRequest { string id = 1; } @@ -282,15 +269,7 @@ message FieldResponse { string id = 1; string response = 2; string field = 3; - - oneof data { - TextResponse text = 4; - RatingResponse rating = 5; - CheckboxResponse checkbox = 6; - SelectionResponse selection = 7; - RangeResponse range = 8; - NumberResponse number = 9; - } + ResponseData data = 4; } message FieldResponseList { diff --git a/src/database/schema/feedback/field.rs b/src/database/schema/feedback/field.rs index 54565445..a58511c7 100644 --- a/src/database/schema/feedback/field.rs +++ b/src/database/schema/feedback/field.rs @@ -20,7 +20,7 @@ //DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, //OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -use crate::{database::schema::date_time_to_timestamp, prelude::*, to_date_time, save_as_json}; +use crate::{database::schema::date_time_to_timestamp, prelude::*, save_as_json, to_date_time}; use rbatis::rbdc::DateTime; #[derive(Serialize, Deserialize, Clone, Debug, PartialEq)] @@ -35,46 +35,77 @@ pub enum FieldOptions { Number(NumberOptions), } -macro_rules! map_options { - ($($path:path $(,)?)*) => { - $( - impl From for $path { - fn from(value: FieldOptions) -> Self { - match value { - FieldOptions::Text(options) => Self::Text(options.into()), - FieldOptions::Rating(options) => Self::Rating(options.into()), - FieldOptions::Checkbox(options) => Self::Checkbox(options.into()), - FieldOptions::Selection(options) => Self::Selection(options.into()), - FieldOptions::Range(options) => Self::Range(options.into()), - FieldOptions::Number(options) => Self::Number(options.into()), - } - } +impl From for feedback_fusion_common::proto::FieldOptions { + fn from(value: FieldOptions) -> Self { + match value { + FieldOptions::Text(options) => Self { + options: Some(feedback_fusion_common::proto::field_options::Options::Text( + options.into(), + )), + }, + FieldOptions::Rating(options) => Self { + options: Some( + feedback_fusion_common::proto::field_options::Options::Rating(options.into()), + ), + }, + FieldOptions::Checkbox(options) => Self { + options: Some( + feedback_fusion_common::proto::field_options::Options::Checkbox(options.into()), + ), + }, + FieldOptions::Selection(options) => Self { + options: Some( + feedback_fusion_common::proto::field_options::Options::Selection( + options.into(), + ), + ), + }, + FieldOptions::Range(options) => Self { + options: Some( + feedback_fusion_common::proto::field_options::Options::Range(options.into()), + ), + }, + FieldOptions::Number(options) => Self { + options: Some( + feedback_fusion_common::proto::field_options::Options::Number(options.into()), + ), + }, } + } +} - impl TryInto for $path { - type Error = FeedbackFusionError; - - fn try_into(self) -> Result { - Ok(match self { - Self::Text(options) => FieldOptions::Text(options.try_into()?), - Self::Rating(options) => FieldOptions::Rating(options.try_into()?), - Self::Checkbox(options) => FieldOptions::Checkbox(options.try_into()?), - Self::Selection(options) => FieldOptions::Selection(options.into()), - Self::Range(options) => FieldOptions::Range(options.try_into()?), - Self::Number(options) => FieldOptions::Number(options.try_into()?), - }) - } +impl TryInto for feedback_fusion_common::proto::FieldOptions { + type Error = FeedbackFusionError; + fn try_into(self) -> Result { + if let Some(options) = self.options { + Ok(match options { + feedback_fusion_common::proto::field_options::Options::Text(options) => { + FieldOptions::Text(options.try_into()?) + } + feedback_fusion_common::proto::field_options::Options::Rating(options) => { + FieldOptions::Rating(options.try_into()?) + } + feedback_fusion_common::proto::field_options::Options::Checkbox(options) => { + FieldOptions::Checkbox(options.try_into()?) + } + feedback_fusion_common::proto::field_options::Options::Selection(options) => { + FieldOptions::Selection(options.into()) + } + feedback_fusion_common::proto::field_options::Options::Range(options) => { + FieldOptions::Range(options.try_into()?) + } + feedback_fusion_common::proto::field_options::Options::Number(options) => { + FieldOptions::Number(options.try_into()?) + } + }) + } else { + Err(FeedbackFusionError::BadRequest( + "Missing FieldOptions value".to_owned(), + )) } - )* - }; + } } -map_options!( - feedback_fusion_common::proto::create_field_request::Options, - feedback_fusion_common::proto::update_field_request::Options, - feedback_fusion_common::proto::field::Options, -); - #[derive(Deserialize, Serialize, Clone, Debug, PartialEq, TypedBuilder, Validate)] #[builder(field_defaults(setter(into)))] pub struct TextOptions { @@ -402,45 +433,74 @@ pub enum FieldData { Number(NumberResponse), } -macro_rules! map_response { - ($($path:path $(,)?)*) => { - $( - impl From for $path { - fn from(value: FieldData) -> $path { - match value { - FieldData::Text(data) => Self::Text(data.into()), - FieldData::Rating(data) => Self::Rating(data.into()), - FieldData::Checkbox(data) => Self::Checkbox(data.into()), - FieldData::Selection(data) => Self::Selection(data.into()), - FieldData::Range(data) => Self::Range(data.into()), - FieldData::Number(data) => Self::Number(data.into()), - } - } +impl From for feedback_fusion_common::proto::ResponseData { + fn from(value: FieldData) -> feedback_fusion_common::proto::ResponseData { + match value { + FieldData::Text(data) => Self { + data: Some(feedback_fusion_common::proto::response_data::Data::Text( + data.into(), + )), + }, + FieldData::Rating(data) => Self { + data: Some(feedback_fusion_common::proto::response_data::Data::Rating( + data.into(), + )), + }, + FieldData::Checkbox(data) => Self { + data: Some( + feedback_fusion_common::proto::response_data::Data::Checkbox(data.into()), + ), + }, + FieldData::Selection(data) => Self { + data: Some( + feedback_fusion_common::proto::response_data::Data::Selection(data.into()), + ), + }, + FieldData::Range(data) => Self { + data: Some(feedback_fusion_common::proto::response_data::Data::Range( + data.into(), + )), + }, + FieldData::Number(data) => Self { + data: Some(feedback_fusion_common::proto::response_data::Data::Number( + data.into(), + )), + }, } - - impl TryInto for $path { - type Error = FeedbackFusionError; - - fn try_into(self) -> Result { - Ok(match self { - Self::Text(data) => FieldData::Text(data.into()), - Self::Rating(data) => FieldData::Rating(data.try_into()?), - Self::Checkbox(data) => FieldData::Checkbox(data.into()), - Self::Selection(data) => FieldData::Selection(data.into()), - Self::Range(data) => FieldData::Range(data.try_into()?), - Self::Number(data) => FieldData::Number(data.try_into()?), - }) - } + } +} +impl TryInto for feedback_fusion_common::proto::ResponseData { + type Error = FeedbackFusionError; + fn try_into(self) -> Result { + if let Some(data) = self.data { + Ok(match data { + feedback_fusion_common::proto::response_data::Data::Text(data) => { + FieldData::Text(data.into()) + } + feedback_fusion_common::proto::response_data::Data::Rating(data) => { + FieldData::Rating(data.try_into()?) + } + feedback_fusion_common::proto::response_data::Data::Checkbox(data) => { + FieldData::Checkbox(data.into()) + } + feedback_fusion_common::proto::response_data::Data::Selection(data) => { + FieldData::Selection(data.into()) + } + feedback_fusion_common::proto::response_data::Data::Range(data) => { + FieldData::Range(data.try_into()?) + } + feedback_fusion_common::proto::response_data::Data::Number(data) => { + FieldData::Number(data.try_into()?) + } + }) + } else { + Err(FeedbackFusionError::BadRequest( + "Missing ResponseData value".to_owned(), + )) } - )* - }; + } } -map_response!( - feedback_fusion_common::proto::field_response::Data, - feedback_fusion_common::proto::response_data::Data -); - macro_rules! validate_data { ($self: expr, $voptions: expr, $rident:ident, $ident:ident, $($type:path = $options:path => $if:block $(,)?)*) => { $( diff --git a/src/services/v1/response.rs b/src/services/v1/response.rs index 24ff3bc4..78cc116f 100644 --- a/src/services/v1/response.rs +++ b/src/services/v1/response.rs @@ -68,7 +68,7 @@ pub async fn create_responses( if let Some(field) = field { // validate the data - let field_data: FieldData = value.data.unwrap().try_into()?; + let field_data: FieldData = value.try_into()?; field_data.validate(field.options())?; Ok(FieldResponse::builder() diff --git a/tests/field.rs b/tests/field.rs index 586158c5..1b33652a 100644 --- a/tests/field.rs +++ b/tests/field.rs @@ -22,8 +22,8 @@ use common::*; use feedback_fusion_common::proto::{ - create_field_request::Options, CreateFieldRequest, CreatePromptRequest, CreateTargetRequest, - DeleteFieldRequest, FieldType, GetFieldsRequest, TextOptions, UpdateFieldRequest, + CreateFieldRequest, CreatePromptRequest, CreateTargetRequest, DeleteFieldRequest, FieldOptions, + FieldType, GetFieldsRequest, TextOptions, UpdateFieldRequest, }; use test_log::test; @@ -51,10 +51,14 @@ fn create_field(prompt: String) -> CreateFieldRequest { title: "Field".to_owned(), description: Some("Description".to_owned()), field_type: FieldType::Text.into(), - options: Some(Options::Text(TextOptions { - lines: 1, - placeholder: "Placeholder".to_owned(), - })), + options: Some(FieldOptions { + options: Some(feedback_fusion_common::proto::field_options::Options::Text( + TextOptions { + lines: 1, + placeholder: "Placeholder".to_owned(), + }, + )), + }), } } diff --git a/tests/response.rs b/tests/response.rs index b2fb7097..3eccf445 100644 --- a/tests/response.rs +++ b/tests/response.rs @@ -24,8 +24,8 @@ use std::collections::HashMap; use common::*; use feedback_fusion_common::proto::{ - create_field_request::Options, response_data::Data, CreateFieldRequest, CreatePromptRequest, - CreateResponsesRequest, CreateTargetRequest, FieldType, GetResponsesRequest, RatingResponse, + response_data::Data, CreateFieldRequest, CreatePromptRequest, CreateResponsesRequest, + CreateTargetRequest, FieldOptions, FieldType, GetResponsesRequest, RatingResponse, ResponseData, TextOptions, TextResponse, }; use test_log::test; @@ -54,10 +54,14 @@ fn create_field(prompt: String) -> CreateFieldRequest { title: "Field".to_owned(), description: Some("Description".to_owned()), field_type: FieldType::Text.into(), - options: Some(Options::Text(TextOptions { - lines: 1, - placeholder: "Placeholder".to_owned(), - })), + options: Some(FieldOptions { + options: Some(feedback_fusion_common::proto::field_options::Options::Text( + TextOptions { + lines: 1, + placeholder: "Placeholder".to_owned(), + }, + )), + }), } } @@ -155,9 +159,11 @@ async fn test_get() { .first() .unwrap() .data - .eq(&Some( - feedback_fusion_common::proto::field_response::Data::Text(TextResponse { - text: "text".to_owned(), - }) - )))) + .eq(&Some(ResponseData { + data: Some(feedback_fusion_common::proto::response_data::Data::Text( + TextResponse { + text: "text".to_owned(), + } + )) + })))) }