Full Printing Now Available (with some bugs) #20
@@ -1128,7 +1128,7 @@
 | 
				
			|||||||
.print-preview-paper[data-start-hour="7"][data-end-hour="19"]:has(.time-slot.quarter-mode) .time-labels,
 | 
					.print-preview-paper[data-start-hour="7"][data-end-hour="19"]:has(.time-slot.quarter-mode) .time-labels,
 | 
				
			||||||
.print-preview-paper[data-start-hour="7"][data-end-hour="19"]:has(.time-slot.quarter-mode) .week-days-grid { min-height: 1530px !important; }
 | 
					.print-preview-paper[data-start-hour="7"][data-end-hour="19"]:has(.time-slot.quarter-mode) .week-days-grid { min-height: 1530px !important; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Print Page Setup - Force landscape orientation */
 | 
					/* Print Page Setup - Force landscape orientation and fit to page */
 | 
				
			||||||
@page {
 | 
					@page {
 | 
				
			||||||
    size: landscape;
 | 
					    size: landscape;
 | 
				
			||||||
    margin: 0.5in;
 | 
					    margin: 0.5in;
 | 
				
			||||||
@@ -1136,6 +1136,11 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
/* Print Media Rules - Show only the print-preview-copy when printing */
 | 
					/* Print Media Rules - Show only the print-preview-copy when printing */
 | 
				
			||||||
@media print {
 | 
					@media print {
 | 
				
			||||||
 | 
					    html {
 | 
				
			||||||
 | 
					        print-color-adjust: exact; /* Preserve colors when printing */
 | 
				
			||||||
 | 
					        -webkit-print-color-adjust: exact;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
    /* Hide all top-level app content */
 | 
					    /* Hide all top-level app content */
 | 
				
			||||||
    .app {
 | 
					    .app {
 | 
				
			||||||
        display: none !important;
 | 
					        display: none !important;
 | 
				
			||||||
@@ -1147,11 +1152,19 @@
 | 
				
			|||||||
        position: absolute !important;
 | 
					        position: absolute !important;
 | 
				
			||||||
        left: 0 !important;
 | 
					        left: 0 !important;
 | 
				
			||||||
        top: 0 !important;
 | 
					        top: 0 !important;
 | 
				
			||||||
        width: 960px !important;
 | 
					        /* width: 960px !important; */
 | 
				
			||||||
        height: 720px !important;
 | 
					        /* height: 720px !important; */
 | 
				
			||||||
 | 
					        aspect-ratio: 1.2941176470588236 !important;
 | 
				
			||||||
        margin: 0 !important;
 | 
					        margin: 0 !important;
 | 
				
			||||||
        padding: 0 !important;
 | 
					        padding: 0 !important;
 | 
				
			||||||
        box-sizing: border-box !important;
 | 
					        box-sizing: border-box !important;
 | 
				
			||||||
 | 
					        /* Properties to help browsers scale to fit page */
 | 
				
			||||||
 | 
					        max-width: 100vw;
 | 
				
			||||||
 | 
					        max-height: 100vh;
 | 
				
			||||||
 | 
					        object-fit: contain;
 | 
				
			||||||
 | 
					        page-break-inside: avoid;
 | 
				
			||||||
 | 
					        orphans: 1;
 | 
				
			||||||
 | 
					        widows: 1;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    /* Ensure print content uses the full page */
 | 
					    /* Ensure print content uses the full page */
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -106,8 +106,8 @@ pub fn PrintPreviewModal(props: &PrintPreviewModalProps) -> Html {
 | 
				
			|||||||
    {
 | 
					    {
 | 
				
			||||||
        let start_hour = *start_hour;
 | 
					        let start_hour = *start_hour;
 | 
				
			||||||
        let end_hour = *end_hour;
 | 
					        let end_hour = *end_hour;
 | 
				
			||||||
        let base_unit_value = base_unit;
 | 
					        let time_increment = props.time_increment;
 | 
				
			||||||
        let pixels_per_hour_value = pixels_per_hour;
 | 
					        let original_base_unit = base_unit;
 | 
				
			||||||
        use_effect(move || {
 | 
					        use_effect(move || {
 | 
				
			||||||
            if let Some(window) = web_sys::window() {
 | 
					            if let Some(window) = web_sys::window() {
 | 
				
			||||||
                if let Some(document) = window.document() {
 | 
					                if let Some(document) = window.document() {
 | 
				
			||||||
@@ -115,8 +115,6 @@ pub fn PrintPreviewModal(props: &PrintPreviewModalProps) -> Html {
 | 
				
			|||||||
                    if let Some(document_element) = document.document_element() {
 | 
					                    if let Some(document_element) = document.document_element() {
 | 
				
			||||||
                        if let Some(html_element) = document_element.dyn_ref::<web_sys::HtmlElement>() {
 | 
					                        if let Some(html_element) = document_element.dyn_ref::<web_sys::HtmlElement>() {
 | 
				
			||||||
                            let style = html_element.style();
 | 
					                            let style = html_element.style();
 | 
				
			||||||
                            let _ = style.set_property("--print-base-unit", &format!("{:.2}", base_unit_value));
 | 
					 | 
				
			||||||
                            let _ = style.set_property("--print-pixels-per-hour", &format!("{:.2}", pixels_per_hour_value));
 | 
					 | 
				
			||||||
                            let _ = style.set_property("--print-start-hour", &start_hour.to_string());
 | 
					                            let _ = style.set_property("--print-start-hour", &start_hour.to_string());
 | 
				
			||||||
                            let _ = style.set_property("--print-end-hour", &end_hour.to_string());
 | 
					                            let _ = style.set_property("--print-end-hour", &end_hour.to_string());
 | 
				
			||||||
                        }
 | 
					                        }
 | 
				
			||||||
@@ -132,24 +130,82 @@ pub fn PrintPreviewModal(props: &PrintPreviewModalProps) -> Html {
 | 
				
			|||||||
                                    print_copy.set_inner_html("");
 | 
					                                    print_copy.set_inner_html("");
 | 
				
			||||||
                                    let _ = print_copy.append_child(&content_clone);
 | 
					                                    let _ = print_copy.append_child(&content_clone);
 | 
				
			||||||
                                    
 | 
					                                    
 | 
				
			||||||
                                    // Copy the CSS variables and data attributes from the print-preview-paper
 | 
					                                    // Get the actual rendered height of the print copy div and recalculate base-unit
 | 
				
			||||||
                                    if let Some(preview_paper) = document.query_selector(".print-preview-paper").ok().flatten() {
 | 
					 | 
				
			||||||
                                        if let Some(_paper_element) = preview_paper.dyn_ref::<web_sys::HtmlElement>() {
 | 
					 | 
				
			||||||
                                            // Copy CSS custom properties (variables)
 | 
					 | 
				
			||||||
                                    if let Some(print_copy_html) = print_copy.dyn_ref::<web_sys::HtmlElement>() {
 | 
					                                    if let Some(print_copy_html) = print_copy.dyn_ref::<web_sys::HtmlElement>() {
 | 
				
			||||||
 | 
					                                        // Temporarily make visible to measure height, then hide again
 | 
				
			||||||
 | 
					                                        let original_display = print_copy_html.style().get_property_value("display").unwrap_or_default();
 | 
				
			||||||
 | 
					                                        let _ = print_copy_html.style().set_property("display", "block");
 | 
				
			||||||
 | 
					                                        let _ = print_copy_html.style().set_property("visibility", "hidden");
 | 
				
			||||||
 | 
					                                        let _ = print_copy_html.style().set_property("position", "absolute");
 | 
				
			||||||
 | 
					                                        let _ = print_copy_html.style().set_property("top", "-9999px");
 | 
				
			||||||
 | 
					                                        
 | 
				
			||||||
 | 
					                                        // Now measure the height
 | 
				
			||||||
 | 
					                                        let actual_height = print_copy_html.client_height() as f64;
 | 
				
			||||||
 | 
					                                        
 | 
				
			||||||
 | 
					                                        // Restore original display
 | 
				
			||||||
 | 
					                                        let _ = print_copy_html.style().set_property("display", &original_display);
 | 
				
			||||||
 | 
					                                        let _ = print_copy_html.style().remove_property("visibility");
 | 
				
			||||||
 | 
					                                        let _ = print_copy_html.style().remove_property("position");
 | 
				
			||||||
 | 
					                                        let _ = print_copy_html.style().remove_property("top");
 | 
				
			||||||
 | 
					                                        
 | 
				
			||||||
 | 
					                                        // Recalculate base-unit and pixels-per-hour based on actual height
 | 
				
			||||||
 | 
					                                        let visible_hours = (end_hour - start_hour) as f64;
 | 
				
			||||||
 | 
					                                        let slots_per_hour = if time_increment == 15 { 4.0 } else { 2.0 };
 | 
				
			||||||
 | 
					                                        let header_height = 50.0;
 | 
				
			||||||
 | 
					                                        let header_border = 2.0;
 | 
				
			||||||
 | 
					                                        let container_spacing = 8.0;
 | 
				
			||||||
 | 
					                                        let total_overhead = header_height + header_border + container_spacing;
 | 
				
			||||||
 | 
					                                        let available_height = actual_height - total_overhead;
 | 
				
			||||||
 | 
					                                        let actual_base_unit = available_height / (visible_hours * slots_per_hour);
 | 
				
			||||||
 | 
					                                        let actual_pixels_per_hour = actual_base_unit * slots_per_hour;
 | 
				
			||||||
 | 
					                                        
 | 
				
			||||||
 | 
					                                        
 | 
				
			||||||
 | 
					                                        // Set CSS variables with recalculated values
 | 
				
			||||||
                                        let style = print_copy_html.style();
 | 
					                                        let style = print_copy_html.style();
 | 
				
			||||||
 | 
					                                        let _ = style.set_property("--print-base-unit", &format!("{:.2}", actual_base_unit));
 | 
				
			||||||
 | 
					                                        let _ = style.set_property("--print-pixels-per-hour", &format!("{:.2}", actual_pixels_per_hour));
 | 
				
			||||||
                                        let _ = style.set_property("--print-start-hour", &start_hour.to_string());
 | 
					                                        let _ = style.set_property("--print-start-hour", &start_hour.to_string());
 | 
				
			||||||
                                        let _ = style.set_property("--print-end-hour", &end_hour.to_string());
 | 
					                                        let _ = style.set_property("--print-end-hour", &end_hour.to_string());
 | 
				
			||||||
                                                let _ = style.set_property("--print-base-unit", &format!("{:.2}", base_unit_value));
 | 
					 | 
				
			||||||
                                                let _ = style.set_property("--print-pixels-per-hour", &format!("{:.2}", pixels_per_hour_value));
 | 
					 | 
				
			||||||
                                            }
 | 
					 | 
				
			||||||
                                        
 | 
					                                        
 | 
				
			||||||
                                        // Copy data attributes
 | 
					                                        // Copy data attributes
 | 
				
			||||||
                                        let _ = print_copy.set_attribute("data-start-hour", &start_hour.to_string());
 | 
					                                        let _ = print_copy.set_attribute("data-start-hour", &start_hour.to_string());
 | 
				
			||||||
                                        let _ = print_copy.set_attribute("data-end-hour", &end_hour.to_string());
 | 
					                                        let _ = print_copy.set_attribute("data-end-hour", &end_hour.to_string());
 | 
				
			||||||
 | 
					                                        
 | 
				
			||||||
 | 
					                                        // Recalculate event positions using the new base-unit
 | 
				
			||||||
 | 
					                                        let events = print_copy.query_selector_all(".week-event").unwrap();
 | 
				
			||||||
 | 
					                                        let scale_factor = actual_base_unit / original_base_unit;
 | 
				
			||||||
 | 
					                                        
 | 
				
			||||||
 | 
					                                        for i in 0..events.length() {
 | 
				
			||||||
 | 
					                                            if let Some(event_element) = events.get(i) {
 | 
				
			||||||
 | 
					                                                if let Some(event_html) = event_element.dyn_ref::<web_sys::HtmlElement>() {
 | 
				
			||||||
 | 
					                                                    let event_style = event_html.style();
 | 
				
			||||||
 | 
					                                                    
 | 
				
			||||||
 | 
					                                                    // Get current positioning values and recalculate
 | 
				
			||||||
 | 
					                                                    if let Ok(current_top) = event_style.get_property_value("top") {
 | 
				
			||||||
 | 
					                                                        if current_top.ends_with("px") {
 | 
				
			||||||
 | 
					                                                            if let Ok(top_px) = current_top[..current_top.len()-2].parse::<f64>() {
 | 
				
			||||||
 | 
					                                                                let new_top = top_px * scale_factor;
 | 
				
			||||||
 | 
					                                                                let _ = event_style.set_property("top", &format!("{:.2}px", new_top));
 | 
				
			||||||
                                                            }
 | 
					                                                            }
 | 
				
			||||||
                                                        }
 | 
					                                                        }
 | 
				
			||||||
                                                    }
 | 
					                                                    }
 | 
				
			||||||
 | 
					                                                    
 | 
				
			||||||
 | 
					                                                    if let Ok(current_height) = event_style.get_property_value("height") {
 | 
				
			||||||
 | 
					                                                        if current_height.ends_with("px") {
 | 
				
			||||||
 | 
					                                                            if let Ok(height_px) = current_height[..current_height.len()-2].parse::<f64>() {
 | 
				
			||||||
 | 
					                                                                let new_height = height_px * scale_factor;
 | 
				
			||||||
 | 
					                                                                let _ = event_style.set_property("height", &format!("{:.2}px", new_height));
 | 
				
			||||||
 | 
					                                                            }
 | 
				
			||||||
 | 
					                                                        }
 | 
				
			||||||
 | 
					                                                    }
 | 
				
			||||||
 | 
					                                                }
 | 
				
			||||||
 | 
					                                            }
 | 
				
			||||||
 | 
					                                        }
 | 
				
			||||||
 | 
					                                        
 | 
				
			||||||
 | 
					                                        web_sys::console::log_1(&format!("Height: {:.2}, Original base-unit: {:.2}, New base-unit: {:.2}, Scale factor: {:.2}", 
 | 
				
			||||||
 | 
					                                            actual_height, original_base_unit, actual_base_unit, scale_factor).into());
 | 
				
			||||||
 | 
					                                    }
 | 
				
			||||||
 | 
					                                }
 | 
				
			||||||
                            }
 | 
					                            }
 | 
				
			||||||
                        }
 | 
					                        }
 | 
				
			||||||
                    };
 | 
					                    };
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user