From 9b04a790daaf2e34145325603038a8b6ca016dea Mon Sep 17 00:00:00 2001 From: Ralf Zerres Date: Wed, 1 Jul 2020 09:07:00 +0200 Subject: [PATCH 01/17] state update Signed-off-by: Ralf Zerres --- .../src/callbacks/policycheck_state.rs | 188 ++++++++++++++---- advotracker/src/data/keys.rs | 1 + advotracker/src/main.rs | 100 ++++++---- .../src/services/imports/allianzdirectcall.rs | 21 +- advotracker/src/widgets/main_view.rs | 6 +- advotracker/src/widgets/policycheck_view.rs | 85 +++++--- 6 files changed, 299 insertions(+), 102 deletions(-) diff --git a/advotracker/src/callbacks/policycheck_state.rs b/advotracker/src/callbacks/policycheck_state.rs index a17b6b0..8d3d54c 100644 --- a/advotracker/src/callbacks/policycheck_state.rs +++ b/advotracker/src/callbacks/policycheck_state.rs @@ -1,8 +1,17 @@ +use locales::t; +use dotenv::dotenv; use orbtk::prelude::*; +use serde::Deserialize; +use std::{env, process}; +use std::collections::HashMap; +use tracing::{debug, trace}; + +use crate::services::imports::allianzdirectcall::import; +use crate::callbacks::policy_check::is_valid; use crate::{ callbacks::global_state::GlobalState, - //data::structures::{PolicyData, PolicyDataList}, + data::structures::{PolicyCode, PolicyDataList, PolicyData, PolicyList}, data::keys::*, }; @@ -18,14 +27,22 @@ pub enum Action { TextChanged(Entity, usize), } +#[derive(Debug, Deserialize)] +struct Environment { + test_lang: String, + log: String, +} + /// Handles the requests of the `PolicyCheckView`. #[derive(Default, AsAny)] pub struct PolicyCheckState { - action:Option, + action: Option, last_focused: Option, pub text_box: Entity, menu_button: Entity, policy_number_valid: bool, + policy_number_count: usize, + policy_numbers: HashMap, } impl GlobalState for PolicyCheckState {} @@ -36,6 +53,46 @@ impl PolicyCheckState { self.action = action.into(); } + pub fn create_hashmap(&mut self) -> Result<(), Box> { + // WIP: redundant lang selection (already in main!) + let mut lang = env::var("LANG").unwrap_or("en".to_string()); + // testing environment: read from .env file + dotenv().ok(); + match envy::from_env::() { + Ok(environment) => { + if environment.test_lang != lang { lang = environment.test_lang; } + }, + Err(e) => { debug!(target: "advotracker", "{}", e); } + } + + // importing policy code elements from csv-file + let policy_list = PolicyList::new("Allianz Versicherungsnummen-List"); + println!("Policy List {:?} ", policy_list.name); + + let mut policy_data = PolicyDataList::new("Allianz-Import latest"); + println!("Policy Data List {:?} ", policy_data.name); + + let mut policy_numbers : HashMap = HashMap::new(); + + //let mut csv_import_path = v.get::("import_file").unwrap(); + let mut csv_import_path = String::from("POLLFNR_WOECHENTLICH.txt"); + println!("Importing from: {:?}", csv_import_path); + match import(&mut csv_import_path, &mut policy_data, + &mut policy_numbers, &lang) { + Ok(count) => { + self.policy_number_count = count; + println!("Imported {:?} records", self.policy_number_count); + } + Err(err) => { + println!("error running CSV-Import: {}", err); + process::exit(1); + } + }; + + self.policy_numbers = policy_numbers; + Ok(()) + } + /// Clear text in text box. pub fn clear_entry(&mut self, text_box: Entity, ctx: &mut Context) { let mut text_box = TextBox::get(ctx.get_widget(text_box)); @@ -50,27 +107,86 @@ impl PolicyCheckState { println!("Menu text: {}", text); } - fn parse_entry(&self, policy_check_policy_number: Entity, ctx: &mut Context) { - let mut policy_check_policy_number = TextBox::get(ctx.get_widget(policy_check_policy_number)); - let policy_number = policy_check_policy_number.text_mut(); - - println!("parsing policy Number: {}", policy_number); + fn parse_entry(&mut self, policy_check_policy_number: Entity, + ctx: &mut Context) { + let policy_string = ctx.get_widget(policy_check_policy_number).get::("text").as_string(); + let policy_number_length = policy_string.len(); // Parse policy code: "AS-123456789" // DION VERS POLLFNR // 1 AS 1515735810 - let policy_number_length = policy_number.len(); if policy_number_length == 10 { - println!("Verify {} ...", policy_number); - // check against hash-table + // needs to be an integer + match policy_string.parse::() { + Ok(p) => { + trace!(target: "advotracker", policy_number = ?p); + + // WIP: for now, only import once per session + if self.policy_number_count == 0 { + match self.create_hashmap() { + Ok(()) => { + //let res = t!("policy.hashmap.success", lang); + //println!("{:?}", res); + println!("hashmap has: {:?} entries", self.policy_number_count); + } + _ => { + // let res = t!("policy.hashmap.failed", lang); + // println + // !("{:?}", res); + println!("Creation of a hashmap failed!"); + } + } + } else { + println!("Already imported {} records.", self.policy_number_count); + + + } + println!(" ... verify policy Number {:?}", p); + match self.policy_numbers.get(&p) { + // check hashmaps value field + Some(policy_code) => { + //let res = t!("policy.validation.success", lang); + //println!("{:?}", res); + println!("policy_number: {} ({:?})", + p, policy_code); + } + _ => { + //let res = t!("policy.validation.failed", lang); + //println!("{:?}", res); + println!("Nuup! Number isn't valid!"); + } + } + }, + Err(e) => { + println!("invalid: {}", e); + // Feedback + println!("Please enter an integer!"); + } + } + //ctx.get_widget(text_box).set("policy_number_valid", true); //ctx.get_widget(policy_check_policy_number).set("policy_check_result", true); //TextBox::get(ctx.child("policy_check_result")).set_foreground(colors::LINK_WATER_COLOR); } if policy_number_length < 10 { println!("Policy number is to short!"); - //TextBox::get(ctx.child("text_box")).set_foreground("#ffffff"); - //TextBox::get(ctx.child("text_box")).set_background("#5b0f22"); + ctx.child(ID_POLICY_CHECK_POLICY_NUMBER).set("text", String::from("")); + //ctx.child(ID_POLICY_CHECK_RESULT).set("text", String::from("Policy number is to short!")); + // ctx.get_widget(policy_check_policy_number).set("policy_number_valid", true); + //policy_check_view(ctx.widget()) + // .set_policy_check_result(String16::from(format!("Given Number is to small: {}", policy_number_length))); + //let mut text_box = text_box(ctx.get_widget(Entity)); + //let text = text_box.text; + //println!("submitting {}", text); + //text.clear(); + // TextBock: set "visibility", "text" + //policycheck_view(ctx.widget()) + // .list_mut() + // .push(format!("Item {}", len + 1)); + //ctx.child("items").set::("blub", len + 1); + //TextBox::get(ctx.child("policy_check_result")).set_foreground("#ffffff"); + //text_block::get(ctx.child(policy_check_result)).set_background("#5b0f22"); + //policy_check_result(ctx.child("items")).set_count(len + 1); } if policy_number_length > 10 { println!("Policy number is to big!"); @@ -78,26 +194,26 @@ impl PolicyCheckState { //TextBox::get(ctx.child("text_box")).set_background("#5b0f22"); } - // if let policy_number = text_box.text() { - // match policy_number { - // _ => { - // println!("policynumber: {} is valid!", policy_number); - // } - // } - // } + //if let policy_number = policy_check_policy_number.text() { + // match policy_number { + // _ => { + // println!("policynumber: {} is valid!", policy_number); + // } + // } + //} } - /// If TextBox 'policy_check_policy_number' is empty, disable button "check" + /// If TextBox 'policy_check_policy_number' is empty, disable button "clear" /// otherwise enabled it. - fn set_check_button(&self, text_box: Entity, ctx: &mut Context) { - // if ctx.get_widget(text_box).get::("policy_check_policy_number").is_empty() { - // ctx.get_widget(self.policy_check_result).set("enabled", false); - // } else { - // ctx.get_widget(self.policy_check_result).set("enabled", true); - // } + // fn set_check_button(&self, text_box: Entity, ctx: &mut Context) { + // if ctx.get_widget(clear_button).get::("policy_check_policy_number").is_empty() { + // ctx.get_widget(self.policy_check_clear_button).set("enabled", false); + // } else { + // ctx.get_widget(self.policy_check_clear_button).set("enabled", true); + // } - ctx.get_widget(self.text_box).update_theme_by_state(true); - } + // ctx.get_widget(self.text_box).update_theme_by_state(true); + // } /// Change status of given text box to edit mode. fn set_entry(&self, text_box: Entity, ctx: &mut Context) { @@ -122,16 +238,18 @@ impl PolicyCheckState { .length = ctx.get_widget(text_box).get::("policy_number").len(); ctx.push_event_by_window(FocusEvent::RequestFocus(text_box)); } + } 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("PolicyCheckState.init: Can't find child 'Menu button'."); + // self.button = ctx + // .entity_of_child(ID_POLICY_CHECK_MENU_BUTTON) + // .expect("PolicyCheckState.init: Can't find child 'Menu button'."); self.text_box = ctx - .entity_of_child(ID_POLICY_CHECK_POLICY_NUMBER) - .expect("PolicyCheckState.init: Can't find child 'Text Box'."); + .entity_of_child(ID_POLICY_CHECK_POLICY_NUMBER) + .expect("PolicyCheckState.init: Can't find child 'Text Box'."); + } fn update(&mut self, _registry: &mut Registry, ctx: &mut Context) { @@ -150,13 +268,15 @@ impl State for PolicyCheckState { self.clear_entry(text_box, ctx); } Action::InputTextChanged(text_box) => { - self.set_check_button(text_box, ctx); + //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); + //self.parse_entry(text_box, &mut policy_numbers, + // &lang, ctx); } Action::RemoveFocus(text_box) => { ctx.get_widget(text_box).set("enabled", false); diff --git a/advotracker/src/data/keys.rs b/advotracker/src/data/keys.rs index cc10967..b4fb0ea 100644 --- a/advotracker/src/data/keys.rs +++ b/advotracker/src/data/keys.rs @@ -18,6 +18,7 @@ pub static CLASS_SEPERATOR: &str = "seperator"; 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_CLEAR_BUTTON: &str = "policy_check_clear_button"; pub static ID_POLICY_CHECK_MENU_BUTTON: &str = "policy_check_menu_button"; 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"; diff --git a/advotracker/src/main.rs b/advotracker/src/main.rs index 5fa5d16..93704ce 100644 --- a/advotracker/src/main.rs +++ b/advotracker/src/main.rs @@ -5,13 +5,16 @@ * SPDX-License-Identifier: (0BSD or MIT) */ +#[macro_use] +extern crate lazy_static; + //use chrono::{Local, DateTime}; use locales::t; //use serde::{Deserialize, Serialize}; use serde::Deserialize; use std::{env, process}; //use std::{error::Error, process}; -use std::collections::HashMap; +//use std::collections::HashMap; use tracing::{debug, trace, Level}; use orbtk::prelude::*; @@ -33,7 +36,8 @@ struct Environment { } //#[cfg(feature = "light-theme")] -static STYLESHEET: &'static str = include_str!("../resources/stylesheets/advotracker.css"); +//static STYLESHEET: &'static str = include_str!("../resources/stylesheets/advotracker.css"); +static STYLESHEET: &'static str = include_str!("../resources/stylesheets/policyholder-check.css"); fn get_theme() -> ThemeValue { //ThemeValue::create_from_css(LIGHT_THEME_EXTENSION_CSS) @@ -81,7 +85,7 @@ fn main() -> Result<(), Box> { Ok(environment) => { if environment.test_lang != lang { lang = environment.test_lang; } }, - Err(e) => { debug!(target: "csv-test", "{}", e); } + Err(e) => { debug!(target: "advotracker", "{}", e); } } // how to handle unumplemented lang resources?? res = t!("parse.environment", lang); @@ -90,46 +94,60 @@ fn main() -> Result<(), Box> { trace!(target: "csv-test", message = ?res, state = ?state); // initialize viperus structure - let mut v = Viperus::new(); + let mut viperus = Viperus::new(); + + // lazy_static! { + // static ref VIPERUS: Viperus + 'static = { let mut viperus = Viperus::new(); }; + // static ref VIPERUS_COUNT: usize = VIPERUS.len(); + // } + // lazy_static! { + // static ref HASHMAP: HashMap = { + // let mut policy_numbers = HashMap::new(); + // policy_numbers + // } + // static ref COUNT: usize = HASHMAP.len(); + // println!("The map has {} entries.", *COUNT); + // } // parse commandline arguments res = t!("parse.arguments", lang); state = t!("state.started", lang); trace!(target: "csv-test", process = ?res, state = ?state); - let _ = parse_args(&mut v); + let _ = parse_args(&mut viperus); state = t!("state.finished", lang); trace!(target: "csv-test", process = ?res, state = ?state); - //trace!(target: "Viperus", "Config results: {:?}", v); + //trace!(target: "Viperus", "Count of Config parameters: {:?}", VIPERUS_COUNT); // main tasks res = t!("main.started", lang); state = t!("state.started", lang); trace!(target: "csv-test", process = ?res, state = ?state); - // importing policy code elements from csv-file - let policy_list = PolicyList::new("Allianz Versicherungsnummen-List"); - println!("Policy List {:?} ", policy_list.name); + // moved to callback: checkview_state.rs + // // importing policy code elements from csv-file + // let policy_list = PolicyList::new("Allianz Versicherungsnummen-List"); + // println!("Policy List {:?} ", policy_list.name); - let mut policy_data = PolicyDataList::new("Allianz-Import 20200628"); - println!("Policy Data List {:?} ", policy_data.name); + // let mut policy_data = PolicyDataList::new("Allianz-Import 20200628"); + // println!("Policy Data List {:?} ", policy_data.name); - let mut policy_numbers : HashMap = HashMap::new(); + // let mut policy_numbers : HashMap = HashMap::new(); - let mut csv_import_path = v.get::("import_file").unwrap(); - match import(&mut csv_import_path, &mut policy_data, - &mut policy_numbers, &lang) { - Ok(count) => { - println!("Imported {:?} records", count); - } - Err(err) => { - println!("error running Csv-Test: {}", err); - process::exit(1); - } - } + // let mut csv_import_path = viperus.get::("import_file").unwrap(); + // match import(&mut csv_import_path, &mut policy_data, + // &mut policy_numbers, &lang) { + // Ok(count) => { + // println!("Imported {:?} records", count); + // } + // Err(err) => { + // println!("error running Csv-Test: {}", err); + // process::exit(1); + // } + //} // // test if policy_number is_valid - // let test_policy_number = v.get::("test_policy_number").unwrap() as usize; + // let test_policy_number = VIPERUS.get::("test_policy_number").unwrap() as usize; // trace!(target: "csv-test", test_policy_number = ?test_policy_number); // match policy_numbers.get(&test_policy_number) { // Some(&policy_code) => { @@ -146,28 +164,30 @@ fn main() -> Result<(), Box> { //} + + Application::from_name("rzerres.advotracker") + .window(move |ctx| { + Window::new() + //.title("OrbTk - Policyholder checker") + .title("AdvoTracker - Versicherungsnummern") + .position((500.0, 100.0)) + .size(580.0, 320.0) + .min_width(460.0) + .min_height(180.0) + .resizeable(true) + .theme(get_theme()) + .child(main_view::MainView::new().build(ctx)) + .build(ctx) + }) + .run(); + state = t!("state.finished", lang); res = t!("main.finished", lang); trace!(target: "csv-test", process = ?res, state = ?state); }); - 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(); - Ok(()) + } #[cfg(test)] diff --git a/advotracker/src/services/imports/allianzdirectcall.rs b/advotracker/src/services/imports/allianzdirectcall.rs index 2605c2d..0cefd3a 100644 --- a/advotracker/src/services/imports/allianzdirectcall.rs +++ b/advotracker/src/services/imports/allianzdirectcall.rs @@ -67,7 +67,7 @@ pub fn import(p: &mut String, data_list: &mut PolicyDataList, // error here. let record: PolicyData = result?; //let record: data::AllianzPolicyNumber = result?; - //println!("{:?}", record); + println!("{:?}", record); // WIP: write to redis backend // append the policy_number to the HashMap @@ -84,6 +84,25 @@ pub fn import(p: &mut String, data_list: &mut PolicyDataList, trace!(target: "advotrackerd", record_count = ?count, duration = ?duration); + // Tests + // Takes a reference and returns Option<&V> + let test_policy_number : usize = 1511111111; + match data_list.get(test_policy_number) { + Some(policy_code) => { + println!("Policy-Number {:?} {:?}", + test_policy_number, policy_code); + }, + _ => println!("1. No number found!"), + } + + let test_policy_number_2 : usize = 9999999991; + match data_list.get(test_policy_number_2) { + Some(policy_code) => { println!("Policy-Number: {:?} {:?}", + test_policy_number, policy_code); + }, + _ => println!("2. No number found!"), + } + state = t!("state.finished", lang); res = t!("csv.import.finished", lang); trace!(target: "advotrackerd", process = ?res, state = ?state, date_stop = ?dt_end.to_string()); diff --git a/advotracker/src/widgets/main_view.rs b/advotracker/src/widgets/main_view.rs index 678e96c..d8f5d22 100644 --- a/advotracker/src/widgets/main_view.rs +++ b/advotracker/src/widgets/main_view.rs @@ -11,17 +11,19 @@ use crate::data::structures::PolicyCheck; use crate::widgets::policycheck_view::PolicyCheckView; widget!(MainView { - // policy_list_count: usize, // policy_list: PolicyList, // policy_data_list: PolicyDataList, // policylist_view: u32, // policydata_view: u32, + // policydata_view: u32, + policy_number_count: usize, policycheck_view: u32 }); impl Template for MainView { fn template(self, id: Entity, ctx: &mut BuildContext) -> Self { let policycheck_view = PolicyCheckView::new() + //.policy_number_count(0) //.policylist_view(id) .build(ctx); @@ -39,7 +41,7 @@ impl Template for MainView { // .build(ctx); self.name("MainView") - //.policy_list_count(0) + .policy_number_count(0) //.policycheck_view(PolicyCheck::default()) // //.policycheck_view(0) // .policydata_view(policydata_view.0) diff --git a/advotracker/src/widgets/policycheck_view.rs b/advotracker/src/widgets/policycheck_view.rs index e62c94c..ccc1e91 100644 --- a/advotracker/src/widgets/policycheck_view.rs +++ b/advotracker/src/widgets/policycheck_view.rs @@ -20,10 +20,10 @@ widget!( PolicyCheckView { policy_check: PolicyCheck, //policy_check_list: PolicyCheckList, - policy_check_title: String, - policy_check_number: String, + policy_check_title: String16, + policy_check_number: String16, policy_check_number_valid: bool, - policy_check_text_box: String, + policy_check_result: String16, policy_data_count: u32, //policylist_view: u32, title: String @@ -132,22 +132,23 @@ impl Template for PolicyCheckView { .child( Grid::new() .id(ID_POLICY_CHECK_WIDGET) - //.v_align("start") - //.h_align("center") .background("#fafafa") .columns( Columns::new() - .add(64.0) + .add(84.0) .add("*") .add(50.0) .build(), ) .rows( Rows::new() + // Top Bar .add("auto") .add(1.0) + // Content .add("*") .add(1.0) + // Bottom Bar .add(52.0) /* .add("auto") */ .build(), @@ -195,35 +196,40 @@ impl Template for PolicyCheckView { .attach(Grid::row(2)) .attach(Grid::column(0)) .attach(Grid::column_span(3)) + .margin((16.0, 26.0, 26.0, 16.0)) .child( Grid::new() .id(ID_POLICY_CHECK_FORM) .columns( Columns::new() - .add("5.0") + // Labels .add("220.0") - .add("5.0") + // Seperator + .add("16.0") + // Values .add("100.0") .build(), ) .rows( Rows::new() - .add("45.0") - .add("45.0") + .add("64.0") + .add("64.0") .build(), ) .child( + // Labels Stack::new() - .attach(Grid::column(1)) + .attach(Grid::column(0)) .attach(Grid::row(0)) - .margin((16.0, 16.0, 16.0, 16.0)) .orientation("vertical") //.v_align("center") .child( TextBlock::new() .id(ID_POLICY_CHECK_LABEL_POLICY_NUMBER) //.class(CLASS_TEXT_BLOCK) + .margin((0.0, 0.0, 16.0, 16.0)) .h_align("end") + .v_align("center") .min_width(250.0) .min_height(45.0) //.size(250.0, 45.0) @@ -234,24 +240,27 @@ impl Template for PolicyCheckView { TextBlock::new() .id(ID_POLICY_CHECK_LABEL_RESULT) //.class(CLASS_TEXT_BLOCK) - .attach(Grid::column(1)) + .attach(Grid::column(0)) .attach(Grid::row(1)) + .margin((0.0, 0.0, 16.0, 0.0)) .h_align("end") + .v_align("center") .min_width(250.0) - //.min_size(120.0, 180.0) - .text("Ergebnis:") - .text("Result:") + //.min_size(120.0, 180.0) + //.text("Ergebnis:") + //.text("Result:") .build(ctx), ) .build(ctx) ) .child( + // Values Stack::new() - .attach(Grid::column(2)) + .attach(Grid::column(1)) .attach(Grid::row(0)) //.attach(Grid::column_span(3)) .orientation("vertical") - .margin((16.0, 16.0, 16.0, 16.0)) + //.margin((16.0, 16.0, 16.0, 16.0)) //.child(policy_check_text_box) .child( TextBox::new() @@ -259,26 +268,57 @@ impl Template for PolicyCheckView { .h_align("start") .width(250.0) .min_width(200.0) - .margin((4.0, 0.0, 0.0, 0.0)) + .margin((0.0, 0.0, 0.0, 16.0)) .lost_focus_on_activation(false) .water_mark("10-stellige Nummer (ohne 'AS')") .text("") .on_activate(move |ctx, entity| { + // Entity is entered/activated via Mouse/Keyboard ctx.get_mut::(id) .action(Action::ParseEntry(entity)); }) .on_changed(move |ctx, entity| { + // Element value has changed ctx.get_mut::(id) .action(Action::InputTextChanged(entity)); }) .build(ctx), ) + //.icon(material_icons_font_ttf::MD_ADD_CIRCLE) + // .child() + // NumericBox::new() + // .id(ID_POLICY_CHECK_POLICY_NUMBER) + // .h_align("start") + // .width(250.0) + // .min(1000000000) + // .max(9999999999) + // .val(0) + // .min_width(200.0) + // .margin((0.0, 0.0, 0.0, 16.0)) + // //.lost_focus_on_activation(false) + // //.water_mark("10-stellige Nummer (ohne 'AS')") + // //.text("") + // //.on_activate(move |ctx, entity| { + // // ctx.get_mut::(id) + // // .action(Action::ParseEntry(entity)); + // //}) + // // .on_changed(move |ctx, entity| { + // // ctx.get_mut::(id) + // // .action(Action::InputTextChanged(entity)); + // // }) + // // .on_update(move |ctx, entity| { + // // ctx.get_mut::(id) + // // .action(Action::InputTextChanged(entity)); + // // }) + // .build(ctx), + //) .child( TextBlock::new() .id(ID_POLICY_CHECK_RESULT) .h_align("start") - .attach(Grid::column(3)) + .attach(Grid::column(1)) .attach(Grid::row(1)) + .text(("")) //.margin((4.0, 0.0, 0.0, 0.0)) //.lost_focus_on_activation(false) // .on_activate(move |ctx, entity| { @@ -341,16 +381,11 @@ impl Template for PolicyCheckView { .build(ctx), ) .build(ctx), - //ctx.append_child_to_overlay(policycheck_menu_text_block).unwrap() - ) .build(ctx), - ) .build(ctx), - ) - } } From 8f6655d96cedc3871ade9a2dc32df4663ad03d25 Mon Sep 17 00:00:00 2001 From: Ralf Zerres Date: Thu, 2 Jul 2020 07:08:05 +0200 Subject: [PATCH 02/17] Cargo.toml: preset the default binary * use the GUI variant 'advotracker' as the default binary Signed-off-by: Ralf Zerres --- advotracker/Cargo.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/advotracker/Cargo.toml b/advotracker/Cargo.toml index e906a14..1ec96e6 100644 --- a/advotracker/Cargo.toml +++ b/advotracker/Cargo.toml @@ -6,6 +6,7 @@ description = "Frontend component that supports lawyers to capture relevant data readme = "README.md" license = "(0BSD OR MIT)" edition = "2018" +default-run = "advotracker" [target.'cfg(windows)'.dependencies] winapi = { version = "0.3", features = ["winuser"] } From 31b45ab690cfef7ab75079aed925a892e5fe5ab7 Mon Sep 17 00:00:00 2001 From: Ralf Zerres Date: Thu, 2 Jul 2020 07:10:24 +0200 Subject: [PATCH 03/17] Cargo.toml: rebase root of local orbtk sources Signed-off-by: Ralf Zerres --- advotracker/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/advotracker/Cargo.toml b/advotracker/Cargo.toml index 1ec96e6..4f5ead6 100644 --- a/advotracker/Cargo.toml +++ b/advotracker/Cargo.toml @@ -24,7 +24,7 @@ log = { version = "~0.4.8" } locales = { version = "~0.1" } #orbtk = { version = "~0.3.1-alpha3" } #orbtk = { git = "https://github.com/redox-os/orbtk.git", branch = "develop" } -orbtk = { path = "../../redox-os/orbtk" } +orbtk = { path = "../../orbtk" } serde = { version = "~1.0", features = ["derive"] } #tokio = { version = "~0.2", features = ["macros", "rt-threaded", "stream", "time"] } tracing = { version = "~0.1" } From 8d7d5176d90a4a5cb3afb30a9accb16bc97bf738 Mon Sep 17 00:00:00 2001 From: Ralf Zerres Date: Thu, 2 Jul 2020 07:23:23 +0200 Subject: [PATCH 04/17] examples: advowidgets: update to new api syntax * when addressing widgets properties the new api syntax seems more natural. It accesses the properties via a function oriented notation: - view_name(_mut() - ctx.child("").set::("", ) - (ctx.child(() Signed-off-by: Ralf Zerres --- advotracker/examples/advowidgets.rs | 138 ++++++++++++++-------------- 1 file changed, 69 insertions(+), 69 deletions(-) diff --git a/advotracker/examples/advowidgets.rs b/advotracker/examples/advowidgets.rs index 5c4e80f..350184e 100644 --- a/advotracker/examples/advowidgets.rs +++ b/advotracker/examples/advowidgets.rs @@ -35,60 +35,58 @@ impl State for MainViewState { if let Some(action) = self.action { match action { Action::AddItem => { - let len = ctx.widget().get::("list").len(); + let len = main_view(ctx.widget()).list().len(); + if len < 5 { - ctx.widget() - .get_mut::("list") + main_view(ctx.widget()) + .list_mut() .push(format!("Item {}", len + 1)); - ctx.child("items").set("count", len + 1); - ctx.child("remove-item-button").set("enabled", true); + ctx.child("items").set::("blub", len + 1); + items_widget(ctx.child("items")).set_count(len + 1); + button(ctx.child("remove-item-button")).set_enabled(true); if len == 4 { - ctx.child("add-item-button").set("enabled", false); + button(ctx.child("add-item-button")).set_enabled(false); } } } Action::RemoveItem => { - let len = ctx.widget().get::("list").len(); + let len = main_view(ctx.widget()).list().len(); if len > 0 { - ctx.widget().get_mut::("list").remove(len - 1); - ctx.child("items").set("count", len - 1); - ctx.child("add-item-button").set("enabled", true); + main_view(ctx.widget()).list_mut().remove(len - 1); + items_widget(ctx.child("items")).set_count(len - 1); + button(ctx.child("add-item-button")).set_enabled(true); if len == 1 { - ctx.child("remove-item-button").set("enabled", false); + button(ctx.child("remove-item-button")).set_enabled(false); } } } Action::IncrementCounter => { - *ctx.widget().get_mut::("counter") += 1; + *main_view(ctx.widget()).counter_mut() += 1; - let counter = *ctx.widget().get::("counter"); + let counter = *main_view(ctx.widget()).counter(); - ctx.widget().set( - "result", - String16::from(format!("Button count: {}", counter)), - ); + main_view(ctx.widget()) + .set_result(String16::from(format!("Button count: {}", counter))); } Action::ClearText => { - ctx.widget().set("text_one", String16::from("")); - ctx.widget().set("text_two", String16::from("")); + main_view(ctx.widget()).set_text_one(String16::default()); + main_view(ctx.widget()).set_text_two(String16::default()); } Action::EntryActivated(entity) => { - let mut widget = ctx.get_widget(entity); - let text = widget.get_mut::("text"); + let mut text_box = text_box(ctx.get_widget(entity)); + let text = text_box.text_mut(); println!("submitting {}", text); text.clear(); } Action::EntryChanged(entity) => { - let widget = ctx.get_widget(entity); - let text = widget.get::("text"); - println!("entry changed: {}", text); + println!("entry changed: {}", text_box(ctx.get_widget(entity)).text()); } Action::ValueChanged(entity) => { - let val = - ((*ctx.get_widget(entity).get::("val")).floor() as i32).to_string(); - ctx.child("value_text").set("text", String16::from(val)); + let val = ((slider(ctx.get_widget(entity)).val()).floor() as i32).to_string(); + + text_block(ctx.child("value_text")).set_text(String16::from(val)); } } @@ -99,12 +97,11 @@ impl State for MainViewState { fn update_post_layout(&mut self, _: &mut Registry, ctx: &mut Context<'_>) { let mut selection_string = "Selected:".to_string(); - for index in &ctx.widget().get::("selected_indices").0 { + for index in &main_view(ctx.widget()).selected_indices().0 { selection_string = format!("{} {}", selection_string, index); } - ctx.child("selection") - .set("text", String16::from(selection_string)); + text_block(ctx.child("selection")).set_text(selection_string); } } @@ -174,14 +171,14 @@ impl Template for MainView { .combo_box_list_count(10) .child( Grid::new() - .margin(8.0) + .margin(8.) .columns( Columns::new() - .add(132.0) - .add(16.0) - .add(132.0) - .add(16.0) - .add(132.0), + .add(132.) + .add(16.) + .add(132.) + .add(16.) + .add(132.), ) .child( Stack::new() @@ -191,8 +188,8 @@ impl Template for MainView { .child( Button::new() .text("Button") - .margin((0.0, 8.0, 0.0, 0.0)) - .icon(material_font_icons::CHECK_FONT_ICON) + .margin((0., 8., 0., 0.)) + .icon(material_icons_font_ttf::MD_CHECK) .attach(Grid::column(0)) .attach(Grid::row(1)) .on_click(move |states, _| { @@ -206,8 +203,8 @@ impl Template for MainView { .text("Primary") .element("button") .class("primary") - .margin((0.0, 8.0, 0.0, 0.0)) - .icon(material_font_icons::CHECK_FONT_ICON) + .margin((0., 8., 0., 0.)) + .icon(material_icons_font_ttf::MD_360) .attach(Grid::column(0)) .attach(Grid::row(2)) .build(ctx), @@ -216,7 +213,8 @@ impl Template for MainView { ToggleButton::new() .class("single_content") .text("ToggleButton") - .margin((0.0, 8.0, 0.0, 0.0)) + .margin((0., 8., 2., 0.)) + .icon(material_icons_font_ttf::MD_ALARM_ON) .attach(Grid::column(0)) .attach(Grid::row(3)) .build(ctx), @@ -224,21 +222,21 @@ impl Template for MainView { .child( CheckBox::new() .text("CheckBox") - .margin((0.0, 8.0, 0.0, 0.0)) + .margin((0., 8., 0., 0.)) .attach(Grid::column(0)) .attach(Grid::row(4)) .build(ctx), ) .child( Switch::new() - .margin((0.0, 8.0, 0.0, 0.0)) + .margin((0., 8., 0., 0.)) .attach(Grid::column(0)) .attach(Grid::row(5)) .build(ctx), ) .child( TextBlock::new() - .margin((0.0, 8.0, 0.0, 0.0)) + .margin((0., 8., 0., 0.)) .element("h1") .id("value_text") .text("0") @@ -262,7 +260,7 @@ impl Template for MainView { TextBlock::new() .class("body") .text(("result", id)) - .margin((0.0, 8.0, 0.0, 0.0)) + .margin((0., 8., 0., 0.)) .attach(Grid::column(2)) .attach(Grid::row(1)) .build(ctx), @@ -271,7 +269,7 @@ impl Template for MainView { TextBox::new() .water_mark("TextBox...") .text(("text_one", id)) - .margin((0.0, 8.0, 0.0, 0.0)) + .margin((0., 8., 0., 0.)) .attach(Grid::column(2)) .attach(Grid::row(2)) .on_activate(move |states, entity| { @@ -286,7 +284,7 @@ impl Template for MainView { TextBox::new() .water_mark("TextBox...") .text(("text_two", id)) - .margin((0.0, 8.0, 0.0, 0.0)) + .margin((0., 8., 0., 0.)) .attach(Grid::column(2)) .attach(Grid::row(2)) .on_activate(move |states, entity| { @@ -299,8 +297,10 @@ impl Template for MainView { ) .child( Button::new() - .margin((0.0, 8.0, 0.0, 0.0)) + .margin((0., 8., 0., 0.)) .class("single_content") + .margin((0., 8., 8., 0.)) + .icon(material_icons_font_ttf::MD_CLEAR) .text("clear text") .on_click(move |states, _| { state(id, states).action(Action::ClearText); @@ -310,8 +310,8 @@ impl Template for MainView { ) .child( NumericBox::new() - .margin((0.0, 8.0, 0.0, 0.0)) - .max(123.0) + .margin((-0., 8., 0., 0.)) + .max(123.) .step(0.123) .val(0.123) .build(ctx), @@ -323,14 +323,14 @@ impl Template for MainView { .rows( Rows::new() .add("auto") - .add(32.0) - .add(16.0) - .add(204.0) + .add(32.) + .add(16.) + .add(204.) .add("auto") - .add(192.0) + .add(192.) .add("auto"), ) - .columns(Columns::new().add("*").add(4.0).add("*")) + .columns(Columns::new().add("*").add(4.).add("*")) .attach(Grid::column(4)) .child( TextBlock::new() @@ -350,7 +350,7 @@ impl Template for MainView { .get::>("combo_box_list")[index] .clone(); TextBlock::new() - .margin((0.0, 0.0, 0.0, 2.0)) + .margin((0., 0., 0., 2.)) .v_align("center") .text(text) .build(bc) @@ -359,7 +359,7 @@ impl Template for MainView { .attach(Grid::column(0)) .attach(Grid::column_span(3)) .attach(Grid::row(1)) - .margin((0.0, 8.0, 0.0, 0.0)) + .margin((0., 8., 0., 0.)) .count(("combo_box_list_count", id)) .build(ctx), ) @@ -367,18 +367,18 @@ impl Template for MainView { ItemsWidget::new() .element("items-widget") .id("items") - .padding((4.0, 4.0, 4.0, 2.0)) + .padding((4., 4., 4., 2.)) .attach(Grid::column(0)) .attach(Grid::column_span(3)) .attach(Grid::row(3)) - .margin((0.0, 0.0, 0.0, 8.0)) + .margin((0., 0., 0., 8.)) .items_builder(move |bc, index| { let text = bc.get_widget(id).get::>("list") [index] .clone(); Button::new() - .margin((0.0, 0.0, 0.0, 2.0)) + .margin((0., 0., 0., 2.)) .text(text) .build(bc) }) @@ -390,12 +390,12 @@ impl Template for MainView { .element("button") .class("single_content") .id("remove-item-button") - .icon(material_font_icons::MINUS_FONT_ICON) + .icon(material_icons_font_ttf::MD_REMOVE_CIRCLE) .on_click(move |states, _| { state(id, states).action(Action::RemoveItem); true }) - .min_width(0.0) + .min_width(0.) .attach(Grid::column(0)) .attach(Grid::row(4)) .build(ctx), @@ -405,12 +405,12 @@ impl Template for MainView { .element("button") .class("single_content") .id("add-item-button") - .icon(material_font_icons::ADD_FONT_ICON) + .icon(material_icons_font_ttf::MD_ADD_CIRCLE) .on_click(move |states, _| { state(id, states).action(Action::AddItem); true }) - .min_width(0.0) + .min_width(0.) .attach(Grid::column(2)) .attach(Grid::row(4)) .build(ctx), @@ -421,14 +421,14 @@ impl Template for MainView { .attach(Grid::column_span(3)) .attach(Grid::row(5)) .selected_indices(id) - .margin((0.0, 16.0, 0.0, 8.0)) + .margin((0., 16., 0., 8.)) .items_builder(move |bc, index| { let text = bc .get_widget(id) .get::>("selection_list")[index] .clone(); TextBlock::new() - .margin((0.0, 0.0, 0.0, 2.0)) + .margin((0., 0., 0., 2.)) .v_align("center") .text(text) .build(bc) @@ -441,7 +441,7 @@ impl Template for MainView { TextBlock::new() .element("text-block") .id("selection") - .max_width(120.0) + .max_width(120.) .attach(Grid::column(0)) .attach(Grid::column_span(3)) .attach(Grid::row(6)) @@ -463,8 +463,8 @@ fn main() { .window(|ctx| { Window::new() .title("OrbTk - widgets example") - .position((100.0, 100.0)) - .size(468.0, 730.0) + .position((100., 100.)) + .size(468., 730.) .resizeable(true) .child(MainView::new().build(ctx)) .build(ctx) From b76090d846fcfa40b833c0cd574328837bc59766 Mon Sep 17 00:00:00 2001 From: Ralf Zerres Date: Thu, 2 Jul 2020 08:39:15 +0200 Subject: [PATCH 05/17] policycheck_view: adapt width of policy number text_box Signed-off-by: Ralf Zerres --- advotracker/src/widgets/policycheck_view.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/advotracker/src/widgets/policycheck_view.rs b/advotracker/src/widgets/policycheck_view.rs index ccc1e91..5f7e360 100644 --- a/advotracker/src/widgets/policycheck_view.rs +++ b/advotracker/src/widgets/policycheck_view.rs @@ -266,7 +266,7 @@ impl Template for PolicyCheckView { TextBox::new() .id(ID_POLICY_CHECK_POLICY_NUMBER) .h_align("start") - .width(250.0) + .width(280.0) .min_width(200.0) .margin((0.0, 0.0, 0.0, 16.0)) .lost_focus_on_activation(false) @@ -314,7 +314,8 @@ impl Template for PolicyCheckView { //) .child( TextBlock::new() - .id(ID_POLICY_CHECK_RESULT) + //.id(ID_POLICY_CHECK_RESULT) + .id("policy_check_result") .h_align("start") .attach(Grid::column(1)) .attach(Grid::row(1)) From 41464c9346b89e318664ec96db3aa6a66af742e2 Mon Sep 17 00:00:00 2001 From: Ralf Zerres Date: Fri, 3 Jul 2020 00:48:10 +0200 Subject: [PATCH 06/17] Cargo.toml: identifier change * use 'nwx' as company prefix Signed-off-by: Ralf Zerres --- advotracker/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/advotracker/Cargo.toml b/advotracker/Cargo.toml index 4f5ead6..0e4d930 100644 --- a/advotracker/Cargo.toml +++ b/advotracker/Cargo.toml @@ -38,6 +38,6 @@ testing = ["orbtk/debug"] [package.metadata.bundle] name = "advotracker" -identifier = "rzerres.advotracker" +identifier = "nwx.advotracker" short_description = "Online legal advice helper." description = "Supports lawyers to capture relevant data encountered during an online legal advice.\n" From e949ae61eb9a7f066cb0583e3550987b766d8bba Mon Sep 17 00:00:00 2001 From: Ralf Zerres Date: Fri, 3 Jul 2020 00:54:06 +0200 Subject: [PATCH 07/17] locales: remove redundant allianzdirectcal Signed-off-by: Ralf Zerres --- .../src/locales/allianzdirectcall.json | 37 ------------------- 1 file changed, 37 deletions(-) delete mode 100644 advotracker/src/locales/allianzdirectcall.json diff --git a/advotracker/src/locales/allianzdirectcall.json b/advotracker/src/locales/allianzdirectcall.json deleted file mode 100644 index 8814eb9..0000000 --- a/advotracker/src/locales/allianzdirectcall.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "err.lang.not_found": { - "de_DE.UTF-8": "Konnte die Umgebungsvarialbe LANG nicht auslesen", - "de": "Konnte die Umgebungsvarialbe LANG nicht auslesen", - "en": "Couldn't read LANG" - }, - "csv_import.started": { - "de_DE.UTF-8": "importieren von einer csv-datei gestartet", - "de": "importieren von einer csv-datei gestartet", - "en": "import from a csv-file started" - }, - "csv_import.finished": { - "de_DE.UTF-8": "importieren von einer csv-datei beendet", - "de": "importieren von einer csv-datei beendet", - "en": "import from a csv-file finished" - }, - "csv_export.started": { - "de_DE.UTF-8": "exportieren in eine csv-datei gestartet", - "de": "exportieren in eine csv-datei gestartet", - "en": "export to csv-file started" - }, - "csv_export.finished": { - "de_DE.UTF-8": "exportieren in eine csv-datei beendet", - "de": "exportieren in eine csv-datei beendet", - "en": "export to csv-file finished" - }, - "state.started": { - "de_DE.UTF-8": "gestartet", - "de": "gestartet", - "en": "started" - }, - "state.finished": { - "de_DE.UTF-8": "beendet", - "de": "beended", - "en": "finished" - } -} From caec9e4d6854e69ad38369299f199026e3d0823f Mon Sep 17 00:00:00 2001 From: Ralf Zerres Date: Fri, 3 Jul 2020 00:55:41 +0200 Subject: [PATCH 08/17] data: keys: cleanup DCES id's and properties Signed-off-by: Ralf Zerres --- advotracker/src/data/keys.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/advotracker/src/data/keys.rs b/advotracker/src/data/keys.rs index b4fb0ea..f81a8bf 100644 --- a/advotracker/src/data/keys.rs +++ b/advotracker/src/data/keys.rs @@ -17,17 +17,18 @@ pub static CLASS_SEPERATOR: &str = "seperator"; // 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_ITEMS_WIDGET: &str = "policy_check_items_widget"; pub static ID_POLICY_CHECK_CLEAR_BUTTON: &str = "policy_check_clear_button"; pub static ID_POLICY_CHECK_MENU_BUTTON: &str = "policy_check_menu_button"; 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_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_RESULT: &str = "policy_check_result"; 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_COUNT_BLOCK: &str = "policy_data_count_block"; 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_DATA_DATE_INSERTED: &str = "policy_data_date_inserted"; @@ -42,8 +43,8 @@ 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_ADVOTRACKER: &str = "advotracker"; pub static PROP_POLICY_CHECK: &str = "policy_check"; -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"; From 8ec566b78a5bf907b4ef2fbf818c6ee5cfcbb0a9 Mon Sep 17 00:00:00 2001 From: Ralf Zerres Date: Fri, 3 Jul 2020 00:57:34 +0200 Subject: [PATCH 09/17] structures: orbtk includes * make structures accessible for orbtk * ducumentation update Signed-off-by: Ralf Zerres --- advotracker/src/data/structures.rs | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/advotracker/src/data/structures.rs b/advotracker/src/data/structures.rs index fb537ad..f237ea4 100644 --- a/advotracker/src/data/structures.rs +++ b/advotracker/src/data/structures.rs @@ -6,6 +6,7 @@ */ use chrono::NaiveDateTime; +use orbtk::prelude::*; use serde::{Deserialize, Serialize}; /// An enumeration of valid policy codes. @@ -144,10 +145,14 @@ pub struct HarmType { pub struct PolicyCheck { /// Versicherungsschein-Prüfnummer pub policy_check_number: String, + /// Referenz zum Versicherungsschein-Typ + pub dion: u8, + /// Referenz zum Versicherungsschein-Typ + pub policy_code: PolicyCode, /// Referenz zur Versicherungsschein-Nummer - pub policy_number: String, + pub policy_number: usize, /// Validitätsergebnis - pub policy_number_valid: bool + pub policy_number_status: Status } impl PolicyCheck { @@ -335,3 +340,7 @@ pub struct AllianzPolicyNumber { // pub struct AllianzPolicyNumberList { // records: Vec // } + +into_property_source!(PolicyCheck); +into_property_source!(PolicyDataList); +into_property_source!(PolicyList); From 7f58ecb96c00504956303f73bed05fddf2a4393d Mon Sep 17 00:00:00 2001 From: Ralf Zerres Date: Fri, 3 Jul 2020 00:58:35 +0200 Subject: [PATCH 10/17] imports: allianzdirectcall: use array to verify on startup * using test dataset Signed-off-by: Ralf Zerres --- .../src/services/imports/allianzdirectcall.rs | 34 ++++++++----------- 1 file changed, 15 insertions(+), 19 deletions(-) diff --git a/advotracker/src/services/imports/allianzdirectcall.rs b/advotracker/src/services/imports/allianzdirectcall.rs index 0cefd3a..b2d2572 100644 --- a/advotracker/src/services/imports/allianzdirectcall.rs +++ b/advotracker/src/services/imports/allianzdirectcall.rs @@ -47,7 +47,7 @@ pub fn import(p: &mut String, data_list: &mut PolicyDataList, let file = File::open(path)?; trace!(target: "advotrackerd", extension = ?extension, file = ?file); - // Build the CSV reader and iterate over each record. + // Build the CSV reader let mut csv_reader = csv::ReaderBuilder::new() .has_headers(true) .delimiter(b' ') @@ -60,14 +60,15 @@ pub fn import(p: &mut String, data_list: &mut PolicyDataList, trace!(target: "advotrackerd", header = ?headers); } - //for result in csv_reader.records() { + // Iterate over each record, deserialize und write to our structures let mut count = 0; for result in csv_reader.deserialize() { // The iterator yields Result, so we check the // error here. let record: PolicyData = result?; - //let record: data::AllianzPolicyNumber = result?; - println!("{:?}", record); + //if verbose > 3 { + // println!("{:?}", record); + //} // WIP: write to redis backend // append the policy_number to the HashMap @@ -86,21 +87,16 @@ pub fn import(p: &mut String, data_list: &mut PolicyDataList, // Tests // Takes a reference and returns Option<&V> - let test_policy_number : usize = 1511111111; - match data_list.get(test_policy_number) { - Some(policy_code) => { - println!("Policy-Number {:?} {:?}", - test_policy_number, policy_code); - }, - _ => println!("1. No number found!"), - } - - let test_policy_number_2 : usize = 9999999991; - match data_list.get(test_policy_number_2) { - Some(policy_code) => { println!("Policy-Number: {:?} {:?}", - test_policy_number, policy_code); - }, - _ => println!("2. No number found!"), + let my_policy_numbers : [usize; 2] = [1511111111, 9999999993]; + assert_eq!(my_policy_numbers, [1511111111, 9999999993]); + for p in &my_policy_numbers { + match policy_numbers.get(&p) { + Some(policy_code) => { + println!("Test: Policy-Number {:?} => Policy-Type {:?}, as expected!", + p, policy_code); + }, + _ => println!("Test: Policy-Number {:?} => not valid, can't dereference the Policy-Type as expected", p), + } } state = t!("state.finished", lang); From dbe0ef9ea1b415ee3130f98690a0fc79593f86b5 Mon Sep 17 00:00:00 2001 From: Ralf Zerres Date: Fri, 3 Jul 2020 00:59:59 +0200 Subject: [PATCH 11/17] widgets: main_view: activate structure init via default() * possible, since structure provides access via orbtk Signed-off-by: Ralf Zerres --- advotracker/src/widgets/main_view.rs | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/advotracker/src/widgets/main_view.rs b/advotracker/src/widgets/main_view.rs index d8f5d22..43de361 100644 --- a/advotracker/src/widgets/main_view.rs +++ b/advotracker/src/widgets/main_view.rs @@ -15,13 +15,12 @@ widget!(MainView { // policy_data_list: PolicyDataList, // policylist_view: u32, // policydata_view: u32, - // policydata_view: u32, - policy_number_count: usize, - policycheck_view: u32 + //policycheck_view: u32 + policycheck_view: PolicyCheck }); impl Template for MainView { - fn template(self, id: Entity, ctx: &mut BuildContext) -> Self { + fn template(self, id: Entity, ctx: &mut BuildContext<'_>) -> Self { let policycheck_view = PolicyCheckView::new() //.policy_number_count(0) //.policylist_view(id) @@ -41,8 +40,7 @@ impl Template for MainView { // .build(ctx); self.name("MainView") - .policy_number_count(0) - //.policycheck_view(PolicyCheck::default()) + .policycheck_view(PolicyCheck::default()) // //.policycheck_view(0) // .policydata_view(policydata_view.0) // //.policylist_view(PolicyList::default()) From 58045967cb59c1bb6ae8df6a40c519eb94a58f62 Mon Sep 17 00:00:00 2001 From: Ralf Zerres Date: Fri, 3 Jul 2020 01:01:24 +0200 Subject: [PATCH 12/17] callbacks: policy_check: update identifier for tracing Signed-off-by: Ralf Zerres --- advotracker/src/callbacks/policy_check.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/advotracker/src/callbacks/policy_check.rs b/advotracker/src/callbacks/policy_check.rs index c0170cf..84b56c8 100644 --- a/advotracker/src/callbacks/policy_check.rs +++ b/advotracker/src/callbacks/policy_check.rs @@ -25,7 +25,7 @@ pub fn is_valid(policy_number: &usize, policy_list: &PolicyDataList, let mut state = t!("state.started", lang); let dt_start: DateTime = Local::now(); - trace!(target: "csv-test", + trace!(target: "advotracker", process = ?res, state = ?state, policy_number = ?policy_number, @@ -41,7 +41,7 @@ pub fn is_valid(policy_number: &usize, policy_list: &PolicyDataList, policy_number, policy_code); info!("{} => {} ({:?})", res, policy_number, policy_code); result = true; - trace!(target: "csv-test", + trace!(target: "advotracker", policy_number = ?policy_number, validation = ?res, policy_code = ?policy_code); @@ -50,7 +50,7 @@ pub fn is_valid(policy_number: &usize, policy_list: &PolicyDataList, let res = t!("policy.validation.failed", lang); println!("Noop! Number isn't valid!"); info!("{} => {}", res, policy_number); - trace!(target: "csv-test", + trace!(target: "advotracker", policy_number = ?policy_number, validation = ?res); }, @@ -61,7 +61,7 @@ pub fn is_valid(policy_number: &usize, policy_list: &PolicyDataList, res = t!("policy.validation.finished", lang); state = t!("state.finished", lang); - trace!(target: "csv-test", + trace!(target: "advotracker", process = ?res, state = ?state, date_stop = ?dt_end.to_string(), From d0a5013b7158e3fb3b45a2d4c66cb793d3d08537 Mon Sep 17 00:00:00 2001 From: Ralf Zerres Date: Fri, 3 Jul 2020 01:04:21 +0200 Subject: [PATCH 13/17] callbacks: global_state: compiler sanitization * use unspecific lifetimes Signed-off-by: Ralf Zerres --- advotracker/src/callbacks/global_state.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/advotracker/src/callbacks/global_state.rs b/advotracker/src/callbacks/global_state.rs index cc4ab84..ffb9733 100644 --- a/advotracker/src/callbacks/global_state.rs +++ b/advotracker/src/callbacks/global_state.rs @@ -16,7 +16,7 @@ use orbtk::prelude::*; /// Provides generic methods to handle states of datatypes (e.g. used in `PolicyList`). pub trait GlobalState { /// Navigates to the given entity. - fn navigate(&self, to: Entity, ctx: &mut Context) { + 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); @@ -28,7 +28,7 @@ pub trait GlobalState { } /// Get the text of a widget. - fn get_text(&self, ctx: &mut Context, entity: Entity) -> Option { + fn get_text(&self, ctx: &mut Context<'_>, entity: Entity) -> Option { let mut widget = ctx.get_widget(entity); let entry = widget.get_mut::("text"); From 2ba39436bc15ca6e56e3a8b1f9d7cc7bc77c4045 Mon Sep 17 00:00:00 2001 From: Ralf Zerres Date: Fri, 3 Jul 2020 01:05:33 +0200 Subject: [PATCH 14/17] callbacks: global_state: save data vector to ron file on disk * new functionality * save imported / edited data-structures persitantliy on disk to file in 'ron' format Signed-off-by: Ralf Zerres --- advotracker/src/callbacks/global_state.rs | 33 +++++++++++++---------- 1 file changed, 19 insertions(+), 14 deletions(-) diff --git a/advotracker/src/callbacks/global_state.rs b/advotracker/src/callbacks/global_state.rs index ffb9733..46cd69c 100644 --- a/advotracker/src/callbacks/global_state.rs +++ b/advotracker/src/callbacks/global_state.rs @@ -8,10 +8,10 @@ use orbtk::prelude::*; //use crate::data::keys; -// use crate::{ -// //data::structures::PolicyList, -// data::keys::* -// }; +use crate::{ + data::structures::PolicyList, + data::keys::* +}; /// Provides generic methods to handle states of datatypes (e.g. used in `PolicyList`). pub trait GlobalState { @@ -41,14 +41,19 @@ pub trait GlobalState { Some(copy) } - // Save the data. - // fn save(&self, registry: &mut Registry, ctx: &mut Context) { - // registry - // .get::("settings") - // .save( - // PROP_POLICY_LIST, - // ctx.widget().get::(PROP_POLICY_LIST), - // ) - // .unwrap(); - // } + /// Save the our data structure and convert it to `ron` file format. + /// The cargo package identifier (here: 'nwx.advotracker') is taken to create the app directory. + /// in users 'settings directory'. The directory location is OS dependant + /// (Windows: AppData, Unix: XDG_CONFIG_HOME, MacOS: $HOME/Library/Preferences). + /// The data is stored in filename PROP_ADVOTRACKER (here: `advotracker.ron`) + + fn save(&self, registry: &mut Registry, ctx: &mut Context<'_>) { + registry + .get::("settings") + .save( + PROP_ADVOTRACKER, + ctx.widget().get::(PROP_ADVOTRACKER), + ) + .unwrap(); + } } From 1d48f294dcc8143bfeae2d63315e81d98b89b711 Mon Sep 17 00:00:00 2001 From: Ralf Zerres Date: Fri, 3 Jul 2020 01:10:28 +0200 Subject: [PATCH 15/17] main: add stylesheet, comment out inactive includes Signed-off-by: Ralf Zerres --- advotracker/src/main.rs | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/advotracker/src/main.rs b/advotracker/src/main.rs index 93704ce..5c5a845 100644 --- a/advotracker/src/main.rs +++ b/advotracker/src/main.rs @@ -5,14 +5,15 @@ * SPDX-License-Identifier: (0BSD or MIT) */ -#[macro_use] -extern crate lazy_static; +//#[macro_use] +//extern crate lazy_static; //use chrono::{Local, DateTime}; use locales::t; //use serde::{Deserialize, Serialize}; use serde::Deserialize; -use std::{env, process}; +use std::env; +//use std::process; //use std::{error::Error, process}; //use std::collections::HashMap; use tracing::{debug, trace, Level}; @@ -36,8 +37,8 @@ struct Environment { } //#[cfg(feature = "light-theme")] -//static STYLESHEET: &'static str = include_str!("../resources/stylesheets/advotracker.css"); -static STYLESHEET: &'static str = include_str!("../resources/stylesheets/policyholder-check.css"); +static STYLESHEET: &'static str = include_str!("../resources/stylesheets/advotracker.css"); +//static STYLESHEET: &'static str = include_str!("../resources/stylesheets/policyholder-check.css"); fn get_theme() -> ThemeValue { //ThemeValue::create_from_css(LIGHT_THEME_EXTENSION_CSS) @@ -55,8 +56,9 @@ fn main() -> Result<(), Box> { use viperus::Viperus; //use advotracker::callbacks::policy_check::is_valid; - use advotracker::services::imports::allianzdirectcall::*; - use advotracker::data::structures::{PolicyCode, PolicyDataList, PolicyList}; + //use advotracker::data::structures::{PolicyCode, PolicyDataList, PolicyList}; + // WIP: can't push pointer by value to widget, call import in widget callback for now + //use advotracker::services::imports::allianzdirectcall::*; //static DEFAULT_FILTER: &str = concat!(module_path!(), "=", "trace"); @@ -124,7 +126,7 @@ fn main() -> Result<(), Box> { state = t!("state.started", lang); trace!(target: "csv-test", process = ?res, state = ?state); - // moved to callback: checkview_state.rs + // WIP: can't push pointer by value to widget, call import in widget callback for now // // importing policy code elements from csv-file // let policy_list = PolicyList::new("Allianz Versicherungsnummen-List"); // println!("Policy List {:?} ", policy_list.name); From a89e400029595e9dbdf0605cf0fefba6c9bec1da Mon Sep 17 00:00:00 2001 From: Ralf Zerres Date: Fri, 3 Jul 2020 01:12:25 +0200 Subject: [PATCH 16/17] policycheck: functionality update * show count of active hashmap members in GUI * move import call to init function * show results of policy_number validation in GUI * improve tracing information * disable stdout messages via println!() Signed-off-by: Ralf Zerres --- .../src/callbacks/policycheck_state.rs | 265 +++++---- advotracker/src/widgets/policycheck_view.rs | 523 +++++++++--------- 2 files changed, 416 insertions(+), 372 deletions(-) diff --git a/advotracker/src/callbacks/policycheck_state.rs b/advotracker/src/callbacks/policycheck_state.rs index 8d3d54c..6452822 100644 --- a/advotracker/src/callbacks/policycheck_state.rs +++ b/advotracker/src/callbacks/policycheck_state.rs @@ -1,17 +1,17 @@ -use locales::t; +//use locales::t; use dotenv::dotenv; use orbtk::prelude::*; use serde::Deserialize; use std::{env, process}; use std::collections::HashMap; -use tracing::{debug, trace}; +use tracing::{debug, error, info, trace}; use crate::services::imports::allianzdirectcall::import; -use crate::callbacks::policy_check::is_valid; +//use crate::callbacks::policy_check::is_valid; use crate::{ callbacks::global_state::GlobalState, - data::structures::{PolicyCode, PolicyDataList, PolicyData, PolicyList}, + data::structures::{PolicyCheck, PolicyCode, PolicyDataList, PolicyList}, data::keys::*, }; @@ -24,6 +24,7 @@ pub enum Action { ParseEntry(Entity), RemoveFocus(Entity), SetEntry(Entity), + SetVisibility(Entity), TextChanged(Entity, usize), } @@ -37,16 +38,19 @@ struct Environment { #[derive(Default, AsAny)] pub struct PolicyCheckState { action: Option, + label_result_text_block: Entity, last_focused: Option, - pub text_box: Entity, menu_button: Entity, - policy_number_valid: bool, - policy_number_count: usize, - policy_numbers: HashMap, + //policy_check_clean_button: Entity, + policy_check: PolicyCheck, + policy_data_count: usize, + //policy_number_text_box: Entity, + policy_numbers: HashMap } impl GlobalState for PolicyCheckState {} +/// method definitions, that react on any given state change inside the view impl PolicyCheckState { /// Sets a new action. pub fn action(&mut self, action: Action) { @@ -74,14 +78,15 @@ impl PolicyCheckState { let mut policy_numbers : HashMap = HashMap::new(); + // Wip: use cli parameter stored in viperus ... //let mut csv_import_path = v.get::("import_file").unwrap(); let mut csv_import_path = String::from("POLLFNR_WOECHENTLICH.txt"); println!("Importing from: {:?}", csv_import_path); match import(&mut csv_import_path, &mut policy_data, &mut policy_numbers, &lang) { Ok(count) => { - self.policy_number_count = count; - println!("Imported {:?} records", self.policy_number_count); + self.policy_data_count = count; + println!("Imported {:?} records", self.policy_data_count); } Err(err) => { println!("error running CSV-Import: {}", err); @@ -94,24 +99,26 @@ impl PolicyCheckState { } /// Clear text in text box. - pub fn clear_entry(&mut self, text_box: Entity, ctx: &mut Context) { + pub fn clear_entry(&mut self, text_box: Entity, ctx: &mut Context<'_>) { let mut text_box = TextBox::get(ctx.get_widget(text_box)); let text = text_box.text_mut(); println!("reset {}", text); } /// Open menu. - pub fn open_menu(&mut self, text_block: Entity, ctx: &mut Context) { + 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); } fn parse_entry(&mut self, policy_check_policy_number: Entity, - ctx: &mut Context) { + ctx: &mut Context<'_>) { let policy_string = ctx.get_widget(policy_check_policy_number).get::("text").as_string(); let policy_number_length = policy_string.len(); + trace!(target: "advotracker", state = "parsing", policy_number = ?policy_string); + // Parse policy code: "AS-123456789" // DION VERS POLLFNR // 1 AS 1515735810 @@ -119,107 +126,84 @@ impl PolicyCheckState { // needs to be an integer match policy_string.parse::() { Ok(p) => { - trace!(target: "advotracker", policy_number = ?p); - - // WIP: for now, only import once per session - if self.policy_number_count == 0 { - match self.create_hashmap() { - Ok(()) => { - //let res = t!("policy.hashmap.success", lang); - //println!("{:?}", res); - println!("hashmap has: {:?} entries", self.policy_number_count); - } - _ => { - // let res = t!("policy.hashmap.failed", lang); - // println - // !("{:?}", res); - println!("Creation of a hashmap failed!"); - } - } - } else { - println!("Already imported {} records.", self.policy_number_count); - - - } println!(" ... verify policy Number {:?}", p); + let mut label_wrapper : TextBlockCtx<'_> = text_block(ctx.child("policy_check_label_result")); + let string_label = "Prüfungsergebnis:".to_string(); + label_wrapper.set_text(string_label); + label_wrapper.set_visibility(Visibility::Visible); + label_wrapper.set_enabled(true); + let mut result_wrapper: TextBlockCtx<'_> = text_block(ctx.child("policy_check_result")); + result_wrapper.set_text("Prüfung läuft ..."); match self.policy_numbers.get(&p) { - // check hashmaps value field + // check hashmap value field Some(policy_code) => { - //let res = t!("policy.validation.success", lang); - //println!("{:?}", res); - println!("policy_number: {} ({:?})", - p, policy_code); + trace!(target: "advotracker", state = "success", + policy_number = ?p, policy_code = ?policy_code); + result_wrapper.set_enabled(true); + let string_result = format!("gütig! => vollständig: 1-{:?}-{}", + policy_code, p); + result_wrapper.set_text(string_result); } _ => { //let res = t!("policy.validation.failed", lang); //println!("{:?}", res); - println!("Nuup! Number isn't valid!"); + trace!(target: "advotracker", state = "failed", + policy_number = ?p); + println!("Noop! Number isn't valid!"); + result_wrapper.set_enabled(true); + result_wrapper.set_text("noop, ungültig!"); } } }, Err(e) => { + trace!(target: "advotracker", state = "error", error_type = "invalid type"); println!("invalid: {}", e); // Feedback println!("Please enter an integer!"); } } - //ctx.get_widget(text_box).set("policy_number_valid", true); - //ctx.get_widget(policy_check_policy_number).set("policy_check_result", true); - //TextBox::get(ctx.child("policy_check_result")).set_foreground(colors::LINK_WATER_COLOR); } if policy_number_length < 10 { println!("Policy number is to short!"); - ctx.child(ID_POLICY_CHECK_POLICY_NUMBER).set("text", String::from("")); - //ctx.child(ID_POLICY_CHECK_RESULT).set("text", String::from("Policy number is to short!")); - // ctx.get_widget(policy_check_policy_number).set("policy_number_valid", true); - //policy_check_view(ctx.widget()) - // .set_policy_check_result(String16::from(format!("Given Number is to small: {}", policy_number_length))); - //let mut text_box = text_box(ctx.get_widget(Entity)); - //let text = text_box.text; - //println!("submitting {}", text); - //text.clear(); - // TextBock: set "visibility", "text" - //policycheck_view(ctx.widget()) - // .list_mut() - // .push(format!("Item {}", len + 1)); - //ctx.child("items").set::("blub", len + 1); - //TextBox::get(ctx.child("policy_check_result")).set_foreground("#ffffff"); - //text_block::get(ctx.child(policy_check_result)).set_background("#5b0f22"); - //policy_check_result(ctx.child("items")).set_count(len + 1); + let mut text_block_wrapper: TextBlockCtx<'_> = text_block(ctx.child("policy_check_result")); + text_block_wrapper.set_enabled(true); + text_block_wrapper.set_text("zu kurz!"); + //ctx.get_widget(policy_check_policy_number).set("policy_check_result", true); + //ctx.child(ID_POLICY_CHECK_POLICY_NUMBER).set("text", String::from("")); } if policy_number_length > 10 { println!("Policy number is to big!"); - //TextBox::get(ctx.child("text_box")).set_foreground("#ffffff"); - //TextBox::get(ctx.child("text_box")).set_background("#5b0f22"); + let mut text_block_wrapper: TextBlockCtx<'_> = text_block(ctx.child("policy_check_result")); + text_block_wrapper.set_enabled(true); + text_block_wrapper.set_text("zu lang!"); } - - //if let policy_number = policy_check_policy_number.text() { - // match policy_number { - // _ => { - // println!("policynumber: {} is valid!", policy_number); - // } - // } - //} } /// If TextBox 'policy_check_policy_number' is empty, disable button "clear" /// otherwise enabled it. - // fn set_check_button(&self, text_box: Entity, ctx: &mut Context) { + // fn set_policy_check_clear_button(&self, policy_check_policy_number: Entity, ctx: &mut Context<' >) { // if ctx.get_widget(clear_button).get::("policy_check_policy_number").is_empty() { // ctx.get_widget(self.policy_check_clear_button).set("enabled", false); // } else { // ctx.get_widget(self.policy_check_clear_button).set("enabled", true); // } - // ctx.get_widget(self.text_box).update_theme_by_state(true); + // ctx.get_widget(self.policy_check_policy_number).update_theme_by_state(true); // } /// Change status of given text box to edit mode. - fn set_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)); + fn set_entry(&self, policy_check_policy_number: Entity, ctx: &mut Context<'_>) { + if *ctx.get_widget(policy_check_policy_number).get::("focused") { + //let mut my_ctx: WidgetContainer<'_> = ctx.widget(); + //let mut child: WidgetContainer<'_> = ctx.get_widget(policy_check_policy_number); + //ctx.get_widget(policy_check_policy_number).set("enabled", true); + let mut text_box_wrapper: TextBoxCtx<'_> = text_box(ctx.child("policy_check_policy_number")); + //ctx.push_event_by_window(FocusEvent::RemoveFocus(policy_check_policy_number)); + text_box_wrapper.set_visibility( Visibility::Visible); + text_box_wrapper.set_enabled(true); + text_box_wrapper.set_text(""); + text_box_wrapper.set_water_mark("Neue Eingabe ..."); return; } @@ -227,36 +211,88 @@ impl PolicyCheckState { ctx.push_event_by_window(FocusEvent::RemoveFocus(old_focused_element)); } - 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::("policy_number").len(); - ctx.push_event_by_window(FocusEvent::RequestFocus(text_box)); } + /// Change visibility of the result label + fn set_visibility(&self, entity: Entity, ctx: &mut Context<'_>) { + if ctx.get_widget(entity).get::("text").is_empty() { + text_block(ctx.child(ID_POLICY_CHECK_LABEL_RESULT)).set_visibility(Visibility::Visible); + } else { + text_block(ctx.child(ID_POLICY_CHECK_LABEL_RESULT)).set_visibility(Visibility::Collapsed); + //ctx.get_widget(self.policy_check_label_policy_number).set("enabled", false); + } + + ctx.get_widget(self.label_result_text_block).update_theme_by_state(true); + } + + // Update count of elements in the policy data list. + fn update_data_count(&self, ctx: &mut Context<'_>) { + // old api syntax + let data_list_count = ctx.widget().get::(PROP_POLICY_DATA_LIST).len(); + ctx.widget().set(PROP_POLICY_DATA_COUNT, data_list_count); + } } +/// upported states for our view impl State for PolicyCheckState { - fn init(&mut self, _: &mut Registry, ctx: &mut Context) { - // self.button = ctx - // .entity_of_child(ID_POLICY_CHECK_MENU_BUTTON) - // .expect("PolicyCheckState.init: Can't find child 'Menu button'."); - self.text_box = ctx - .entity_of_child(ID_POLICY_CHECK_POLICY_NUMBER) - .expect("PolicyCheckState.init: Can't find child 'Text Box'."); + fn init(&mut self, _: &mut Registry, ctx: &mut Context<'_>) { + self.menu_button = ctx + .entity_of_child(ID_POLICY_CHECK_MENU_BUTTON) + .expect("PolicyCheckState.init: Can't find entity id defined as resource 'ID_POLICY_CHECK_POLICY_MENU_BUTTON'."); + // self.policy_number_text_box = ctx + // .entity_of_child(ID_POLICY_CHECK_POLICY_NUMBER) + // .expect("PolicyCheckState.init: Can't find entity id defined as resource 'ID_POLICY_CHECK_POLICY_NUMBER'."); + // import data + // WIP: for now, only import once per session + if self.policy_data_count == 0 { + match self.create_hashmap() { + Ok(()) => { + //let res = t!("policy.hashmap.success", lang); + //println!("{:?}", res); + info!("hashmap has: {:?} entries", self.policy_data_count); + trace!(target: "advotracker", + hashmap_status = "new import", + hashmap_entries = ?self.policy_data_count); + } + _ => { + // let res = t!("policy.hashmap.failed", lang); + // println + // !("{:?}", res); + error!("Creation of a hashmap failed!"); + trace!(target: "advotracker", hashmap_status = "failed"); + } + } + } else { + println!("Already imported {} records.", self.policy_data_count); + trace!(target: "advotracker", + hashmap_status = "consume", + hashmap_entries = ?self.policy_data_count); + } + + // // Load the saved data from a file in 'ron' format into our data structure. + // // The cargo package identifier (default: 'nwx.advotracker') is used as the + // // app directory name. The directory location is OS dependant + // // (Windows: AppData, Unix: XDG_CONFIG_HOME, MacOS: $HOME/Library/Preferences). + // // The filename is taken from the propertey PROP_ADVOTRACKER (default: 'advotracker'.ron). + // if let Ok(policy_data) = registry + // .get::("settings") + // .load::(PROP_ADVOTRACKER) + // { + // ctx.widget().set(PROP_ADVOTRACKER, policy_data); + // } + + // number of elements in the restored policy data + //policy_data_count = policy_data.len().clone; + //self.update_data_count(ctx); } - fn update(&mut self, _registry: &mut Registry, ctx: &mut Context) { + fn update(&mut self, _registry: &mut Registry, ctx: &mut Context<'_>) { // clear focus on focus moved if self.last_focused != ctx.window().get::("global").focused_widget { if let Some(last_focused) = self.last_focused { ctx.get_widget(last_focused).set("focused", false); + // widget is unvisible, but takes space to be considered ctx.get_widget(last_focused) .set("visibility", Visibility::Collapsed); } @@ -264,27 +300,34 @@ impl State for PolicyCheckState { if let Some(action) = self.action { match action { - Action::ClearEntry(text_box) => { - self.clear_entry(text_box, ctx); + Action::ClearEntry(policy_check_policy_number) => { + ctx.get_widget(policy_check_policy_number).set("enabled", false); } - Action::InputTextChanged(text_box) => { - //self.set_check_button(text_box, ctx); + Action::InputTextChanged(entity) => { + //println!("entry changed: {}", text_box(ctx.get_widget(entity)).text()); + //self.set_check_button(policy_check_label_policy_number, ctx); + self.set_visibility(entity, ctx); } Action::OpenMenu(text_block) => { self.open_menu(text_block, ctx); } Action::ParseEntry(text_box) => { self.parse_entry(text_box, ctx); + ctx.get_widget(text_box).get::("text").as_string(); //self.parse_entry(text_box, &mut policy_numbers, // &lang, ctx); } - Action::RemoveFocus(text_box) => { - ctx.get_widget(text_box).set("enabled", false); - ctx.push_event_by_window(FocusEvent::RemoveFocus(text_box)); + Action::RemoveFocus(policy_check_policy_number) => { + ctx.get_widget(policy_check_policy_number).set("enabled", false); + ctx.push_event_by_window(FocusEvent::RemoveFocus(policy_check_policy_number)); } - Action::SetEntry(text_box) => { - self.last_focused = Some(text_box); - self.set_entry(text_box, ctx); + Action::SetEntry(policy_check_policy_number) => { + //self.last_focused = Some(); + self.set_entry(policy_check_policy_number, ctx); + } + Action::SetVisibility(entity) => { + //text_block(ctx.child(entity).set_visibility(Visibility::Visible)); + text_block(ctx.child(ID_POLICY_CHECK_LABEL_RESULT)).set_visibility(Visibility::Collapsed); } Action::TextChanged(entity, _index) => { self.set_entry(entity, ctx); @@ -293,4 +336,16 @@ impl State for PolicyCheckState { } self.action = None; } + + fn update_post_layout(&mut self, _: &mut Registry, ctx: &mut Context<'_>) { + let string_result = "Prüfungsergebnis:".to_string(); + //string_result = format!("{} {:?}", string_result, self.??; + text_block(ctx.child(ID_POLICY_CHECK_LABEL_RESULT)).set_text(string_result); + text_block(ctx.child(ID_POLICY_CHECK_LABEL_RESULT)).set_visibility(Visibility::Collapsed); + + let mut string_data_count = "Prüflisten-Elemente:".to_string(); + string_data_count = format!("{} {:?}", string_data_count, self.policy_numbers.len()); + + text_block(ctx.child(ID_POLICY_DATA_COUNT_BLOCK)).set_text(string_data_count); + } } diff --git a/advotracker/src/widgets/policycheck_view.rs b/advotracker/src/widgets/policycheck_view.rs index 5f7e360..1a427cc 100644 --- a/advotracker/src/widgets/policycheck_view.rs +++ b/advotracker/src/widgets/policycheck_view.rs @@ -14,43 +14,21 @@ use crate::{ //policycheck_state::{Action, PolicyCheckState}, }; + +// Macro that initializes the widget structures/variables for our view (essential!) 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: String16, - policy_check_number: String16, - policy_check_number_valid: bool, - policy_check_result: String16, - policy_data_count: u32, - //policylist_view: u32, - title: String + policy_data_count: u32 } ); +// The template implementation for our View 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); - - + fn template(self, id: Entity, ctx: &mut BuildContext<'_>) -> Self { let policy_check_menu_text_block = TextBlock::new() .foreground("#3b434a") .text("Help Menu") @@ -81,24 +59,21 @@ impl Template for PolicyCheckView { }) .build(ctx); - // let policy_check_text_box = TextBox::new() - // .id(ID_POLICY_CHECK_TEXT_BOX) - // .attach(Grid::row(4)) - // .attach(Grid::row(0)) - // .attach(Grid::column(0)) - // .v_align("top") - // .margin((4.0, 0.0, 0.0, 0.0)) - // .lost_focus_on_activation(false) - // //.text(("policy_number", id)) - // // .on_activate(move |ctx, entity| { - // // ctx.get_mut::(id) - // // .action(Action::ParseEntry(entity)); - // // }) - // // .on_changed(move |ctx, entity| { - // // ctx.get_mut::(id) - // // .action(Action::InputTextChanged(entity)); - // // }) - // .build(ctx); + + let policy_data_count_block = TextBlock::new() + .id(ID_POLICY_DATA_COUNT_BLOCK) + //.class(CLASS_TEXT_BLOCK) + .attach(Grid::row(2)) + .attach(Grid::column(0)) + .attach(Grid::column_span(3)) + .margin((0., 0., 0., 16.)) + .h_align("end") + .v_align("end") + .enabled(true) + .min_width(250.0) + .min_height(45.0) + .text("Anzahl Prüfsätze:") + .build(ctx); // let policy_check_menu_container = Container::new() // .id(ID_POLICY_CHECK_MENU_CONTAINER) @@ -128,252 +103,266 @@ impl Template for PolicyCheckView { // Starter page: check for valid policy number self.name("PolicyCheckView") - //.policy_check(PolicyCheck::default()) + // initialize struct consuming the derived default macro + .policy_check(PolicyCheck::default()) .child( - Grid::new() - .id(ID_POLICY_CHECK_WIDGET) - .background("#fafafa") - .columns( - Columns::new() - .add(84.0) - .add("*") - .add(50.0) - .build(), - ) - .rows( - Rows::new() + Grid::new() + .id(ID_POLICY_CHECK_WIDGET) + .background("#fafafa") + .columns( + Columns::new() + .add(84.0) + .add("*") + .add(50.0) + .build(), + ) + .rows( + Rows::new() // Top Bar - .add("auto") - .add(1.0) + .add("auto") + .add(1.0) // Content - .add("*") - .add(1.0) + .add("*") + .add(1.0) // Bottom Bar - .add(52.0) + .add(52.0) /* .add("auto") */ - .build(), - ) - // Header Bar - .child( - //.border_color("transparent") - Container::new() + .build(), + ) + // Header Bar + .child( + //.border_color("transparent") + Container::new() //.class(CLASS_TOP_BAR) - .attach(Grid::row(0)) - .attach(Grid::column(0)) - .attach(Grid::column_span(3)) - .child( - Grid::new() - .child( - TextBlock::new() + .attach(Grid::row(0)) + .attach(Grid::column(0)) + .attach(Grid::column_span(3)) + .child( + Grid::new() + .child( + TextBlock::new() //.class(CLASS_HEADER) - .class("h1") + .class("h1") //.class(".myheader") - .id(ID_POLICY_CHECK_HEADER) + .id(ID_POLICY_CHECK_HEADER) //.font_size(24) //.font("Roboto Medium") - .v_align("center") - .h_align("center") - .margin((32.0, 32.0, 32.0, 32.0)) - .text("Validierung Versicherungsnummer") - .build(ctx), - ) - .build(ctx), - ) - .child(policy_check_menu_button) - .build(ctx), - ) - .child( - Container::new() - .class("separator") - .attach(Grid::row(1)) - .attach(Grid::column_span(3)) - .build(ctx), - ) - // Policy Check Form - .child( - Container::new() + .v_align("center") + .h_align("center") + .margin((32.0, 32.0, 32.0, 32.0)) + .text("Validierung Versicherungsnummer") + .build(ctx), + ) + .build(ctx), + ) + .child(policy_check_menu_button) + .build(ctx), + ) + .child( + Container::new() + .class("separator") + .attach(Grid::row(1)) + .attach(Grid::column_span(3)) + .build(ctx), + ) + // Policy Check Form + .child( + Container::new() //.class(CLASS_POLICY_CHECK_FORM) - .attach(Grid::row(2)) - .attach(Grid::column(0)) - .attach(Grid::column_span(3)) - .margin((16.0, 26.0, 26.0, 16.0)) - .child( - Grid::new() - .id(ID_POLICY_CHECK_FORM) - .columns( - Columns::new() + .attach(Grid::row(2)) + .attach(Grid::column(0)) + .attach(Grid::column_span(3)) + .margin((16.0, 26.0, 26.0, 16.0)) + .child( + Grid::new() + .id(ID_POLICY_CHECK_FORM) + .columns( + Columns::new() // Labels - .add("220.0") + .add("220.0") // Seperator - .add("16.0") + .add("16.0") // Values - .add("100.0") - .build(), - ) - .rows( - Rows::new() - .add("64.0") - .add("64.0") - .build(), - ) - .child( - // Labels - Stack::new() - .attach(Grid::column(0)) - .attach(Grid::row(0)) - .orientation("vertical") + .add("100.0") + .build(), + ) + .rows( + Rows::new() + .add("64.0") + .add("64.0") + .build(), + ) + .child( + // Labels + Stack::new() + .attach(Grid::column(0)) + .attach(Grid::row(0)) + .orientation("vertical") //.v_align("center") - .child( - TextBlock::new() - .id(ID_POLICY_CHECK_LABEL_POLICY_NUMBER) + .child( + TextBlock::new() + .id(ID_POLICY_CHECK_LABEL_POLICY_NUMBER) //.class(CLASS_TEXT_BLOCK) - .margin((0.0, 0.0, 16.0, 16.0)) - .h_align("end") - .v_align("center") - .min_width(250.0) - .min_height(45.0) + .margin((0.0, 0.0, 16.0, 16.0)) + .h_align("end") + .v_align("center") + .min_width(250.0) + .min_height(45.0) //.size(250.0, 45.0) - .text("Versicherungsnummer:") - .build(ctx), - ) - .child( - TextBlock::new() - .id(ID_POLICY_CHECK_LABEL_RESULT) - //.class(CLASS_TEXT_BLOCK) - .attach(Grid::column(0)) - .attach(Grid::row(1)) - .margin((0.0, 0.0, 16.0, 0.0)) - .h_align("end") - .v_align("center") - .min_width(250.0) - //.min_size(120.0, 180.0) - //.text("Ergebnis:") - //.text("Result:") - .build(ctx), - ) - .build(ctx) - ) - .child( - // Values - Stack::new() - .attach(Grid::column(1)) - .attach(Grid::row(0)) - //.attach(Grid::column_span(3)) - .orientation("vertical") - //.margin((16.0, 16.0, 16.0, 16.0)) - //.child(policy_check_text_box) - .child( - TextBox::new() - .id(ID_POLICY_CHECK_POLICY_NUMBER) - .h_align("start") - .width(280.0) - .min_width(200.0) - .margin((0.0, 0.0, 0.0, 16.0)) - .lost_focus_on_activation(false) - .water_mark("10-stellige Nummer (ohne 'AS')") - .text("") - .on_activate(move |ctx, entity| { - // Entity is entered/activated via Mouse/Keyboard - ctx.get_mut::(id) - .action(Action::ParseEntry(entity)); - }) - .on_changed(move |ctx, entity| { - // Element value has changed - ctx.get_mut::(id) - .action(Action::InputTextChanged(entity)); - }) - .build(ctx), - ) + .text("Versicherungsnummer:") + .build(ctx), + ) + .child( + TextBlock::new() + .id(ID_POLICY_CHECK_LABEL_RESULT) + .class(CLASS_TEXT_BLOCK) + .attach(Grid::column(0)) + .attach(Grid::row(1)) + .margin((0.0, 0.0, 16.0, 0.0)) + .h_align("end") + .v_align("center") + .min_width(250.0) + .text("Result:") + .build(ctx), + ) + .build(ctx) + ) + .child( + // Values + Stack::new() + .attach(Grid::column(1)) + .attach(Grid::row(0)) + //.attach(Grid::column_span(3)) + .orientation("vertical") + //.margin((16.0, 16.0, 16.0, 16.0)) + //.child(policy_check_text_box) + .child( + TextBox::new() + .id(ID_POLICY_CHECK_POLICY_NUMBER) + .h_align("start") + .width(280.0) + .min_width(200.0) + .margin((0.0, 0.0, 0.0, 16.0)) + .lost_focus_on_activation(false) + .water_mark("Nummer 10-stellig") + .text("") + .on_activate(move |ctx, entity| { + // Entity is entered/activated via Mouse/Keyboard + println!("activation finished!"); + ctx.get_mut::(id) + .action(Action::ParseEntry(entity)); + }) + .on_changed(move |ctx, entity| { + // Element value has changed + ctx.get_mut::(id) + .action(Action::InputTextChanged(entity)); + ctx.get_mut::(id) + .action(Action::SetVisibility(entity)); + //ctx.get_widget(policy_check_label_policy_number).set("visible"); + // ctx.get_mut::(id) + // .action(Action::SetVisility(entity)); + }) + // .on_mouse_down | .on_mouse_move | .on_mouse_up (move |ctx, entity| { + // state(id, states).action(Action::AddItem); + // }) + // .on_click(move |states, _| { + // state(id, states).action(Action::AddItem); + // true + // }) + .build(ctx), + ) //.icon(material_icons_font_ttf::MD_ADD_CIRCLE) // .child() - // NumericBox::new() - // .id(ID_POLICY_CHECK_POLICY_NUMBER) - // .h_align("start") - // .width(250.0) - // .min(1000000000) - // .max(9999999999) - // .val(0) - // .min_width(200.0) - // .margin((0.0, 0.0, 0.0, 16.0)) - // //.lost_focus_on_activation(false) - // //.water_mark("10-stellige Nummer (ohne 'AS')") - // //.text("") - // //.on_activate(move |ctx, entity| { - // // ctx.get_mut::(id) - // // .action(Action::ParseEntry(entity)); - // //}) - // // .on_changed(move |ctx, entity| { - // // ctx.get_mut::(id) - // // .action(Action::InputTextChanged(entity)); - // // }) - // // .on_update(move |ctx, entity| { - // // ctx.get_mut::(id) - // // .action(Action::InputTextChanged(entity)); - // // }) - // .build(ctx), + // NumericBox::new() + // .id(ID_POLICY_CHECK_POLICY_NUMBER) + // .h_align("start") + // .width(250.0) + // .min(1000000000) + // .max(9999999999) + // .val(0) + // .min_width(200.0) + // .margin((0.0, 0.0, 0.0, 16.0)) + // //.lost_focus_on_activation(false) + // //.water_mark("10-stellige Nummer (ohne 'AS')") + // //.text("") + // //.on_activate(move |ctx, entity| { + // // ctx.get_mut::(id) + // // .action(Action::ParseEntry(entity)); + // //}) + // // .on_changed(move |ctx, entity| { + // // ctx.get_mut::(id) + // // .action(Action::InputTextChanged(entity)); + // // }) + // // .on_update(move |ctx, entity| { + // // ctx.get_mut::(id) + // // .action(Action::InputTextChanged(entity)); + // // }) + // .build(ctx), //) - .child( - TextBlock::new() - //.id(ID_POLICY_CHECK_RESULT) - .id("policy_check_result") - .h_align("start") - .attach(Grid::column(1)) - .attach(Grid::row(1)) - .text(("")) + .child( + TextBlock::new() + .id(ID_POLICY_CHECK_RESULT) + //.id("policy_check_result") + .h_align("start") + .attach(Grid::column(1)) + .attach(Grid::row(1)) + .text("") + .width(250.) //.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::ParseEntry(entity)); - // }) - // .on_changed(move |ctx, entity| { - // ctx.get_mut::(id) - // .action(Action::InputTextChanged(entity)); - // }) - .build(ctx), - ) - .build(ctx) - ) - .build(ctx) - ) - .build(ctx) - ) - .child( - Container::new() - .class("separator") - .attach(Grid::row(3)) - .attach(Grid::column_span(3)) - .build(ctx), - ) + // .on_activate(move |ctx, entity| { + // ctx.get_mut::(id) + // .action(Action::ParseEntry(entity)); + // }) + // .on_changed(move |ctx, entity| { + // ctx.get_mut::(id) + // .action(Action::InputTextChanged(entity)); + // }) + .build(ctx), + ) + .build(ctx) + ) + .build(ctx) + ) + .build(ctx) + ) + .child( + Container::new() + .class("") + .attach(Grid::row(3)) + .attach(Grid::column_span(3)) + .build(ctx), + ) + .child(policy_data_count_block) // Bottom bar - .child( - Container::new() - .class(CLASS_BOTTOM_BAR) - .attach(Grid::row(4)) - .attach(Grid::column(0)) - .attach(Grid::column_span(3)) - .v_align("end") - .child( - Grid::new() - .element("logo_customer") - .margin((9.0, 16.0, 16.0, 9.0)) + .child( + Container::new() + .class(CLASS_BOTTOM_BAR) + .attach(Grid::row(4)) + .attach(Grid::column(0)) + .attach(Grid::column_span(3)) + .v_align("end") + .child( + Grid::new() + .element("logo_customer") + .margin((9.0, 16.0, 16.0, 9.0)) + .attach(Grid::column(0)) + .attach(Grid::row(1)) + .h_align("start") + .v_align("center") + .child( + ImageWidget::new() + .image("resources/images/hiedemann_logo.png") + .build(ctx), + ) + .build(ctx), + ) + .child( + Grid::new() + .element("logo_vendor") + .margin((9.0, 16.0, 16.0, 9.0)) .attach(Grid::column(0)) - .attach(Grid::row(1)) - .h_align("start") - .v_align("center") - .child( - ImageWidget::new() - .image("resources/images/hiedemann_logo.png") - .build(ctx), - ) - .build(ctx), - ) - .child( - Grid::new() - .element("logo_vendor") - .margin((9.0, 16.0, 16.0, 9.0)) - .attach(Grid::column(0)) - .attach(Grid::row(4)) + .attach(Grid::row(5)) .h_align("end") .v_align("center") .child( From e079d34663ae3b4cd8dd4e728d4fd92fb770ea02 Mon Sep 17 00:00:00 2001 From: Ralf Zerres Date: Fri, 3 Jul 2020 01:15:37 +0200 Subject: [PATCH 17/17] resource: stylesheet: advotracker.css Signed-off-by: Ralf Zerres --- .../resources/stylesheets/advotracker.css | 83 +++++++++++++++++++ 1 file changed, 83 insertions(+) diff --git a/advotracker/resources/stylesheets/advotracker.css b/advotracker/resources/stylesheets/advotracker.css index e69de29..87c1f78 100644 --- a/advotracker/resources/stylesheets/advotracker.css +++ b/advotracker/resources/stylesheets/advotracker.css @@ -0,0 +1,83 @@ +.top_bar { + padding-left: 4; + padding-right: 4; + min-height: 52; + background: #475b6e; +} + +.bottom_bar { + height: 40; + background: #475b6e; +} + +.header { + font-size: 24; + font-family: "Roboto Medium"; +} + +text_box.inplace { + color: #dfebf5; + background: transparent; + border-color: transparent; + border-width: 1; + border-radius: 2; + padding: 6; +} + +text_box.inplace:focus { + background: #3b434a; + border-color: #5b0f22; + /* border-color: #f8de4c; */ +} + +text_box.inplace:empty { + color: #9E9E9E + border-color: #5b0f22; +} + +/* +.icon_only { + background: #5b0f22; + */ background: transparent; */ + icon-color: #fffffff; + spacing: 0; +} + +.icon_only:active { + background: #5b0f22; + icon-color: #fffffff; + /* icon-color: #516475; */ + /* icon-color: #dfebf5; */ + } + +.icon_only:disabled { + icon-color: #fffffff; + /* icon-color: #949ca5; */ + background: #fffffff; + /* background: transparent; */ +} +*/ + +items-widget { + padding: 0; + border-color: transparent; +} + +.transparent { + icon-color: transparent; + background: transparent; +} + +.transparent:active { + icon-color: transparent; + background: transparent; +} + +.item_button { + background: transparent; + border-radius: 0; +} + +.separator { + background: #212121; +}