From 267c4faa2c79d42b4824b3f2d07bf56c3199e463 Mon Sep 17 00:00:00 2001 From: Ralf Zerres Date: Sat, 27 Jun 2020 22:30:50 +0200 Subject: [PATCH] frontend: function update Signed-off-by: Ralf Zerres --- frontend/src/base_state.rs | 50 +-- frontend/src/data.rs | 232 ++++++----- frontend/src/keys.rs | 32 +- frontend/src/main.rs | 38 +- frontend/src/main_view.rs | 58 ++- frontend/src/policycheck_state.rs | 20 +- frontend/src/policycheck_view.rs | 127 ++++-- frontend/src/policydata_state.rs | 367 +++++++++-------- frontend/src/policydata_view.rs | 629 +++++++++++++++++------------- frontend/src/policylist_state.rs | 40 +- frontend/src/policylist_view.rs | 70 ++-- 11 files changed, 972 insertions(+), 691 deletions(-) diff --git a/frontend/src/base_state.rs b/frontend/src/base_state.rs index ad532f6..6f5ec0a 100644 --- a/frontend/src/base_state.rs +++ b/frontend/src/base_state.rs @@ -6,38 +6,38 @@ use crate::{data::PolicyList, keys::*}; pub trait BaseState { /// Navigates to the given entity. fn navigate(&self, to: Entity, ctx: &mut Context) { - if let Some(old_focused_element) = ctx.window().get::("global").focused_widget { - let mut old_focused_element = ctx.get_widget(old_focused_element); - old_focused_element.set("focused", false); - old_focused_element.update_theme_by_state(false); - } - ctx.window().get_mut::("global").focused_widget = None; - ctx.widget().set("visibility", Visibility::Collapsed); - ctx.get_widget(to).set("visibility", Visibility::Visible); + if let Some(old_focused_element) = ctx.window().get::("global").focused_widget { + let mut old_focused_element = ctx.get_widget(old_focused_element); + old_focused_element.set("focused", false); + old_focused_element.update_theme_by_state(false); + } + ctx.window().get_mut::("global").focused_widget = None; + ctx.widget().set("visibility", Visibility::Collapsed); + ctx.get_widget(to).set("visibility", Visibility::Visible); } - /// Fetches the text of a widget. - fn fetch_text(&self, ctx: &mut Context, entity: Entity) -> Option { - let mut widget = ctx.get_widget(entity); + /// Get the text of a widget. + fn get_text(&self, ctx: &mut Context, entity: Entity) -> Option { + let mut widget = ctx.get_widget(entity); - let entry = widget.get_mut::("text"); - if entry.is_empty() { - return None; - } + let entry = widget.get_mut::("text"); + if entry.is_empty() { + return None; + } - let copy = entry.to_string(); - entry.clear(); - Some(copy) + let copy = entry.to_string(); + entry.clear(); + Some(copy) } // Save the data. fn save(&self, registry: &mut Registry, ctx: &mut Context) { - registry - .get::("settings") - .save( - PROP_POLICY_LISTS, - ctx.widget().get::(PROP_POLICY_LISTS), - ) - .unwrap(); + registry + .get::("settings") + .save( + PROP_POLICY_LIST, + ctx.widget().get::(PROP_POLICY_LIST), + ) + .unwrap(); } } diff --git a/frontend/src/data.rs b/frontend/src/data.rs index 6d4b234..723a6d2 100644 --- a/frontend/src/data.rs +++ b/frontend/src/data.rs @@ -3,8 +3,85 @@ use orbtk::prelude::*; use chrono::NaiveDateTime; use serde::{Deserialize, Serialize}; +/// An enumeration of valid policy codes +/// right now, only "AS" is used +#[derive(Debug, Clone, Deserialize, Serialize)] +pub enum PolicyCode { + AS +} + +impl Default for PolicyCode { + fn default() -> Self { PolicyCode::AS } +} + +/// Status of a given policy data element (eg: active / inactive) +#[derive(Debug, Clone, Deserialize, Serialize)] +pub enum Status { + Active, + Inactive +} + +impl Default for Status { + fn default() -> Self { Status::Active } +} + +/// A communication type describes possible classifications of customer calls. +/// If not selected, the default will be 'unclassified'. #[derive(Default, Debug, Clone, Deserialize, Serialize)] -pub struct HarmElement { +pub struct CommunicationType { + // Unfall, Bußgeldbescheid, Anhörung, Unfallflucht, Kaufvertrag, + // Vodafone, Kündigung, Lohn, Zeugnis, Nachbar, Vermieter, Rente, GdB, Verwaltungsrecht, Unterhalt, Geburt, Hochzeit + pub communication_id: String, + pub communication_name: String, +} + +/// CSV Export +/// The structure elements are required for an export to a comma seperated text list. +#[derive(Default, Debug, Clone, Deserialize, Serialize)] +pub struct CsvExportRecord { + // policy_code => Versicherungsscheinnummer: "AS1234567890" + // policy_holder => Anrufer: "Vorname, Nachname" + // facts => Sachverhalt: "Kurzschilderung" + // harm_type => Schadensart: "harm_name (harm_id)" + // communication_type => Kommunikationszeichen: "(communication_name)" + // ra_hotline => RA_Hotline: Kanzlei Laqua, Kanzlei Buschbell, Kanzlei DAH, Kanzlei Hiedemann + // ivr_comment => Haftungs-/Deckungskommentar; #IVR (ggf. ergänzt um das Beratungsergebnis) + pub policy_code: String, + pub policy_number: u32, + pub policy_holder: String, + pub facts: String, + pub harm_type: String, + pub communication_name: String, + pub ra_hotline: String, // const "Kanzlei Hiedemann", + pub ivr_comment: String, +} + +/// CSV Import +/// The structure elements provided as a comma seperated text list. +/// Referenz: ERG.txt -> 'DION VERS POLLFNR' +/// '1 AS 1515735810' + #[derive(Default, Debug, Clone, Deserialize, Serialize)] +pub struct CsvImportRecord { + // dion => Allianz Dion: 1 + // policy_code => Policy Typ: "AS" + // policy_number => Versicherungsscheinnummer: "1515735810" + pub dion: String, + pub policy_code: String, + pub policy_number: u32, +} + +/// Harm data are list/collections of harm types. You may toggle them to an unselected state. +#[derive(Default, Debug, Clone, Deserialize, Serialize)] +pub struct HarmData { + pub harm_data: Vec, + //pub name: String, + pub selected: bool +} + +/// Harm types are destincted by a type code. +/// The type code represents the unique harm identifier, bound with a literal name. +#[derive(Default, Debug, Clone, Deserialize, Serialize)] +pub struct HarmType { // Schadenersatz-RS im Verkehrsbereich (RS112) // Ordnungswidrigkeits-RS im Verkehrsbereich (RS122) // Straf-RS im Verkehrsbereich (RS121) @@ -15,158 +92,139 @@ pub struct HarmElement { // Sozialgerichts-RS im Privatbereich (RS216) // Rechtsschutz im Familien- und Erbrecht (RS217) // Wagnis nicht versicherbar / versichert (RS999) - pub harm_id: String, - pub harm_name: String, -} - -#[derive(Default, Debug, Clone, Deserialize, Serialize)] -pub struct HarmType { - pub harm_type: Vec, - pub name: String, - pub selected: bool -} - -#[derive(Default, Debug, Clone, Deserialize, Serialize)] -pub struct CommunicationType { - // Unfall, Bußgeldbescheid, Anhörung, Unfallflucht, Kaufvertrag, - // Vodafone, Kündigung, Lohn, Zeugnis, Nachbar, Vermieter, Rente, GdB, Verwaltungsrecht, Unterhalt, Geburt, Hochzeit - pub communication_id: String, - pub communication_name: String, -} - - -/// CSV Export -#[derive(Default, Debug, Clone, Deserialize, Serialize)] -pub struct CSVExport { - // policy_code => Versicherungsscheinnummer: "AS1234567890" - // policy_holder => Anrufer: "Vorname, Nachname" - // facts => Sachverhalt: "Kurzschilderung" - // harm_type => Schadensart: "harm_name (harm_id)" - // communication_type => Kommunikationszeichen: "(communication_name)" - // ra_hotline => RA_Hotline: Kanzlei Laqua, Kanzlei Buschbell, Kanzlei DAH, Kanzlei Hiedemann - // ivr_comment => Haftungs-/Deckungskommentar; #IVR (ggf. ergänzt um das Beratungsergebnis) - pub policy_id: String, - pub policy_number: u32, - pub policy_holder: String, - pub facts: String, pub harm_type: String, - pub communication_name: String, - pub ra_hotline: String, // const "Kanzlei Hiedemann", - pub ivr_comment: String, + pub harm_name: String, } /// Structure used to verify a policy data element. #[derive(Default, Debug, Clone, Deserialize, Serialize)] pub struct PolicyCheck { - pub policy_id: String, + pub policy_check_number: String, pub policy_number: String, - pub isvalid: bool + pub policy_number_valid: bool } +// #[derive(Default, Clone, Debug, Serialize, Deserialize)] +// pub struct PolicyCheckList { +// pub title: String, +// pub list: Vec +// } + +// impl PolicyCheckList { +// pub fn new(title: impl Into) -> Self { +// PolicyCheckList { +// title: title.into(), +// ..Default::default() +// } +// } + +/// Structure collecting policy data elements #[derive(Default, Clone, Debug, Serialize, Deserialize)] pub struct PolicyList { - pub policy_list: Vec, + pub name: String, + pub policy_list: Vec, } /// implements helper methods, that manage lists of policy data collections impl PolicyList { - pub fn get(&self, index: usize) -> Option<&PolicyData> { - self.policy_list.get(index) + pub fn get(&self, index: usize) -> Option<&PolicyDataList> { + self.policy_list.get(index) } - pub fn get_mut(&mut self, index: usize) -> Option<&mut PolicyData> { - self.policy_list.get_mut(index) + pub fn get_mut(&mut self, index: usize) -> Option<&mut PolicyDataList> { + self.policy_list.get_mut(index) } - pub fn insert_front(&mut self, policy_list: PolicyData) { - self.policy_list.insert(0, policy_list); + pub fn insert_front(&mut self, policy_list: PolicyDataList) { + self.policy_list.insert(0, policy_list); } pub fn is_empty(&self) -> bool { - self.policy_list.is_empty() + self.policy_list.is_empty() } pub fn len(&self) -> usize { - self.policy_list.len() + self.policy_list.len() } - pub fn push(&mut self, policy_list: PolicyData) { - self.policy_list.push(policy_list); + pub fn new(name: impl Into) -> Self { + PolicyList { + name: name.into(), + ..Default::default() + } } - pub fn remove(&mut self, index: usize) -> PolicyData { - self.policy_list.remove(index) + pub fn push(&mut self, policy_list: PolicyDataList) { + self.policy_list.push(policy_list); + } + + pub fn remove(&mut self, index: usize) -> PolicyDataList { + self.policy_list.remove(index) } } -// Valid policy codes are represented in this Enumeration -// right now, only "AS" is used -//enum PolicyCode { -// CodeName(String), -//} - -/// Structure representing a policy data element. +/// Structure representing a policy data element #[derive(Default, Debug, Clone, Deserialize, Serialize)] -pub struct PolicyElement { +pub struct PolicyData { // DION VERS POLLFNR // 1 AS 1515735810 // DION: Allianz id => len = 1?? // VERS: policy_code => enum(AS; ??) // POLLFNR: policy_number => len = 10 + pub date_inserted: Option, pub dion: u8, // is String16 a better default-type? - pub policy_code: String, + pub policy_code: PolicyCode, pub policy_number: u32, - pub date_inserted: Option, - pub isactive: bool + pub status: Status } -/// Structure grouping valid policy data elements +/// Structure collects policy data elements. #[derive(Default, Debug, Clone, Deserialize, Serialize)] -pub struct PolicyData { +pub struct PolicyDataList { pub date_valid_until: Option, - pub policy_elements: Vec, + pub policy_data: Vec, pub name: String, pub selected: bool } /// implements the helper methods, to manage policy data collections. -impl PolicyData { +impl PolicyDataList { pub fn new(name: impl Into) -> Self { - // the new inserted element will be active by default - PolicyData { - date_valid_until: None, - name: name.into(), - selected: true, - ..Default::default() - } + // the new inserted element will be active by default + PolicyDataList { + date_valid_until: None, + name: name.into(), + selected: true, + ..Default::default() + } } - pub fn push(&mut self, policy_element: PolicyElement) { - self.policy_elements.push(policy_element); + pub fn push(&mut self, policy_data: PolicyData) { + self.policy_data.push(policy_data); } - pub fn insert_front(&mut self, policy_element: PolicyElement) { - self.policy_elements.insert(0, policy_element); + pub fn insert_front(&mut self, policy_data: PolicyData) { + self.policy_data.insert(0, policy_data); } - pub fn remove(&mut self, index: usize) -> PolicyElement { - self.policy_elements.remove(index) + pub fn remove(&mut self, index: usize) -> PolicyData { + self.policy_data.remove(index) } - pub fn get(&self, index: usize) -> Option<&PolicyElement> { - self.policy_elements.get(index) + pub fn get(&self, index: usize) -> Option<&PolicyData> { + self.policy_data.get(index) } - pub fn get_mut(&mut self, index: usize) -> Option<&mut PolicyElement> { - self.policy_elements.get_mut(index) + pub fn get_mut(&mut self, index: usize) -> Option<&mut PolicyData> { + self.policy_data.get_mut(index) } pub fn len(&self) -> usize { - self.policy_elements.len() + self.policy_data.len() } pub fn is_empty(&self) -> bool { - self.policy_elements.is_empty() + self.policy_data.is_empty() } } diff --git a/frontend/src/keys.rs b/frontend/src/keys.rs index ec86e34..da192cb 100644 --- a/frontend/src/keys.rs +++ b/frontend/src/keys.rs @@ -14,28 +14,38 @@ pub static CLASS_TOP_BAR: &str = "top_bar"; pub static CLASS_TRANSPARENT: &str = "transparent"; pub static CLASS_SEPERATOR: &str = "seperator"; -// DCES: Entity[id] => [Component1, .. , Component] -> data or state +// Widget IDs (DCES: Entity[id] => [Component1, .. , Component] -> data or state) pub static ID_POLICY_CHECK_FORM: &str = "policy_check_form"; pub static ID_POLICY_CHECK_HEADER: &str = "policy_check_header"; +//pub static ID_POLICY_CHECK_ITEMS_WIDGET: &str = "policy_check_items_widget"; pub static ID_POLICY_CHECK_LABEL_POLICY_NUMBER: &str = "policy_check_label_policy_number"; pub static ID_POLICY_CHECK_LABEL_RESULT: &str = "policy_check_label_result"; pub static ID_POLICY_CHECK_MENU_BUTTON: &str = "policy_check_menu_button"; -pub static ID_POLICY_CHECK_MENU_CONTAINER: &str = "policy_check_menu_container"; +pub static ID_POLICY_CHECK_MENU_TEXT_BLOCK: &str = "policy_check_menu_text_block"; pub static ID_POLICY_CHECK_RESULT: &str = "policy_check_result"; pub static ID_POLICY_CHECK_POLICY_NUMBER: &str = "policy_check_policy_number"; pub static ID_POLICY_CHECK_WIDGET: &str = "policy_check_widget"; + pub static ID_POLICY_DATA_ADD_BUTTON: &str = "policy_data_add_button"; pub static ID_POLICY_DATA_ITEMS_WIDGET: &str = "policy_data_items_widget"; -pub static ID_POLICY_DATA_TEXT_BOX: &str = "policy_data_text_box"; -pub static ID_POLICY_LISTS_ADD_BUTTON: &str = "policy_lists_add_button"; -pub static ID_POLICY_LISTS_ITEMS_WIDGET: &str = "policy_lists_items_widget"; -pub static ID_POLICY_LISTS_TEXT_BOX: &str = "policy_list_text_box"; +//pub static ID_POLICY_DATA_TEXT_BOX: &str = "policy_data_text_box"; +pub static ID_POLICY_DATA_DATE_INSERTED: &str = "policy_data_date_inserted"; +pub static ID_POLICY_DATA_DION: &str = "policy_data_dion"; +pub static ID_POLICY_DATA_POLICY_CODE: &str = "policy_data_policy_code"; +pub static ID_POLICY_DATA_POLICY_NUMBER: &str = "policy_data_policy_number"; +pub static ID_POLICY_DATA_STATUS: &str = "policy_data_status"; +pub static ID_POLICY_DATA_LIST_NAME: &str = "policy_data_list_name"; + +pub static ID_POLICY_LIST_ADD_BUTTON: &str = "policy_list_add_button"; +pub static ID_POLICY_LIST_ITEMS_WIDGET: &str = "policy_list_items_widget"; +pub static ID_POLICY_LIST_TEXT_BOX: &str = "policy_list_text_box"; // Component Values (Properties) pub static PROP_POLICY_CHECK: &str = "policy_check"; -pub static PROP_POLICY_CODE: &str = "policy_code"; -pub static PROP_POLICY_ELEMENT: &str = "policy_element"; -pub static PROP_POLICY_LISTS: &str = "policy_lists"; -pub static PROP_POLICY_DATA: &str = "policy_data"; -pub static PROP_POLICY_LISTS_COUNT: &str = "policy_lists_count"; +pub static PROP_POLICY_CHECK_LIST: &str = "policy_check_list"; + +pub static PROP_POLICY_DATA_LIST: &str = "policy_data_list"; pub static PROP_POLICY_DATA_COUNT: &str = "policy_data_count"; + +pub static PROP_POLICY_LIST: &str = "policy_list"; +pub static PROP_POLICY_LIST_COUNT: &str = "policy_list_count"; diff --git a/frontend/src/main.rs b/frontend/src/main.rs index 718d467..8eb2ebb 100644 --- a/frontend/src/main.rs +++ b/frontend/src/main.rs @@ -19,38 +19,42 @@ pub mod policycheck_menu; pub mod policylist_view; pub mod policylist_state; +// manage policy data elements +pub mod policydata_view; +pub mod policydata_state; + //#[cfg(feature = "light-theme")] static STYLESHEET: &'static str = include_str!("../resources/stylesheets/advotracker.css"); fn get_theme() -> ThemeValue { //ThemeValue::create_from_css(LIGHT_THEME_EXTENSION_CSS) ThemeValue::create_from_css(DEFAULT_THEME_CSS) - .extension_css(STYLESHEET) - .build() + .extension_css(STYLESHEET) + .build() } fn main() { Application::from_name("rzerres.advotracker") - .window(move |ctx| { - Window::new() - //.title("OrbTk - Policyholder checker example") - .title("AdvoTracker - Versicherungsnummern") - .position((500.0, 100.0)) - .size(640.0, 480.0) - .min_width(460.0) - .min_height(180.0) - .resizeable(true) - .theme(get_theme()) - .child(main_view::MainView::new().build(ctx)) - .build(ctx) - }) - .run(); + .window(move |ctx| { + Window::new() + //.title("OrbTk - Policyholder checker example") + .title("AdvoTracker - Versicherungsnummern") + .position((500.0, 100.0)) + .size(640.0, 480.0) + .min_width(460.0) + .min_height(180.0) + .resizeable(true) + .theme(get_theme()) + .child(main_view::MainView::new().build(ctx)) + .build(ctx) + }) + .run(); } #[cfg(test)] mod tests { #[test] fn it_works() { - assert_eq!(2 + 2, 4); + assert_eq!(2 + 2, 4); } } diff --git a/frontend/src/main_view.rs b/frontend/src/main_view.rs index 0f87380..0273045 100644 --- a/frontend/src/main_view.rs +++ b/frontend/src/main_view.rs @@ -1,41 +1,59 @@ use orbtk::prelude::*; -use crate::policycheck_view::PolicyCheckView; - //data::PolicyList, - //policylist_view::PolicyListView, - //policy_view::PolicyDataView +use crate::{ + data::{PolicyCheck, PolicyList, PolicyDataList}, + policycheck_view::PolicyCheckView, + policylist_view::PolicyListView, + policydata_view::PolicyDataView +}; + +// use crate::{ +// data::{PolicyList, PolicyData}, +// //policycheck_view::*, +// //PolicyCheckView, +// //policylist_view::*, +// //PolicyListView, +// //policydata_view::*, +// //PolicyDataList +// }; widget!(MainView { policy_list_count: usize, + policy_list: PolicyList, + policy_data_list: PolicyDataList, + policycheck_view: u32, policylist_view: u32, - policy_view: u32 + policydata_view: u32 }); impl Template for MainView { fn template(self, id: Entity, ctx: &mut BuildContext) -> Self { let policycheck_view = PolicyCheckView::new() - //.policylist_view(id) - //.policylist_count(id) - .build(ctx); - /* let policylist_view = PolicyList::new() - .back_entity(policycheck_view.0) - .policydata_view(id) - .policy_list_count(id) .policylist_view(id) .build(ctx); - */ - /* - let policydata_view = TaskView::new() - .back_entity(policy_view.0) + + let policylist_view = PolicyListView::new() + .back_entity(policycheck_view.0) + .policydata_view(id) + .policylist_view(id) + .policy_list_count(id) + .build(ctx); + + let policydata_view = PolicyDataView::new() + .back_entity(policylist_view.0) .policylist_view(id) .visibility("collapsed") .build(ctx); - */ self.name("MainView") - //.policy_list(policy_list.0) - //.policylist_view(PolicyList:default()) - //.policy_list_count(0) + .policy_list_count(0) + .policycheck_view(PolicyCheck::default()) + //.policycheck_view(0) + .policydata_view(policydata_view.0) + //.policylist_view(PolicyList::default()) + .policylist_view(policylist_view.0) + .child(policydata_view) + .child(policylist_view) .child(policycheck_view) } } diff --git a/frontend/src/policycheck_state.rs b/frontend/src/policycheck_state.rs index e93e1c9..396d308 100644 --- a/frontend/src/policycheck_state.rs +++ b/frontend/src/policycheck_state.rs @@ -2,7 +2,7 @@ use orbtk::prelude::*; use crate::{ base_state::BaseState, - //data::{PolicyData, PolicyList}, + data::{PolicyData, PolicyDataList}, keys::*, }; @@ -11,13 +11,14 @@ use crate::{ pub enum Action { ClearEntry(Entity), InputTextChanged(Entity), + OpenMenu(Entity), ParseEntry(Entity), RemoveFocus(Entity), SetEntry(Entity), TextChanged(Entity, usize), } -/// Handles the requests of the `OverviewView`. +/// Handles the requests of the `PolicyCheckView`. #[derive(Default, AsAny)] pub struct PolicyCheckState { action:Option, @@ -42,9 +43,13 @@ impl PolicyCheckState { println!("reset {}", text); } + /// Open menu. + pub fn open_menu(&mut self, text_block: Entity, ctx: &mut Context) { + let mut text_block = TextBlock::get(ctx.get_widget(text_block)); + let text = text_block.text_mut(); + println!("Menu text: {}", text); + } - /// Parse and verify given policy code to match a valid policy data element. - //fn parse_entry(&self, text_box: Entity, ctx: &mut Context) -> Result<(), Box> { fn parse_entry(&self, text_box: Entity, ctx: &mut Context) { // Old style //let length = ctx.get_widget(text_box).get::("policy_number").len(); @@ -125,10 +130,10 @@ impl State for PolicyCheckState { fn init(&mut self, _: &mut Registry, ctx: &mut Context) { self.menu_button = ctx .entity_of_child(ID_POLICY_CHECK_MENU_BUTTON) - .expect("PolicyState.init: Can't find child 'Menu button'."); + .expect("PolicyCheckState.init: Can't find child 'Menu button'."); self.text_box = ctx .entity_of_child(ID_POLICY_CHECK_POLICY_NUMBER) - .expect("PolicyState.init: Can't find child 'Text Box'."); + .expect("PolicyCheckState.init: Can't find child 'Text Box'."); } fn update(&mut self, _registry: &mut Registry, ctx: &mut Context) { @@ -149,6 +154,9 @@ impl State for PolicyCheckState { Action::InputTextChanged(text_box) => { self.set_check_button(text_box, ctx); } + Action::OpenMenu(text_block) => { + self.open_menu(text_block, ctx); + } Action::ParseEntry(text_box) => { self.parse_entry(text_box, ctx); } diff --git a/frontend/src/policycheck_view.rs b/frontend/src/policycheck_view.rs index 8f95338..cf6ace5 100644 --- a/frontend/src/policycheck_view.rs +++ b/frontend/src/policycheck_view.rs @@ -1,26 +1,79 @@ use orbtk::prelude::*; -use orbtk::theme::vector_graphics::material_icons_font; +//use orbtk::theme::vector_graphics::material_icons_font_ttf; use crate::{ - //data::PolicyList, + data::PolicyCheck, keys::*, + policycheck_state::*, //policycheck_state::{Action, PolicyCheckState}, }; -widget!(PolicyCheckView); -// widget!( -// /// Starter page that offers the dialog to enter an identifier of a policy. -// /// This identifier is checked agains a map of valid policy codes. -// PolicyCheckView { -// //is_valid: bool, -// title: String, -// policy_check_text_box: String -// } -// ); - +widget!( + /// Dialog to enter a policy identifier/number. + /// This identifier is checked agains a map of valid policy codes. + PolicyCheckView { + policy_check: PolicyCheck, + //policy_check_list: PolicyCheckList, + policy_check_title: String, + policy_check_number: String, + policy_check_number_valid: bool, + policy_check_text_box: String, + policy_data_count: u32, + policylist_view: u32, + title: String + } +); impl Template for PolicyCheckView { fn template(self, id: Entity, ctx: &mut BuildContext)-> Self { + // collect the DCES elements of our 'policy check' view + // let items_widget = ItemsWidget::new() + // .id(ID_POLICY_CHECK_ITEMS_WIDGET) + // .v_align("start") + // .items_builder(move |ctx, index| { + // let mut title = "".to_string(); + + // if let Some(policy_check) = ctx + // .get_widget(id) + // .get::(PROP_POLICY_CHECK_LIST) + // .get(index) + // { + // title = policy_check.title.clone(); + // } + // }) + // .count((PROP_POLICY_DATA_COUNT, id)) + // .build(ctx); + + + let policycheck_menu_text_block = TextBlock::new() + .foreground("#3b434a") + .text("Help Menu") + .v_align("center") + .h_align("center") + .build(ctx); + + let policy_check_menu_button = Button::new() + .margin((0.0, 0.0, 12.0, 12.0)) + .icon(material_icons_font_ttf::MD_MENU) + //.class(CLASS_ICON_ONLY) + //.attach(Grid::row(0)) + .attach(Grid::column(2)) + .margin((8.0, 0.0, 2.0, 0.0)) + .text("Menu Button") + //.min_size(8.0, 8.0) + //.min_size(16.0, 16.0) + //.h_align("end") + //.v_align("center") + //.enabled(true) + //.on_mouse_down(|_, _| true) + //.child(policycheck_menu_container) + //.on_click(move |ctx, _| { + // ctx.get_mut::(id) + // .action(Action::OpenMenu(policy_check_menu_text_block)); + // true + //}) + .build(ctx); + // let policy_check_text_box = TextBox::new() // .id(ID_POLICY_CHECK_TEXT_BOX) // .attach(Grid::row(4)) @@ -50,41 +103,26 @@ impl Template for PolicyCheckView { // .min_size(120.0, 180.0) // .v_align("center") // .on_click(move |ctx, _| { - // ctx.get_mut::(id) - // .action(Action::NewEntry(quit)); - // true + // ctx.get_mut::(id) + // .action(Action::NewEntry(quit)); + // true // }) // .build(ctx); - let policy_check_menu_button = Button::new() - .id(ID_POLICY_CHECK_MENU_BUTTON) - //.class(CLASS_ICON_ONLY) - //.attach(Grid::row(0)) - .attach(Grid::column(2)) - //.margin((0.0, 0.0, 12.0, 12.0)) - //.min_size(8.0, 8.0) - .min_size(16.0, 16.0) - .h_align("end") - .v_align("center") - .enabled(true) - //.icon(material_icons_font::MENU_FONT_ICON) - //.icon(material_icons_font_ttf::EDIT_FONT_ICON) - //.icon("") - //.icon("") - .on_mouse_down(|_, _| true) - //.child(policycheck_menu) - // .on_click(move |ctx, _| { - // //ctx.get_mut::(id) - // // .action(Action::NewEntry(policy_check_menu_container)); - // true - //}) - .build(ctx); + // let policycheck_menu_container = Container::new() + // .id(ID_POLICY_CHECK_MENU_CONTAINER) + // .background("#dfebf5") + // .width(200.0) + // .height(200.0) + // .child( // The menu implemented as an overlay //ctx.append_child_to_overlay(policy_check_menu_button).unwrap(); - // Check policy identifier page - self.name("Policy check").child( + // Starter page: check for valid policy number + self.name("PolicyCheckView") + .policy_check(PolicyCheck::default()) + .child( Grid::new() .id(ID_POLICY_CHECK_WIDGET) //.v_align("start") @@ -133,7 +171,7 @@ impl Template for PolicyCheckView { ) .build(ctx), ) - .child(policy_check_menu_button) + //.child(policy_check_menu_button) .build(ctx), ) .child( @@ -294,10 +332,15 @@ impl Template for PolicyCheckView { .build(ctx), ) .build(ctx), + + //ctx.append_child_to_overlay(policycheck_menu_text_block).unwrap() + ) .build(ctx), + ) .build(ctx), + ) } diff --git a/frontend/src/policydata_state.rs b/frontend/src/policydata_state.rs index 876b376..a0ffbac 100644 --- a/frontend/src/policydata_state.rs +++ b/frontend/src/policydata_state.rs @@ -2,11 +2,10 @@ use orbtk::prelude::*; use crate::{ base_state::BaseState, - data::{PolicyData, PolicyList}, + data::{PolicyCode, PolicyData, PolicyList, Status}, keys::*, }; -use chrono::{Local, NaiveDateTime}; -//use chrono::{DateTime, Local, TimeZone, NaiveDateTime, Utc}; +use chrono::{Utc, NaiveDateTime}; /// Actions that can execute on the task view. #[derive(Debug, Clone, Copy)] @@ -16,19 +15,25 @@ pub enum Action { NewEntry(Entity), RemoveFocus(Entity), RemoveEntry(usize), - SetEntry(Entity), + SetDateInserted(Entity), + SetDion(Entity), + SetPolicyCode(Entity), + SetPolicyNumber(Entity), StatusChanged(Entity, usize), TextChanged(Entity, usize), } -/// Handles the requests of the `OverviewView`. -#[derive(Default, AsAny)] +/// Handles the requests of the `PolicyDataListView`. +#[derive(Debug, Default, AsAny)] pub struct PolicyDataState { action:Option, - add_button: Entity, back_entity: Entity, last_focused: Option, - pub text_box: Entity, + policy_data_add_button: Entity, + pub policy_data_date_inserted: Entity, + pub policy_data_dion: Entity, + pub policy_data_policy_code: Entity, + pub policy_data_policy_number: Entity, open: bool, } @@ -39,214 +44,240 @@ impl BaseState for PolicyDataState {} impl PolicyDataState { /// Sets a new action. pub fn action(&mut self, action: Action) { - self.action = action.into(); + self.action = action.into(); } /// update number of available policy data entries. fn adjust_count(&self, ctx: &mut Context) { - if let Some(index) = ctx.widget().clone::>("list_index") { - if let Some(policy_list) = ctx - .widget() - .clone::("policy_list") - .get(index) - { - ctx.widget().set("policy_data_count", policy_list.len()); - } - } + if let Some(index) = ctx.widget().clone::>("list_index") { + if let Some(policy_list) = ctx + .widget() + .clone::("policy_list") + .get(index) + { + ctx.widget().set("policy_data_count", policy_list.len()); + } + } } /// If policy data element 'name' is empty, disable the add button /// otherwise otherwise enabled it. fn adjust_add_button_enabled(&self, text_box: Entity, ctx: &mut Context) { - if ctx.get_widget(text_box).get::("name").is_empty() { - ctx.get_widget(self.add_button).set("enabled", false); - } else { - ctx.get_widget(self.add_button).set("enabled", true); - } + if ctx.get_widget(text_box).get::("name").is_empty() { + ctx.get_widget(self.policy_data_add_button).set("enabled", false); + } else { + ctx.get_widget(self.policy_data_add_button).set("enabled", true); + } - ctx.get_widget(self.add_button).update_theme_by_state(true); + ctx.get_widget(self.policy_data_add_button).update_theme_by_state(true); } /// Change status of given text box to edit mode. fn edit_entry(&self, text_box: Entity, ctx: &mut Context) { - if *ctx.get_widget(text_box).get::("focused") { - ctx.get_widget(text_box).set("enabled", false); - ctx.push_event_by_window(FocusEvent::RemoveFocus(text_box)); - return; - } + if *ctx.get_widget(text_box).get::("focused") { + ctx.get_widget(text_box).set("enabled", false); + ctx.push_event_by_window(FocusEvent::RemoveFocus(text_box)); + return; + } - if let Some(old_focused_element) = ctx.window().get::("global").focused_widget { - ctx.push_event_by_window(FocusEvent::RemoveFocus(old_focused_element)); - } + if let Some(old_focused_element) = ctx.window().get::("global").focused_widget { + ctx.push_event_by_window(FocusEvent::RemoveFocus(old_focused_element)); + } - ctx.get_widget(text_box).set("enabled", true); + ctx.get_widget(text_box).set("enabled", true); - // select all - ctx.get_widget(text_box) - .get_mut::("text_selection") - .start_index = 0; - ctx.get_widget(text_box) - .get_mut::("text_selection") - .length = ctx.get_widget(text_box).get::("name").len(); - ctx.push_event_by_window(FocusEvent::RequestFocus(text_box)); + // select all + ctx.get_widget(text_box) + .get_mut::("text_selection") + .start_index = 0; + ctx.get_widget(text_box) + .get_mut::("text_selection") + .length = ctx.get_widget(text_box).get::("name").len(); + ctx.push_event_by_window(FocusEvent::RequestFocus(text_box)); } /// navigate to previous policy data entry. fn navigate_back(&mut self, ctx: &mut Context) { - ctx.get_widget(self.text_box) - .set("name", String16::from("")); - self.open = false; - ctx.widget().set::>("list_index", None); - ctx.widget().set("policy_data_count", 0 as usize); - self.navigate(self.back_entity, ctx); + ctx.get_widget(self.text_box) + .set("name", String16::from("")); + self.open = false; + ctx.widget().set::>("list_index", None); + ctx.widget().set("policy_data_count", 0 as usize); + self.navigate(self.back_entity, ctx); } /// create a new policy data member - fn new_entry(&self, name: String, registry: &mut Registry, ctx: &mut Context) { - let index = ctx.widget().clone::>("list_index"); + fn new_entry(&self, policy_number: u32, registry: &mut Registry, ctx: &mut Context) { + let index = ctx.widget().clone::>("list_index"); - if let Some(index) = index { - if let Some(policy_elements) = ctx - .widget() - .get_mut::("policy_elements") - .get_mut(index) - { - policy_list.push(PolicyData { - policy_code, - date_valid_until, - selected: true, - }); - } + if let Some(index) = index { + if let Some(policy_data) = ctx + .widget() + .get_mut::("policy_list") + .get_mut(index) + { + policy_data.push(PolicyData { + date_inserted: Some(Utc::now().naive_utc()), + dion: 1, + policy_code: PolicyCode::AS, + policy_number, + status: Status::Active, + }); + } - self.adjust_count(ctx); - } + self.adjust_count(ctx); + } - self.save(registry, ctx); + self.save(registry, ctx); } pub fn open(&mut self, ctx: &mut Context) { - if let Some(index) = ctx.widget().clone::>("list_index") { - let mut name: String16 = "".into(); - let mut policy_data_count = 0; - if let Some(policy_list) = ctx.widget().get::("policy_list").get(index) { - name = String16::from(policy_list.name.as_str()); - policy_data_count = policy_list.len(); - } - ctx.widget().set("name", title); - ctx.widget().set("policy_data_count", policy_count); - self.open = true; - } + if let Some(index) = ctx.widget().clone::>("list_index") { + let mut name: String16 = "".into(); + let mut policy_data_count = 0; + if let Some(policy_list) = ctx.widget().get::("policy_list").get(index) { + name = String16::from(policy_list.name.as_str()); + policy_data_count = policy_list.len(); + } + ctx.widget().set("name", name); + ctx.widget().set("policy_data_count", policy_data_count); + self.open = true; + } } fn remove_entry(&self, index: usize, registry: &mut Registry, ctx: &mut Context) { - if let Some(idx) = ctx.widget().clone::>("list_index") { - if let Some(policy_list) = ctx - .widget() - .get_mut::("policy_list") - .get_mut(idx) - { - policy_list.remove(index); - } - } - self.adjust_count(ctx); - self.save(registry, ctx); + if let Some(idx) = ctx.widget().clone::>("list_index") { + if let Some(policy_list) = ctx + .widget() + .get_mut::("policy_list") + .get_mut(idx) + { + policy_list.remove(index); + } + } + self.adjust_count(ctx); + self.save(registry, ctx); } - /// Toggle the invalid element of the given policy data entry - fn toggle_invalid( - &self, - entry: Entity, - index: usize, - registry: &mut Registry, - ctx: &mut Context, + /// Toggle the selection state of the given policy number element + fn toggle_status( + &self, + entry: Entity, + index: usize, + registry: &mut Registry, + ctx: &mut Context, ) { - let invalid: bool = *ctx.get_widget(entry).get("invalid"); + let invalid: bool = *ctx.get_widget(entry).get("status"); - if let Some(idx) = ctx.widget().clone::>("list_index") { - if let Some(policy_list) = ctx - .widget() - .get_mut::("policy_list") - .get_mut(idx) - { - if let Some(task) = policy_list.get_mut(index) { - policy.selected = selected; - } - } - } - self.save(registry, ctx); + if let Some(idx) = ctx.widget().clone::>("list_index") { + if let Some(policy_data) = ctx + .widget() + .get_mut::("policy_list") + .get_mut(idx) + { + if let Some(policy_data) = policy_data.get_mut(index) { + policy_data.status = Status::Active; + } + } + } + self.save(registry, ctx); } fn update_entry( - &self, - text_box: Entity, - index: usize, - registry: &mut Registry, - ctx: &mut Context, + &self, + policy_data_date_inserted: Entity, + policy_data_dion: Entity, + policy_data_policy_code: Entity, + policy_data_policy_number: Entity, + index: usize, + registry: &mut Registry, + ctx: &mut Context, ) { - let text: String16 = ctx.get_widget(text_box).clone("text"); + let date_inserted: Option = ctx.get_widget(policy_data_date_inserted).clone("date_inserted"); + let dion: u8 = ctx.get_widget(policy_data_dion).clone("dion"); + let policy_code: PolicyCode = ctx.get_widget(policy_data_policy_code).clone("policy_code"); + let policy_number: u32 = ctx.get_widget(policy_data_policy_number).clone("policy_number"); - if let Some(idx) = ctx.widget().clone::>("list_index") { - if let Some(policy_list) = ctx - .widget() - .get_mut::("policy_list") - .get_mut(idx) - { - if let Some(task) = policy_list.get_mut(index) { - task.text = text.to_string(); - } - } - } - self.save(registry, ctx); + // get the index from the active widgets 'list_index' member + if let Some(idx) = ctx.widget().clone::>("list_index") { + // get view record from the active widgets 'policy_list' member + if let Some(policy_list) = ctx + .widget() + .get_mut::("policy_list") + .get_mut(idx) + { + // update the record data using the view values of the active policy_list member + if let Some(policy_data) = policy_list.get_mut(index) { + policy_data.date_inserted = date_inserted; + policy_data.dion = dion; + policy_data.policy_code = policy_code; + policy_data.policy_number = policy_number; + } + } + } + self.save(registry, ctx); } } -impl State for PolicyState { +impl State for PolicyDataState { fn init(&mut self, _: &mut Registry, ctx: &mut Context) { - self.back_entity = (*ctx.widget().get::("back_entity")).into(); - self.add_button = ctx - .entity_of_child(ID_POLICY_ADD_BUTTON) - .expect("PolicyState.init: Can't find child 'Add button'."); - self.text_box = ctx - .entity_of_child(ID_POLICY_TEXT_BOX) - .expect("PolicyState.init: Can't find child 'Text Box'."); + self.back_entity = (*ctx.widget().get::("back_entity")).into(); + self.policy_data_add_button = ctx + .entity_of_child(ID_POLICY_DATA_ADD_BUTTON) + .expect("PolicyState.init: Can't find child 'Add button'."); + self.policy_data_policy_number = ctx + .entity_of_child(ID_POLICY_DATA_POLICY_NUMBER) + .expect("PolicyState.init: Can't find child 'Policy Number'."); } fn update(&mut self, registry: &mut Registry, ctx: &mut Context) { - if !self.open { - self.open(ctx); - } - if let Some(action) = self.action { - match action { - Action::InputTextChanged(text_box) => { - self.adjust_add_button_enabled(text_box, ctx); - } - Action::CreateEntry(entity) => { - if let Some(text) = self.fetch_text(ctx, entity) { - self.create_entry(name, registry, ctx); - } - } - Action::RemoveEntry(index) => { - self.remove_entry(index, registry, ctx); - } - Action::SelectionChanged(entity, index) => { - self.toggle_selection(entity, index, registry, ctx); - } - Action::TextChanged(entity, index) => { - self.update_entry(entity, index, registry, ctx); - } - Action::EditEntry(text_box) => { - self.last_focused = Some(text_box); - self.edit_entry(text_box, ctx); - } - Action::RemoveFocus(text_box) => { - ctx.get_widget(text_box).set("enabled", false); - ctx.push_event_by_window(FocusEvent::RemoveFocus(text_box)); - } - Action::NavigateBack() => { - self.navigate_back(ctx); - } - } - } - self.action = None; + if !self.open { + self.open(ctx); + } + if let Some(action) = self.action { + match action { + Action::InputTextChanged(text_box) => { + self.adjust_add_button_enabled(text_box, ctx); + } + Action::NewEntry(entity) => { + if let Some(text) = self.fetch_text(ctx, entity) { + self.new_entry(text, registry, ctx); + } + } + Action::RemoveEntry(index) => { + self.remove_entry(index, registry, ctx); + } + Action::SelectionChanged(entity, index) => { + self.toggle_selection(entity, index, registry, ctx); + } + Action::TextChanged(entity, index) => { + self.update_entry(entity, index, registry, ctx); + } + Action::SetDateInserted(policy_data_date_inserted) => { + self.last_focused = Some(policy_data_date_inserted); + self.edit_entry(policy_data_date_inserted, ctx); + } + Action::SetDion(policy_data_dion) => { + self.last_focused = Some(policy_data_dion); + self.edit_entry(policy_data_policy_dion); + } + Action::SetPolicyCode(policy_data_policy_code) => { + self.last_focused = Some(policy_data_policy_code); + self.edit_entry(policy_data_policy_code, ctx); + } + Action::SetPolicyNumber(policy_data_policy_number) => { + self.last_focused = Some(policy_data_policy_number); + self.edit_entry(policy_data_policy_number, ctx); + } + Action::RemoveFocus(text_box) => { + ctx.get_widget(text_box).set("enabled", false); + ctx.push_event_by_window(FocusEvent::RemoveFocus(text_box)); + } + Action::NavigateBack() => { + self.navigate_back(ctx); + } + } + } + self.action = None; } } diff --git a/frontend/src/policydata_view.rs b/frontend/src/policydata_view.rs index 103812d..c54f684 100644 --- a/frontend/src/policydata_view.rs +++ b/frontend/src/policydata_view.rs @@ -1,280 +1,387 @@ use orbtk::prelude::*; use crate::{ - data::PolicyData, + data::{PolicyList, Status}, keys::*, - policy_state::{Action, PolicyState}, + policydata_state::{Action, PolicyDataState}, }; +use chrono::NaiveDateTime; type ListIndex = Option; -widget!(PolicyData { - back_entity: u32, - list_index: ListIndex, - name: String16 - policy_data: PolicyData, - policy_data_count: usize, +// Dialog to manage policy identifiers. +// The elements may be toggled to be deactivated. The optional value 'data_valid_until' +// will render this value unvalid after the given date. +widget!( + PolicyDataView { + back_entity: u32, + policy_list_count: usize, + policylist_view: u32, + list_index: ListIndex, + date_valid_until: NaiveDateTime, + policy_list: PolicyList }); -impl Template for PolicyData { +impl Template for PolicyDataView { fn template(self, id: Entity, ctx: &mut BuildContext) -> Self { - // listing the policy elements - let items_widget = ItemsWidget::new() - .id(ID_POLICY_DATA_ITEMS_WIDGET) - .v_align("start") - .items_builder(move |ctx, index| { - let mut policy_code = "".to_string(); - let mut date_inserted = None; - let mut isactive = false; + // listing the policy elements + let items_widget = ItemsWidget::new() + .id(ID_POLICY_DATA_ITEMS_WIDGET) + .v_align("start") + .items_builder(move |ctx, index| { + let mut date_inserted = None; + let mut dion = 1; + let mut policy_code = "".to_string(); + let mut policy_number = None; + let mut status = false; // Status::; - if let Some(list_index) = ctx.get_widget(id).clone::("list_index") { - if let Some(policy_data) = ctx - .get_widget(id) - .get::("list_index") { + if let Some(policy_data) = ctx + .get_widget(id) + .get::(PROP_POLICY_LIST) + .get(list_index) + { + if let Some(policy_data) = policy_data.get(index) { + date_inserted = policy_data.date_inserted.clone(); + dion = policy_data.dion.clone(); + policy_code = policy_data.policy_code.clone(); + policy_number = policy_data.policy_number.clone(); + status = policy_data.status; + } + } + } - let text_box = TextBox::new() - .text(name) - .enabled(false) - .v_align("center") - .water_mark("Insert the new policy collection name ...") - .class("inplace") - .attach(Grid::column(3)) - .on_changed(move |ctx, entity| { - ctx.get_mut::(id) - .action(Action::TextChanged(entity, index)); - }) - .on_activate(move |ctx, entity| { - ctx.get_mut::(id) - .action(Action::RemoveFocus(entity)); - }) - .build(ctx); + let policy_data_status = CheckBox::new() + .attach(Grid::column(1)) + .v_align("center") + // status: true -> State::Active false -> State::Inactive + .enabled(status) + .on_changed(move |ctx, entity| { + ctx.get_mut::(id) + .action(Action::StatusChanged(entity, index)); + }) + .build(ctx); - Grid::new() - .height(48.0) - .columns( - Columns::new() - .add(10.0) - .add(24.0) - .add(8.0) - .add("*") - .add(8.0) - .add(32.0) - .add(4.0) - .add(32.0) - .add(8.0) - .build(), - ) - .child( - CheckBox::new() - .attach(Grid::column(1)) - .v_align("center") - .invalid(invalid) - .on_changed(move |ctx, entity| { - ctx.get_mut::(id) - .action(Action::StatusChanged(entity, index)); - }) - .build(ctx), - ) - .child(text_box) - .child( - ToggleButton::new() - .selected(("focused", text_box)) - .class(CLASS_ICON_ONLY) - .attach(Grid::column(5)) - .min_size(32.0, 32.0) - .v_align("center") - .build(ctx), - ) - .child( - Button::new() - .class(CLASS_ICON_ONLY) - .attach(Grid::column(5)) - .min_size(32.0, 32.0) - .v_align("center") - // todo use remove from icons - // .icon(material_font_icons::DELETE_FONT_ICON) - .icon("") - .on_mouse_down(|_, _| true) - .on_click(move |ctx, _| { - ctx.get_mut::(id) - .action(Action::EditEntry(text_box)); - true - }) - .build(ctx), - ) - .child( - Button::new() - .class("icon_only") - .attach(Grid::column(7)) - .min_size(32.0, 32.0) - .v_align("center") - // todo use remove from icons - // .icon(material_font_icons::DELETE_FONT_ICON) - .icon("") - .on_mouse_down(|_, _| true) - .on_click(move |ctx, _| { - ctx.get_mut::(id) - .action(Action::RemoveEntry(index)); - true - }) - .build(ctx), - ) - .build(ctx) - }) - .policy_data_count(PROP_POLICY_COUNT, id) - .build(ctx); + let policy_data_dion = TextBox::new() + .id(ID_POLICY_DATA_DION) + .attach(Grid::row(3)) + .v_align("center") + .margin((4.0, 0.0, 0.0, 0.0)) + .text(dion) + .lost_focus_on_activation(false) + .on_activate(move |ctx, entity| { + ctx.get_mut::(id) + .action(Action::CreateEntry(entity)); + }) + .on_changed(move |ctx, entity| { + ctx.get_mut::(id) + .action(Action::InputTextChanged(entity)); + }) + .build(ctx); - let scroll_viewer = ScrollViewer::new() - .scroll_viewer_mode(("disabled", "auto")) - .child(items_widget) - .build(ctx); + let policy_data_dion = TextBox::new() + .id(ID_POLICY_DATA_DION) + .attach(Grid::row(5)) + .v_align("center") + .margin((4.0, 0.0, 0.0, 0.0)) + .text(policy_code) + .lost_focus_on_activation(false) + .on_activate(move |ctx, entity| { + ctx.get_mut::(id) + .action(Action::TextChanged(entity)); + }) + .on_changed(move |ctx, entity| { + ctx.get_mut::(id) + .action(Action::RemoveFocus(entity)); + }) + .build(ctx); - let task_text_box = TextBox::new() - .id(ID_POLICY_TEXT_BOX) - .attach(Grid::row(4)) - .v_align("center") - .margin((4.0, 0.0, 0.0, 0.0)) - .lost_focus_on_activation(false) - .on_activate(move |ctx, entity| { - ctx.get_mut::(id) - .action(Action::CreateEntry(entity)); - }) - .on_changed(move |ctx, entity| { - ctx.get_mut::(id) - .action(Action::InputTextChanged(entity)); - }) - .build(ctx); + let policy_data_policy_code = TextBox::new() + .id(ID_POLICY_DATA_POLICY_CODE) + .attach(Grid::row(7)) + .v_align("center") + .margin((4.0, 0.0, 0.0, 0.0)) + .text(policy_code) + .lost_focus_on_activation(false) + .on_activate(move |ctx, entity| { + ctx.get_mut::(id) + .action(Action::TextChanged(entity)); + }) + .on_changed(move |ctx, entity| { + ctx.get_mut::(id) + .action(Action::RemoveFocus(entity)); + }) + .build(ctx); - self.name("PolicyList").child( - Grid::new() - .rows( - Rows::new() - .add(52.0) - .add(1.0) - .add("*") - .add(1.0) - .add("auto") - .build(), - ) - .columns( - Columns::new() - .add("*") - .add(4.0) - .add(36.0) - .build(), - ) - // Content - .child( - Container::new() - .attach(Grid::row(2)) - .attach(Grid::column(0)) - .attach(Grid::column_span(3)) - .child(scroll_viewer) - .child( - ScrollIndicator::new() - .padding((0.0, 4.0, 0.0, 0.0)) - .content_id(items_widget.0) - .scroll_offset(scroll_viewer) - .build(ctx), - ) - .build(ctx), - ) - // Top Bar - .child( - Container::new() - .class(CLASS_TOP_BAR) - .attach(Grid::row(0)) - .attach(Grid::column(0)) - .attach(Grid::column_span(3)) - .child( - Grid::new() - .columns( - Columns::new() - .add(32.0) - .add(4.0) - .add("*") - .add(4.0) - .add(32.0) - .build(), - ) - .child( - Button::new() - .height(32.0) - .icon("") - .class(CLASS_ICON_ONLY) - .v_align("center") - .on_click(move |ctx, _| { - ctx.get_mut::(id) - .action(Action::NavigateBack()); - true - }) - .build(ctx), - ) - .child( - TextBlock::new() - .class(CLASS_HEADER) - .attach(Grid::column(2)) - .v_align("center") - .h_align("center") - .text(("name", id)) - .build(ctx), - ) - .build(ctx), - ) - .build(ctx), - ) - .child( - Container::new() - .class("separator") - .attach(Grid::row(1)) - .attach(Grid::column_span(3)) - .build(ctx), - ) - .child( - Container::new() - .class("separator") - .attach(Grid::row(3)) - .attach(Grid::column_span(3)) - .build(ctx), - ) - // Bottom bar - .child( - Container::new() - .class(CLASS_BOTTOM_BAR) - .attach(Grid::row(4)) - .attach(Grid::column(0)) - .attach(Grid::column_span(3)) - .build(ctx), - ) - .child(task_text_box) - .child( - Button::new() - .id(ID_POLICY_ADD_BUTTON) - .class(CLASS_ICON_ONLY) - .attach(Grid::row(4)) - .attach(Grid::column(2)) - .margin((0.0, 0.0, 4.0, 0.0)) - .enabled(false) - .min_size(32.0, 32.0) - .v_align("center") - .icon(material_font_icons::ADD_FONT_ICON) - .on_click(move |ctx, _| { - ctx.get_mut::(id) - .action(Action::CreateEntry(task_text_box)); - true - }) - .build(ctx), - ) - .build(ctx), - ) + + let policy_data_policy_number = TextBox::new() + .id(ID_POLICY_DATA_POLICY_NUMBER) + .attach(Grid::column(9)) + .text(policy_number) + .enabled(false) + .v_align("center") + .water_mark("Insert the new policy number ...") + .class("inplace") + .on_activate(move |ctx, entity| { + ctx.get_mut::(id) + .action(Action::TextChanged(entity)); + }) + .on_changed(move |ctx, entity| { + ctx.get_mut::(id) + .action(Action::RemoveFocus(entity)); + }) + .build(ctx); + + let policy_data_date_inserted = TextBlock::new() + .id(ID_POLICY_DATA_DATE_INSERTED) + .attach(Grid::column(9)) + .text(date_inserted) + .v_align("start") + .on_activate(move |ctx, entity| { + ctx.get_mut::(id) + .action(Action::TextChanged(entity)); + }) + .on_changed(move |ctx, entity| { + ctx.get_mut::(id) + .action(Action::RemoveFocus(entity)); + }) + .build(ctx); + + Grid::new() + .height(48.0) + .columns( + Columns::new() + .add(10.0) + .add(24.0) + .add(8.0) + .add(24.0) + .add(8.0) + .add(24.0) + .add(8.0) + .add("auto") + .add(8.0) + .add("auto") + .add(8.0) + .add(32.0) + .add(4.0) + .add(32.0) + .add(8.0) + .build(), + ) + .child(policy_data_status) + .child(policy_data_dion) + .child(policy_data_policy_code) + .child(policy_data_policy_number) + .child(policy_data_date_inserted) + .child( + // edit active policy data element + Button::new() + .class(CLASS_ICON_ONLY) + .attach(Grid::column(11)) + .min_size(32.0, 32.0) + .v_align("center") + .icon(material_icons_font_ttf::MD_EDIT) + //.icon("") + .on_mouse_down(|_, _| true) + .on_click(move |ctx, _| { + ctx.get_mut::(id) + .action(Action::EditEntry(text_box)); + true + }) + .build(ctx), + ) + .child( + // delete active policy data element + Button::new() + .class("icon_only") + .attach(Grid::column(13)) + .min_size(32.0, 32.0) + .v_align("center") + .icon(material_icons_font_ttf::MD_DELETE) + //.icon("") + .on_mouse_down(|_, _| true) + .on_click(move |ctx, _| { + ctx.get_mut::(id) + .action(Action::RemoveEntry(index)); + true + }) + .build(ctx), + ) + .build(ctx) + }) + .policy_data_count(PROP_POLICY_DATA_COUNT, id) + .build(ctx); + + let scroll_viewer = ScrollViewer::new() + .scroll_viewer_mode(("disabled", "auto")) + .child(items_widget) + .build(ctx); + + let policy_data_list_name = TextBox::new() + .id(ID_POLICY_DATA_LIST_NAME) + .attach(Grid::row(4)) + .v_align("center") + .margin((4.0, 0.0, 0.0, 0.0)) + .lost_focus_on_activation(false) + .on_activate(move |ctx, entity| { + ctx.get_mut::(id) + .action(Action::CreateEntry(entity)); + }) + .on_changed(move |ctx, entity| { + ctx.get_mut::(id) + .action(Action::InputTextChanged(entity)); + }) + .build(ctx); + + // Child page: list available policy data elements + self.name("PolicyDataListView").child( + Grid::new() + .rows( + Rows::new() + .add(52.0) + .add(1.0) + .add("*") + .add(1.0) + .add("auto") + .build(), + ) + .columns( + Columns::new() + .add("*") + .add(4.0) + .add(36.0) + .build(), + ) + // Top Bar + .child( + Container::new() + .class(CLASS_TOP_BAR) + .attach(Grid::row(0)) + .attach(Grid::column(0)) + .attach(Grid::column_span(3)) + .child( + Grid::new() + .columns( + Columns::new() + .add(32.0) + .add(4.0) + .add("*") + .add(4.0) + .add(32.0) + .build(), + ) + .child( + Button::new() + .height(32.0) + .icon(material_icons_font_ttf::MD_ARROW_LEFT) + //.icon("") + .class(CLASS_ICON_ONLY) + .v_align("center") + .on_click(move |ctx, _| { + ctx.get_mut::(id) + .action(Action::NavigateBack()); + true + }) + .build(ctx), + ) + .child( + TextBlock::new() + .class(CLASS_HEADER) + .attach(Grid::column(2)) + .v_align("center") + .h_align("center") + .text(("name", id)) + .build(ctx), + ) + .child( + Stack::new() + .class(CLASS_HEADER) + .attach(Grid::column(3)) + .h_align("start") + .orientation("horizontal") + .child( + TextBox::new() + .class(CLASS_HEADER) + //.v_align("center") + .h_align("start") + .text(("Anzahl:", id)) + .build(ctx), + ) + .child( + TextBlock::new() + .class(CLASS_HEADER) + .id(PROP_POLICY_DATA_COUNT) + .attach(Grid::column(3)) + //.v_align("center") + .h_align("end") + .text("policy_data_count") + .build(ctx), + ) + .build, + ) + .build(ctx), + ) + .build(ctx), + ) + .child( + Container::new() + .class("separator") + .attach(Grid::row(1)) + .attach(Grid::column_span(3)) + .build(ctx), + ) + // Content + .child( + Container::new() + .attach(Grid::row(2)) + .attach(Grid::column(0)) + .attach(Grid::column_span(3)) + .child(scroll_viewer) + .child( + ScrollIndicator::new() + .padding((0.0, 4.0, 0.0, 0.0)) + .content_id(items_widget.0) + .scroll_offset(scroll_viewer) + .build(ctx), + ) + .build(ctx), + ) + .child( + Container::new() + .class("separator") + .attach(Grid::row(3)) + .attach(Grid::column_span(3)) + .build(ctx), + ) + // Bottom bar + .child( + Container::new() + .class(CLASS_BOTTOM_BAR) + .attach(Grid::row(4)) + .attach(Grid::column(0)) + .attach(Grid::column_span(3)) + .build(ctx), + ) + .child(policy_data_list_name) + .child( + Button::new() + .id(ID_POLICY_DATA_ADD_BUTTON) + .class(CLASS_ICON_ONLY) + .attach(Grid::row(4)) + .attach(Grid::column(2)) + .margin((0.0, 0.0, 4.0, 0.0)) + .enabled(false) + .min_size(32.0, 32.0) + .v_align("center") + .icon(material_icons_font_ttf::MD_ADD_CIRCLE) + .on_click(move |ctx, _| { + ctx.get_mut::(id) + .action(Action::CreateEntry(policy_data_list_name)); + true + }) + .build(ctx), + ) + .build(ctx), + ) } } diff --git a/frontend/src/policylist_state.rs b/frontend/src/policylist_state.rs index c6733b8..43f2159 100644 --- a/frontend/src/policylist_state.rs +++ b/frontend/src/policylist_state.rs @@ -2,7 +2,7 @@ use orbtk::prelude::*; use crate::{ base_state::BaseState, - data::{PolicyData, PolicyList}, + data::{PolicyDataList, PolicyList}, keys::*, }; @@ -18,7 +18,7 @@ pub enum Action { TextChanged(Entity, usize), } -/// Handles the requests of the `OverviewView`. +/// Handles the requests of the `PolicyListView`. #[derive(Default, AsAny)] pub struct PolicyListState { action:Option, @@ -60,21 +60,21 @@ impl PolicyListState { /// update number of available policy list entries. fn adjust_count(&self, ctx: &mut Context) { - let policy_lists_count = ctx.widget().get::(PROP_POLICY_LISTS).len(); - ctx.widget().set(PROP_POLICY_LISTS_COUNT, policy_lists_count); + let policy_list_count = ctx.widget().get::(PROP_POLICY_LIST).len(); + ctx.widget().set(PROP_POLICY_LIST_COUNT, policy_list_count); } - // Creates a new policy list. + // Creates a new policy data list. fn new_entry(&self, name: String, registry: &mut Registry, ctx: &mut Context) { ctx.widget() - .get_mut::(PROP_POLICY_LISTS) - .push(PolicyData::new(name)); + .get_mut::(PROP_POLICY_LIST) + .push(PolicyList::new(name)); self.adjust_count(ctx); self.save(registry, ctx); } // opens a given policy list name. - fn open_policy_lists(&self, index: usize, ctx: &mut Context) { + fn open_policy_list(&self, index: usize, ctx: &mut Context) { ctx.get_widget(self.text_box) .set("text", String16::from("")); ctx.get_widget(self.policydata_view) @@ -85,7 +85,7 @@ impl PolicyListState { // removes a policy list. fn remove_entry(&self, index: usize, registry: &mut Registry, ctx: &mut Context) { ctx.widget() - .get_mut::(PROP_POLICY_LISTS) + .get_mut::(PROP_POLICY_LIST) .remove(index); self.adjust_count(ctx); self.save(registry, ctx); @@ -120,22 +120,22 @@ impl PolicyListState { impl State for PolicyListState { fn init(&mut self, registry: &mut Registry, ctx: &mut Context) { self.text_box = ctx - .entity_of_child(ID_POLICY_LISTS_TEXT_BOX) + .entity_of_child(ID_POLICY_LIST_TEXT_BOX) .expect("PolicyListState.init: Child 'Text box' not found."); self.add_button = ctx - .entity_of_child(ID_POLICY_LISTS_ADD_BUTTON) + .entity_of_child(ID_POLICY_LIST_ADD_BUTTON) .expect("PolicyListState.init: Child 'Add button' not found."); self.items_widget = ctx - .entity_of_child(ID_POLICY_LISTS_ITEMS_WIDGET) + .entity_of_child(ID_POLICY_LIST_ITEMS_WIDGET) .expect("PolicyListState.init: Child 'Items widget' not found."); self.policydata_view = (*ctx.widget() - .get::("policy_lists_view")).into(); + .get::("policy_list_view")).into(); - if let Ok(tasks) = registry + if let Ok(policy_list_name) = registry .get::("settings") - .load::(PROP_POLICY_LISTS) + .load::(PROP_POLICY_LIST) { - ctx.widget().set(PROP_POLICY_LISTS, tasks); + ctx.widget().set(PROP_POLICY_LIST, policy_list_name); } self.adjust_count(ctx); @@ -157,8 +157,8 @@ impl State for PolicyListState { self.adjust_add_button_enabled(text_box, ctx); } Action::NewEntry(entity) => { - if let Some(text) = self.fetch_text(ctx, entity) { - self.new_entry(text, registry, ctx); + if let Some(name) = self.fetch_text(ctx, entity) { + self.new_entry(name, registry, ctx); } } Action::RemoveEntry(index) => { @@ -169,7 +169,7 @@ impl State for PolicyListState { if let Some(header) = ctx .widget() - .get_mut::("policy_lists") + .get_mut::("policy_list") .get_mut(index) { header.name = text.to_string(); @@ -186,7 +186,7 @@ impl State for PolicyListState { ctx.push_event_by_window(FocusEvent::RemoveFocus(text_box)); } Action::OpenPolicyList(index) => { - self.open_policy_lists(index, ctx); + self.open_policy_list(index, ctx); } } } diff --git a/frontend/src/policylist_view.rs b/frontend/src/policylist_view.rs index 0f20359..714b318 100644 --- a/frontend/src/policylist_view.rs +++ b/frontend/src/policylist_view.rs @@ -10,34 +10,35 @@ use crate::{ //type ListIndex = Option; widget!( - /// Starter page that offers the dialog to enter an identifier of a policy. - /// This identifier is checked agains a map of valid policy codes. + /// Dialog selecting a list of policy identifiers. + /// The lists groups a collection of policy codes. PolicyListView { - policy_lists: PolicyList, - policy_lists_count: usize, - policy_data: u32 + back_entity: u32, + policy_list: PolicyList, + policy_list_count: usize, + policydata_view: u32 } ); impl Template for PolicyListView { fn template(self, id: Entity, ctx: &mut BuildContext) -> Self { - // all items of our policy lists + // collect the DCES elements of our 'policy lists' view let items_widget = ItemsWidget::new() - .id(ID_POLICY_LISTS_ITEMS_WIDGET) + .id(ID_POLICY_LIST_ITEMS_WIDGET) .v_align("start") .items_builder(move |ctx, index| { let mut name = "".to_string(); - //let mut selected = false; - if let Some(policy_lists) = ctx + if let Some(policy_list) = ctx .get_widget(id) - .get::(PROP_POLICY_LISTS) - .get(index) { - name = policy_lists.name.clone(); - } + .get::(PROP_POLICY_LIST) + .get(index) + { + name = policy_list.name.clone(); + } // plus button: open new policy - let helper_button = Button::new() + let new_list_button = Button::new() .min_height(48.0) .class(CLASS_ITEM_BUTTON) .attach(Grid::column(0)) @@ -51,7 +52,7 @@ impl Template for PolicyListView { .build(ctx); let text_block = TextBlock::new() - .foreground(helper_button) + .foreground(new_list_button) .margin((14.0, 0.0, 0.0, 0.0)) .v_align("center") .attach(Grid::column(0)) @@ -63,7 +64,7 @@ impl Template for PolicyListView { .margin((8.0, 0.0, 0.0, 0.0)) .visibility("collapsed") .v_align("center") - .water_mark("Insert name of a new policy list...") + .water_mark("Insert name of a new policy collection ...") .attach(Grid::column(0)) .text(text_block) .on_changed(move |ctx, entity| { @@ -88,10 +89,11 @@ impl Template for PolicyListView { .add(8.0) .build(), ) - .child(helper_button) + .child(new_list_button) .child(text_box) .child(text_block) .child( + // toggle if text_box is focused ToggleButton::new() .selected(("focused", text_box)) .class(CLASS_ICON_ONLY) @@ -107,9 +109,9 @@ impl Template for PolicyListView { .attach(Grid::column(2)) .min_size(32.0, 32.0) .v_align("center") - // todo use remove from icons - // .icon(material_font_icons::DELETE_FONT_ICON) - .icon("") + .icon(material_icons_font_ttf::MD_ADD) + //.icon(material_icons_font_ttf::MD_EDIT) + //.icon("") .on_mouse_down(|_, _| true) .on_click(move |ctx, _| { ctx.get_mut::(id) @@ -124,9 +126,8 @@ impl Template for PolicyListView { .attach(Grid::column(4)) .min_size(32.0, 32.0) .v_align("center") - // todo use Tray icon for action remove - // .icon(material_font_icons::DELETE_FONT_ICON) - .icon("") + .icon(material_icons_font_ttf::MD_DELETE) + //.icon("") .on_mouse_down(|_, _| true) .on_click(move |ctx, _| { ctx.get_mut::(id) @@ -137,12 +138,12 @@ impl Template for PolicyListView { ) .build(ctx) }) - .count((PROP_POLICY_LISTS_COUNT, id)) + .count((PROP_POLICY_LIST_COUNT, id)) .build(ctx); // create new policy list element - let policy_lists_text_box = TextBox::new() - .id(ID_POLICY_LISTS_TEXT_BOX) + let policy_list_text_box = TextBox::new() + .id(ID_POLICY_LIST_TEXT_BOX) .attach(Grid::row(4)) .v_align("center") .margin((4.0, 0.0, 0.0, 2.0)) @@ -162,9 +163,10 @@ impl Template for PolicyListView { .child(items_widget) .build(ctx); - self.name("Policy Lists") - .policy_lists(PolicyList::default()) - .policy_lists_count(0) + // Child page: list available policy lists + self.name("PolicyListView") + .policy_list(PolicyList::default()) + .policy_list_count(0) .child( Grid::new() .rows( @@ -213,7 +215,7 @@ impl Template for PolicyListView { .class(CLASS_HEADER) .v_align("center") .h_align("center") - .text("Lists with policy data collections") + .text("Lists of policy data collections") .build(ctx), ) .build(ctx), @@ -255,10 +257,10 @@ impl Template for PolicyListView { .class(CLASS_TRANSPARENT) .build(ctx), ) - .child(policy_lists_text_box) + .child(policy_list_text_box) .child( Button::new() - .id(ID_POLICY_LISTS_ADD_BUTTON) + .id(ID_POLICY_LIST_ADD_BUTTON) .class(CLASS_ICON_ONLY) .attach(Grid::row(4)) .attach(Grid::column(2)) @@ -266,10 +268,10 @@ impl Template for PolicyListView { .enabled(false) .min_size(32.0, 32.0) .v_align("center") - .icon(material_icons_font::ADD_FONT_ICON) + .icon(material_icons_font_ttf::MD_ADD) .on_click(move |ctx, _| { ctx.get_mut::(id) - .action(Action::NewEntry(policy_lists_text_box)); + .action(Action::NewEntry(policy_list_text_box)); true }) .build(ctx),