Enhanced AG Grid Functionality with Clean Styles

Adds vibrant row hover effect, conditional status cell styling for test and sample status, static red background for emergency rows, and cleans up styles for specific elements.

Από την 14/04/2025. Δείτε την τελευταία έκδοση.

θα χρειαστεί να εγκαταστήσετε μια επέκταση όπως το Tampermonkey, το Greasemonkey ή το Violentmonkey για να εγκαταστήσετε αυτόν τον κώδικα.

You will need to install an extension such as Tampermonkey to install this script.

θα χρειαστεί να εγκαταστήσετε μια επέκταση όπως το Tampermonkey ή το Violentmonkey για να εγκαταστήσετε αυτόν τον κώδικα.

θα χρειαστεί να εγκαταστήσετε μια επέκταση όπως το Tampermonkey ή το Userscripts για να εγκαταστήσετε αυτόν τον κώδικα.

You will need to install an extension such as Tampermonkey to install this script.

Θα χρειαστεί να εγκαταστήσετε μια επέκταση διαχείρισης κώδικα χρήστη για να εγκαταστήσετε αυτόν τον κώδικα.

(Έχω ήδη έναν διαχειριστή κώδικα χρήστη, επιτρέψτε μου να τον εγκαταστήσω!)

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

(Έχω ήδη έναν διαχειριστή στυλ χρήστη, επιτρέψτε μου να τον εγκαταστήσω!)

// ==UserScript==
// @name         Enhanced AG Grid Functionality with Clean Styles
// @version      3.8
// @description  Adds vibrant row hover effect, conditional status cell styling for test and sample status, static red background for emergency rows, and cleans up styles for specific elements.
// @match        *://his.kaauh.org/lab/*
// @author       Hamad AlShegifi
// @grant        GM_addStyle
// @namespace    http://tampermonkey.net/
// ==/UserScript==

