From 622811df5ababd8181015bb944484eb86a1abffd Mon Sep 17 00:00:00 2001 From: Paul-Christian Volkmer Date: Thu, 7 Nov 2024 19:06:06 +0100 Subject: [PATCH] refactor: merge DataForm and Unterformular (#36) * refactor: merge DataForm and Unterformular * refactor: change visibility --- src/model/{data_form.rs => form.rs} | 330 ++++++++++++- src/model/mod.rs | 3 +- src/model/onkostar_editor.rs | 15 +- src/model/other.rs | 10 +- src/model/requirements.rs | 11 +- src/model/unterformular.rs | 699 ---------------------------- 6 files changed, 335 insertions(+), 733 deletions(-) rename src/model/{data_form.rs => form.rs} (72%) delete mode 100644 src/model/unterformular.rs diff --git a/src/model/data_form.rs b/src/model/form.rs similarity index 72% rename from src/model/data_form.rs rename to src/model/form.rs index b7847fc..9aa4f83 100644 --- a/src/model/data_form.rs +++ b/src/model/form.rs @@ -17,12 +17,13 @@ * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ - -use std::cmp::Ordering; -use std::collections::HashSet; - use console::style; use serde::{Deserialize, Serialize}; +use std::any::TypeId; +use std::cmp::Ordering; +use std::collections::HashSet; +use std::fmt::Debug; +use std::marker::PhantomData; use crate::checks::CheckNotice::ErrorWithCode; use crate::checks::{CheckNotice, Checkable}; @@ -37,9 +38,18 @@ use crate::model::{ use crate::model::{Haeufigkeiten, Ordner}; use crate::profile::Profile; +#[derive(Debug)] +pub struct DataFormType; + +#[derive(Debug)] +pub struct UnterformularType; + #[derive(Serialize, Deserialize, Debug)] #[serde(deny_unknown_fields)] -pub struct DataForm { +pub struct Form { + #[serde(skip)] + form_type: PhantomData, + #[serde(rename = "DataCatalogues")] data_catalogues: DataCatalogues, #[serde(rename = "Category")] @@ -191,7 +201,7 @@ pub struct DataForm { ansichten: Option, } -impl FormEntryContainer for DataForm { +impl FormEntryContainer for Form { fn apply_profile(&mut self, profile: &Profile) { profile.forms.iter().for_each(|profile_form| { if self.name == profile_form.name { @@ -222,10 +232,15 @@ impl FormEntryContainer for DataForm { } } -impl Listable for DataForm { +impl Listable for Form { fn to_listed_string(&self) -> String { format!( - "Formular ({}) '{}' in Revision '{}'", + "{} ({}) '{}' in Revision '{}'", + if TypeId::of::() == TypeId::of::() { + "Formular" + } else { + "Unterformular" + }, match self.is_system_library_content() { true => style("S").yellow(), _ => style("u"), @@ -236,7 +251,7 @@ impl Listable for DataForm { } } -impl Sortable for DataForm { +impl Sortable for Form { fn sorting_key(&self) -> String { self.name.clone() } @@ -265,7 +280,10 @@ impl Sortable for DataForm { } } -impl Comparable for DataForm { +impl Comparable for Form +where + Type: Debug + 'static, +{ fn get_name(&self) -> String { self.name.clone() } @@ -290,7 +308,10 @@ impl Comparable for DataForm { } } -impl Requires for DataForm { +impl Requires for Form +where + Self: Listable + 'static, +{ fn requires_form_reference(&self, name: &str) -> bool { self.entries .entry @@ -385,13 +406,13 @@ impl Requires for DataForm { } } -impl FolderContent for DataForm { +impl FolderContent for Form { fn get_library_folder(&self) -> String { self.ordner.bibliothek.name.to_string() } } -impl Checkable for DataForm { +impl Checkable for Form { fn check(&self) -> Vec { if self .entries @@ -415,6 +436,24 @@ impl Checkable for DataForm { } } +impl Checkable for Form { + fn check(&self) -> Vec { + if self.hat_unterformulare { + return vec![ErrorWithCode { + code: "2023-0001".to_string(), + description: format!( + "Unterformular '{}' mit Markierung 'hat Unterformulare'", + self.name + ), + line: None, + example: None, + }]; + } + + vec![] + } +} + #[derive(Serialize, Deserialize, Debug)] #[serde(deny_unknown_fields)] pub struct DataCatalogues { @@ -770,4 +809,269 @@ mod tests { None ); } + + #[test] + fn should_change_unterformular_entry_default_value() { + let onkostar_editor = OnkostarEditor::from_str(include_str!("../../tests/test.osc")); + + assert!(onkostar_editor.is_ok()); + let mut onkostar_editor = onkostar_editor.unwrap(); + + let profile = "forms: + - name: 'Unterformular' + form_fields: + - name: Termin + default_value: '2024-03-18' + "; + + let profile = Profile::from_str(profile); + assert!(profile.is_ok()); + let profile = profile.unwrap(); + + assert_eq!( + onkostar_editor.editor.unterformular[0].entries.entry[1].name, + "Termin" + ); + assert_eq!( + onkostar_editor.editor.unterformular[0].entries.entry[1].default_value, + "" + ); + + onkostar_editor.apply_profile(&profile); + + assert_eq!( + onkostar_editor.editor.unterformular[0].entries.entry[1].name, + "Termin" + ); + assert_eq!( + onkostar_editor.editor.unterformular[0].entries.entry[1].default_value, + "2024-03-18" + ) + } + + #[test] + fn should_not_change_unterformular_entry_default_value() { + let onkostar_editor = OnkostarEditor::from_str(include_str!("../../tests/test.osc")); + + assert!(onkostar_editor.is_ok()); + let mut onkostar_editor = onkostar_editor.unwrap(); + + let profile = "forms: + - name: 'Unterformular' + "; + + let profile = Profile::from_str(profile); + assert!(profile.is_ok()); + let profile = profile.unwrap(); + + assert_eq!( + onkostar_editor.editor.unterformular[0].entries.entry[1].name, + "Termin" + ); + assert_eq!( + onkostar_editor.editor.unterformular[0].entries.entry[1].default_value, + "" + ); + + onkostar_editor.apply_profile(&profile); + + assert_eq!( + onkostar_editor.editor.unterformular[0].entries.entry[1].name, + "Termin" + ); + assert_eq!( + onkostar_editor.editor.unterformular[0].entries.entry[1].default_value, + "" + ) + } + + #[test] + fn should_ignore_menu_category_for_subform() { + let onkostar_editor = OnkostarEditor::from_str(include_str!("../../tests/test.osc")); + + assert!(onkostar_editor.is_ok()); + let mut onkostar_editor = onkostar_editor.unwrap(); + + let profile = "forms: + - name: 'Unterformular' + "; + + let profile = Profile::from_str(profile); + assert!(profile.is_ok()); + let profile = profile.unwrap(); + + onkostar_editor.apply_profile(&profile); + + assert!(&onkostar_editor.editor.unterformular[0] + .menu_category + .is_none()); + } + + #[test] + fn should_change_unterformular_entry_scripts_code_with_form_fields() { + let onkostar_editor = OnkostarEditor::from_str(include_str!("../../tests/test.osc")); + + assert!(onkostar_editor.is_ok()); + let mut onkostar_editor = onkostar_editor.unwrap(); + + let profile = "forms: + - name: 'Unterformular' + form_fields: + - name: Termin + scripts_code: |- + // Example code + console.log(42); + "; + + let profile = Profile::from_str(profile); + assert!(profile.is_ok()); + let profile = profile.unwrap(); + + assert_eq!( + onkostar_editor.editor.unterformular[0].entries.entry[1].scripts, + None + ); + + onkostar_editor.apply_profile(&profile); + + assert_eq!( + onkostar_editor.editor.unterformular[0].entries.entry[1].scripts, + Some(Script { + code: "// Example code console.log(42);".into(), + valid: true + }) + ); + } + + #[test] + fn should_change_unterformular_entry_scripts_code_with_form_references() { + let onkostar_editor = OnkostarEditor::from_str(include_str!("../../tests/test.osc")); + + assert!(onkostar_editor.is_ok()); + let mut onkostar_editor = onkostar_editor.unwrap(); + + let profile = "forms: + - name: 'Unterformular' + form_fields: + - name: Termin + scripts_code: |- + // Example code + console.log(42); + "; + + let profile = Profile::from_str(profile); + assert!(profile.is_ok()); + let profile = profile.unwrap(); + + assert_eq!( + onkostar_editor.editor.unterformular[0].entries.entry[1].scripts, + None + ); + + onkostar_editor.apply_profile(&profile); + + assert_eq!( + onkostar_editor.editor.unterformular[0].entries.entry[1].scripts, + Some(Script { + code: "// Example code console.log(42);".into(), + valid: true + }) + ); + } + + #[test] + fn should_remove_unterformular_entry_filter_with_form_fields() { + let onkostar_editor = OnkostarEditor::from_str(include_str!("../../tests/test.osc")); + + assert!(onkostar_editor.is_ok()); + let mut onkostar_editor = onkostar_editor.unwrap(); + + let profile = "forms: + - name: 'Unterformular' + form_fields: + - name: Termin + remove_filter: true + scripts_code: |- + // Example code + console.log(42); + "; + + let profile = Profile::from_str(profile); + assert!(profile.is_ok()); + let profile = profile.unwrap(); + + assert_eq!( + onkostar_editor.editor.unterformular[0].entries.entry[0].filter, + None + ); + + assert_eq!( + onkostar_editor.editor.unterformular[0].entries.entry[1].filter, + Some(Filter { + condition: "getGlobalSetting('mehrere_mtb_in_mtbepisode') = 'true'".into(), + valid: true, + ref_entries: Some(RefEntries { ref_entry: None }) + }) + ); + + onkostar_editor.apply_profile(&profile); + + assert_eq!( + onkostar_editor.editor.unterformular[0].entries.entry[0].filter, + None + ); + + assert_eq!( + onkostar_editor.editor.unterformular[0].entries.entry[1].filter, + None + ); + } + + #[test] + fn should_remove_unterformular_entry_filter_with_form_references() { + let onkostar_editor = OnkostarEditor::from_str(include_str!("../../tests/test.osc")); + + assert!(onkostar_editor.is_ok()); + let mut onkostar_editor = onkostar_editor.unwrap(); + + let profile = "forms: + - name: 'Unterformular' + form_fields: + - name: Termin + remove_filter: true + scripts_code: |- + // Example code + console.log(42); + "; + + let profile = Profile::from_str(profile); + assert!(profile.is_ok()); + let profile = profile.unwrap(); + + assert_eq!( + onkostar_editor.editor.unterformular[0].entries.entry[0].filter, + None + ); + + assert_eq!( + onkostar_editor.editor.unterformular[0].entries.entry[1].filter, + Some(Filter { + condition: "getGlobalSetting('mehrere_mtb_in_mtbepisode') = 'true'".into(), + valid: true, + ref_entries: Some(RefEntries { ref_entry: None }) + }) + ); + + onkostar_editor.apply_profile(&profile); + + assert_eq!( + onkostar_editor.editor.unterformular[0].entries.entry[0].filter, + None + ); + + assert_eq!( + onkostar_editor.editor.unterformular[0].entries.entry[1].filter, + None + ); + } } diff --git a/src/model/mod.rs b/src/model/mod.rs index f640174..0239b07 100644 --- a/src/model/mod.rs +++ b/src/model/mod.rs @@ -29,12 +29,11 @@ use crate::model::requirements::Requires; use crate::profile::{FormField, FormReference, Profile, WithScriptsCode}; pub mod data_catalogue; -pub mod data_form; +pub mod form; pub mod onkostar_editor; pub mod other; pub mod property_catalogue; pub mod requirements; -pub mod unterformular; #[derive(Serialize, Deserialize, Debug, PartialEq)] #[serde(deny_unknown_fields)] diff --git a/src/model/onkostar_editor.rs b/src/model/onkostar_editor.rs index 1cbe2de..bac5c27 100644 --- a/src/model/onkostar_editor.rs +++ b/src/model/onkostar_editor.rs @@ -28,11 +28,10 @@ use serde::{Deserialize, Serialize}; use crate::checks::{CheckNotice, Checkable}; use crate::model::data_catalogue::DataCatalogue; -use crate::model::data_form::DataForm; +use crate::model::form::{DataFormType, Form, UnterformularType}; use crate::model::other::{Ablaufschema, Akte, RecordLinkage, Rskript, SidGuid}; use crate::model::property_catalogue::PropertyCatalogue; use crate::model::requirements::{Requirement, Requires}; -use crate::model::unterformular::Unterformular; use crate::model::{Comparable, FolderContent, FormEntryContainer, Listable, Sortable}; use crate::profile::Profile; @@ -72,7 +71,7 @@ impl OnkostarEditor { } } - pub fn find_data_form(&self, name: &str) -> Option<&DataForm> { + pub fn find_data_form(&self, name: &str) -> Option<&Form> { match self .editor .data_form @@ -85,7 +84,7 @@ impl OnkostarEditor { } } - pub fn find_unterformular(&self, name: &str) -> Option<&Unterformular> { + pub fn find_unterformular(&self, name: &str) -> Option<&Form> { match self .editor .unterformular @@ -233,7 +232,7 @@ impl OnkostarEditor { self.editor .data_form - .sort_unstable_by(DataForm::compare_by_requirement); + .sort_unstable_by(Form::compare_by_requirement); self.editor.data_form.iter_mut().for_each(|item| { item.sorted(); @@ -245,7 +244,7 @@ impl OnkostarEditor { self.editor .unterformular - .sort_unstable_by(Unterformular::compare_by_requirement); + .sort_unstable_by(Form::compare_by_requirement); self.editor.unterformular.iter_mut().for_each(|item| { item.sorted(); @@ -519,9 +518,9 @@ pub struct Editor { #[serde(rename = "DataCatalogue", default)] data_catalogue: Vec, #[serde(rename = "Unterformular", default)] - pub unterformular: Vec, + pub unterformular: Vec>, #[serde(rename = "DataForm", default)] - pub data_form: Vec, + pub data_form: Vec>, #[serde(rename = "Ablaufschema", default)] #[serde(skip_serializing_if = "Option::is_none")] diff --git a/src/model/other.rs b/src/model/other.rs index 7456ed8..9ba2fd5 100644 --- a/src/model/other.rs +++ b/src/model/other.rs @@ -270,9 +270,9 @@ pub struct Entry { #[serde(skip_serializing_if = "Option::is_none")] parent_ref_id: Option, #[serde(rename = "Type")] - pub type_: String, + pub(crate) type_: String, #[serde(rename = "Name")] - pub name: String, + pub(crate) name: String, #[serde(rename = "Description")] description: String, #[serde(rename = "Active")] @@ -297,7 +297,7 @@ pub struct Entry { #[serde(rename = "MultipleChoice")] multiple_choice: bool, #[serde(rename = "DefaultValue")] - pub default_value: String, + pub(crate) default_value: String, #[serde(rename = "Alignment")] alignment: String, #[serde(rename = "Direction")] @@ -310,7 +310,7 @@ pub struct Entry { #[serde(rename = "ElementParent")] element_parent: String, #[serde(rename = "ProcedureDateStatus")] - pub procedure_date_status: String, + pub(crate) procedure_date_status: String, #[serde(rename = "ZuordnungErkrankung")] zuordnung_erkrankung: String, #[serde(rename = "Grafik")] @@ -326,7 +326,7 @@ pub struct Entry { datenart: Option, #[serde(rename = "Filter")] #[serde(skip_serializing_if = "Option::is_none")] - pub filter: Option, + pub(crate) filter: Option, #[serde(rename = "NotSpecified")] not_specified: bool, #[serde(rename = "Scripts")] diff --git a/src/model/requirements.rs b/src/model/requirements.rs index 962b8e7..78ce934 100644 --- a/src/model/requirements.rs +++ b/src/model/requirements.rs @@ -19,10 +19,9 @@ */ use crate::model::data_catalogue::DataCatalogue; -use crate::model::data_form::DataForm; +use crate::model::form::{DataFormType, Form, UnterformularType}; use crate::model::onkostar_editor::OnkostarEditor; use crate::model::property_catalogue::PropertyCatalogue; -use crate::model::unterformular::Unterformular; use crate::model::{Comparable, Listable, Sortable}; use std::fmt::Display; @@ -32,14 +31,14 @@ pub enum Requirement<'a> { DataCatalogue(&'a DataCatalogue), ExternalPropertyCatalogue(String), ExternalDataCatalogue(String), - DataFormReference(&'a DataForm), - UnterformularReference(&'a Unterformular), + DataFormReference(&'a Form), + UnterformularReference(&'a Form), #[allow(dead_code)] ExternalDataFormReference(String), ExternalUnterformularReference(String), - DataFormSubform(&'a DataForm), - UnterformularSubform(&'a Unterformular), + DataFormSubform(&'a Form), + UnterformularSubform(&'a Form), #[allow(dead_code)] ExternalDataFormSubform(String), ExternalUnterformularSubform(String), diff --git a/src/model/unterformular.rs b/src/model/unterformular.rs deleted file mode 100644 index 923f1ce..0000000 --- a/src/model/unterformular.rs +++ /dev/null @@ -1,699 +0,0 @@ -/* - * This file is part of osc-variant - * - * Copyright (C) 2023-2024 the original author or authors. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -use std::cmp::Ordering; -use std::collections::HashSet; - -use console::style; -use serde::{Deserialize, Serialize}; - -use crate::checks::CheckNotice::ErrorWithCode; -use crate::checks::{CheckNotice, Checkable}; -use crate::model::onkostar_editor::OnkostarEditor; -use crate::model::other::Entry; -use crate::model::requirements::{Requirement, Requires}; -use crate::model::{ - apply_profile_to_form_entry, apply_profile_to_form_field, Ansichten, Comparable, Entries, - FolderContent, FormEntry, FormEntryContainer, Kennzahlen, Listable, MenuCategory, - PlausibilityRules, PunkteKategorien, Script, Sortable, -}; -use crate::model::{Haeufigkeiten, Ordner}; -use crate::profile::Profile; - -#[derive(Serialize, Deserialize, Debug)] -#[serde(deny_unknown_fields)] -pub struct Unterformular { - #[serde(rename = "DataCatalogues")] - data_catalogues: DataCatalogues, - #[serde(rename = "Category")] - category: String, - #[serde(rename = "Name")] - name: String, - #[serde(rename = "Version")] - version: String, - #[serde(rename = "MenuEntry")] - menu_entry: String, - #[serde(rename = "Title")] - title: String, - #[serde(rename = "Description")] - description: String, - #[serde(rename = "Note")] - note: String, - #[serde(rename = "Readonly")] - readonly: bool, - #[serde(rename = "Active")] - active: bool, - #[serde(rename = "TudokPosition")] - tudok_position: String, - #[serde(rename = "Aktenbereich")] - #[serde(skip_serializing_if = "Option::is_none")] - aktenbereich: Option, - #[serde(rename = "BefragungRelevant")] - #[serde(skip_serializing_if = "Option::is_none")] - befragung_relevant: Option, - #[serde(rename = "Hotkey")] - #[serde(skip_serializing_if = "Option::is_none")] - hotkey: Option, - #[serde(rename = "Summary")] - summary: String, - #[serde(rename = "BigSummary")] - big_summary: String, - #[serde(rename = "KalenderSchnipsel")] - #[serde(skip_serializing_if = "Option::is_none")] - kalender_schnipsel: Option, - #[serde(rename = "EmailTemplate")] - #[serde(skip_serializing_if = "Option::is_none")] - mail_template: Option, - #[serde(rename = "ErkrankungText", default)] - #[serde(skip_serializing_if = "Option::is_none")] - erkrankung_text: Option, - #[serde(rename = "ErkrankungTextLong")] - #[serde(skip_serializing_if = "Option::is_none")] - erkrankung_text_long: Option, - #[serde(rename = "ErkrankungProzedurText")] - #[serde(skip_serializing_if = "Option::is_none")] - erkrankung_prozedur_text: Option, - #[serde(rename = "ErkrankungSummary")] - #[serde(skip_serializing_if = "Option::is_none")] - erkrankung_summary: Option, - #[serde(rename = "ErkrankungBigSummary")] - #[serde(skip_serializing_if = "Option::is_none")] - erkrankung_big_summary: Option, - #[serde(rename = "Kontext")] - #[serde(skip_serializing_if = "Option::is_none")] - kontext: Option, - #[serde(rename = "Datenart")] - #[serde(skip_serializing_if = "Option::is_none")] - datenart: Option, - #[serde(rename = "ShowHistoryButton", default)] - #[serde(skip_serializing_if = "Option::is_none")] - show_history_button: Option, - #[serde(rename = "TudokReadonly")] - #[serde(skip_serializing_if = "Option::is_none")] - tudok_readonly: Option, - #[serde(rename = "VitalstatusRelevant")] - #[serde(skip_serializing_if = "Option::is_none")] - vitalstatus_relevant: Option, - #[serde(rename = "AutoNummerierung")] - #[serde(skip_serializing_if = "Option::is_none")] - auto_nummerierung: Option, - #[serde(rename = "Zwischenspeichern")] - #[serde(skip_serializing_if = "Option::is_none")] - zwischenspeichern: Option, - #[serde(rename = "Zurueckblaettern")] - #[serde(skip_serializing_if = "Option::is_none")] - zurueckblaettern: Option, - #[serde(rename = "Datenbankexport")] - #[serde(skip_serializing_if = "Option::is_none")] - datenbankexport: Option, - #[serde(rename = "DatenschutzRelevant")] - #[serde(skip_serializing_if = "Option::is_none")] - datenschutz_relevant: Option, - #[serde(rename = "KonferenzRelevant")] - #[serde(skip_serializing_if = "Option::is_none")] - konferenz_relevant: Option, - #[serde(rename = "Drucken")] - #[serde(skip_serializing_if = "Option::is_none")] - drucken: Option, - #[serde(rename = "hatUnterformulare")] - hat_unterformulare: bool, - #[serde(rename = "ScriptBeimSchliessen")] - #[serde(skip_serializing_if = "Option::is_none")] - script_beim_schliessen: Option