(function () {
    'use strict';

    // Inject CSS for hover effect, status cell styling, and emergency highlighting
    GM_addStyle(`
        .ag-row {
            transition: background-color 0.3s ease;
        }
        .vibrant-hover {
            /* Background color and text color are now applied to cells within the hovered row */
        }
        .ag-row.vibrant-hover .ag-cell {
            background-color: #87dced !important; /* Light blue color */
            color: black !important; /* Black text color */
            font-weight: bold !important; /* Bold font */
        }
        .ag-cell[col-id="testStatus"].status-verified-level2,
        .ag-cell[col-id="testStatus"].status-verified-level1 {
            background-color: #90EE90 !important; /* Light green color */
        }
        .ag-cell[col-id="testStatus"].status-ordered {
            background-color: #FFFFE0 !important; /* Light yellow color */
        }
        .ag-cell[col-id="testStatus"].status-resulted {
            background-color: #FFA500 !important; /* Orange color */
            color: black !important; /* Ensure text is readable on orange */
        }
        .ag-cell[col-id="testStatus"].status-cancelled {
            background-color: #000000 !important; /* Brown color */
            color: white !important; /* White text for contrast */
        }
        .emergency-row {
            background-color: #ffe0e0 !important; /* Light red */
        }
        .ag-cell[col-id="sampleStatus"].status-received {
            background-color: #90EE90 !important; /* Light green color for Received sample status */
        }
    `);

    // Clean styles for specific links and spans
    function applyCleanStyles() {
        const anchor = document.querySelector('li > a[href="#/lab-orders/doctor-request"]');
        if (anchor) {
            anchor.style.setProperty('white-space', 'nowrap', 'important');
            anchor.style.setProperty('font-size', '13px', 'important');
            anchor.style.setProperty('overflow', 'visible', 'important');
            anchor.style.setProperty('text-overflow', 'unset', 'important');

            const spans = anchor.querySelectorAll('span');
            spans.forEach(span => {
                span.style.setProperty('display', 'inline', 'important');
                span.style.setProperty('font-size', '13px', 'important');
                span.style.setProperty('white-space', 'nowrap', 'important');
            });
        }

        const simplifySpan = (selector) => {
            const span = document.querySelector(selector);
            if (span) {
                span.style.setProperty('display', 'inline', 'important');
                span.style.setProperty('font-size', '20px', 'important');
                span.style.setProperty('white-space', 'nowrap', 'important');
                span.style.setProperty('overflow', 'visible', 'important');
                span.style.setProperty('text-overflow', 'unset', 'important');
                span.textContent = span.textContent.replace(/\s+/g, ''); // Optional cleanup
            }
        };

        simplifySpan('span.to-do');
        simplifySpan('span.pending-orders');
    }

    // Debounce for applying clean styles
    function debounce(func, wait) {
        let timeout;
        return function(...args) {
            clearTimeout(timeout);
            timeout = setTimeout(() => func.apply(this, args), wait);
        };
    }

    const debouncedStyleUpdater = debounce(applyCleanStyles, 300);
    const observer = new MutationObserver(debouncedStyleUpdater);
    observer.observe(document.body, { childList: true, subtree: true });

    // Apply hover effects
    const targetColumnIdsForHover = [
        "orderNo", "testId", "testDescription", "clusterMrn",
        "hospitalMrn", "patientName", "dob", "nationalIqamaId",
        "department", "clinic", "doctor", "analyzer",
        "orderDateAndTime", "lastUpdatedDate", "sampleStatus",
        "referenceLab", "accessionNo", "barcode", "sequenceNo",
        "primaryPatientId", "referenceLabDesc", "testStatus",
        "orderLastModifiedOnEpoch", "orderCreatedOnEpoch", "equipmentName", "doctorName", "localMrn",
        "dateOfBirth", "idNumber"
    ];

    function applyHoverEffect() {
        document.querySelectorAll('.ag-cell').forEach(cell => {
            const colId = cell.getAttribute('col-id');
            if (colId && targetColumnIdsForHover.includes(colId)) {
                const row = cell.closest('.ag-row'); // Find the parent row
                if (row) {
                    // Add hover effect to the entire row on mouseenter
                    cell.addEventListener('mouseenter', () => {
                        row.classList.add('vibrant-hover'); // Add hover effect to the row
                    });
                    // Remove hover effect on mouseleave
                    cell.addEventListener('mouseleave', () => {
                        row.classList.remove('vibrant-hover'); // Remove hover effect from the row
                    });
                }
            }
        });
    }

    // Apply conditional background color for test and sample statuses
    function applyStatusCellStyle() {
        document.querySelectorAll('.ag-cell[col-id="testStatus"]').forEach(cell => {
            const statusValue = cell.textContent.trim();
            cell.classList.remove('status-verified-level2', 'status-verified-level1', 'status-ordered', 'status-resulted', 'status-cancelled'); // Remove previous styles

            if (statusValue === "VerifiedLevel2" || statusValue === "VerifiedLevel1") {
                cell.classList.add('status-verified-level2');
            } else if (statusValue === "Ordered") {
                cell.classList.add('status-ordered');
            } else if (statusValue === "Resulted") {
                cell.classList.add('status-resulted');
            } else if (statusValue === "Cancelled") {
                cell.classList.add('status-cancelled'); // Apply brown color for Cancelled
            }
        });

        // Apply style for Sample Status = Received
        document.querySelectorAll('.ag-cell[col-id="sampleStatus"]').forEach(cell => {
            if (cell.textContent.trim() === "Received") {
                cell.classList.add('status-received');
            } else {
                cell.classList.remove('status-received'); // Ensure the class is removed if the value changes
            }
        });
    }

    // Highlight emergency rows based on clinic column
    function highlightEmergencyRows() {
        const rows = document.querySelectorAll('div[role="row"]');
        rows.forEach(row => {
            const clinicCell = row.querySelector('div[col-id="clinic"]');
            if (clinicCell && clinicCell.textContent.trim() === 'EMERGENCY') {
                row.classList.add('emergency-row');
            } else {
                row.classList.remove('emergency-row'); // Remove the class if the condition is no longer met
            }
        });
    }

    const observerForGrid = new MutationObserver(() => {
        applyHoverEffect();
        applyStatusCellStyle();
        highlightEmergencyRows(); // Call highlightEmergencyRows on every DOM change
    });

    const gridBodyViewport = document.querySelector('.ag-body-viewport'); // Observe the grid body viewport
    if (gridBodyViewport) {
        observerForGrid.observe(gridBodyViewport, { childList: true, subtree: false }); // subtree should be false here as we are observing direct children (rows)
    } else {
        console.warn("AG Grid body viewport not found. Falling back to body observer.");
        observerForGrid.observe(document.body, { childList: true, subtree: true });
    }

    window.addEventListener('load', () => {
        applyHoverEffect();
        applyStatusCellStyle();
        highlightEmergencyRows(); // Initial call to highlight emergency rows
    });

    // Set the dropdown value for pagination to 100
    function setDropdownValue() {
        const dropdown = document.getElementById("dropdownPaginationPageSize");
        if (dropdown && dropdown.value !== "100") {
            dropdown.value = "100"; // Set the value to "100"

            // Trigger the 'change' event
            const event = new Event('change', { bubbles: true });
            dropdown.dispatchEvent(event);

            console.log("Dropdown value set to 100");
        }
    }

    // Observe changes in the DOM for the dropdown
    function observeDOMForDropdown() {
        const observer = new MutationObserver(() => {
            setDropdownValue(); // Check and set the dropdown value when changes are detected
        });

        // Observe the entire document for changes
        observer.observe(document.body, {
            childList: true,
            subtree: true,
        });

        console.log("MutationObserver is active for dropdown");
    }

    window.addEventListener('load', () => {
        setDropdownValue(); // Initial check
        observeDOMForDropdown(); // Start observing for dynamic changes
    });

})();