- // ==UserScript==
- // @name Enhanced AG Grid Functionality
- // @version 3.5
- // @description Adds vibrant row hover effect (overriding all cell colors), conditional status cell styling for test status and sample status, static red background for emergency rows in AG Grid.
- // @match https://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 */
- }
- `);
-
- // List of `col-id` attributes to target for hover effect
- 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"
- ];
-
- const columnsToUncheck = [
- 'Lab Order No', 'Hospital MRN', 'DOB', 'Test ID', 'National/Iqama Id',
- 'Department', 'Doctor', 'Analyzer', 'Reference Lab',
- 'Accession No', 'Sequence No','Age','Container Type','Storage Condition'
- ];
-
- let hasRunOnce = false; // Prevents running the column unchecking code more than once
-
- function isSpecificPage() {
- return window.location.href.endsWith('/#/lab-orders/lab-test-analyzer');
- }
-
- function areColumnsChecked() {
- return columnsToUncheck.some(column => isColumnChecked(column));
- }
-
- function isColumnChecked(labelText) {
- const labels = document.querySelectorAll('.ag-column-tool-panel-column-label');
- for (const label of labels) {
- if (label.textContent.trim() === labelText) {
- const checkbox = label.parentElement.querySelector('.ag-icon-checkbox-checked');
- if (checkbox) return true; // Column is checked
- }
- }
- return false; // Column is not checked
- }
-
- function ensureColumnsUnchecked() {
- if (hasRunOnce || !isSpecificPage()) return;
- if (!areColumnsChecked()) return; // Do nothing if columns are not checked
-
- hasRunOnce = true;
- console.log("Unchecking checked columns...");
-
- setTimeout(() => {
- columnsToUncheck.forEach(column => clickColumnLabel(column));
- }, 1000);
- }
-
- function ensureOtherColumnsChecked() {
- if (!isSpecificPage()) return;
- console.log("Ensuring all other columns are checked...");
-
- const allLabels = document.querySelectorAll('.ag-column-tool-panel-column-label');
- allLabels.forEach(label => {
- const labelText = label.textContent.trim();
- if (!columnsToUncheck.includes(labelText)) {
- const checkbox = label.parentElement.querySelector('.ag-icon-checkbox-unchecked');
- if (checkbox) {
- label.click(); // Click to check the column if unchecked
- }
- }
- });
- }
-
- function clickColumnLabel(labelText) {
- if (!isSpecificPage()) return;
- const labels = document.querySelectorAll('.ag-column-tool-panel-column-label');
- labels.forEach(label => {
- if (label.textContent.trim() === labelText) {
- const checkbox = label.parentElement.querySelector('.ag-icon-checkbox-checked');
- if (checkbox) {
- label.click(); // Click only if checked
- }
- }
- });
- }
-
- 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
- }
- });
- }
-
- function initColumnToggle() {
- if (!isSpecificPage()) return;
- console.log("Checking if columns need to be unchecked and highlighting emergency rows...");
-
- let attempts = 0;
- const interval = setInterval(() => {
- if (document.querySelector('.ag-side-buttons')) {
- ensureColumnsUnchecked();
- ensureOtherColumnsChecked();
- highlightEmergencyRows(); // Call the highlighting function here
- clearInterval(interval);
- }
- if (++attempts > 10) {
- highlightEmergencyRows(); // Ensure highlighting runs even if sidebar isn't found quickly
- clearInterval(interval);
- }
- }, 500);
-
- // Also run highlighting on initial load attempt
- highlightEmergencyRows();
- }
-
- // Function to apply hover effects to the entire row when any target cell is hovered
- 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
- });
- }
- }
- });
- }
-
- // Function to apply conditional background color to the "Status" column
- 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
- }
- });
- }
-
- const observer = new MutationObserver(() => {
- applyHoverEffect();
- applyStatusCellStyle();
- highlightEmergencyRows(); // Call highlightEmergencyRows on every DOM change
-
- if (isSpecificPage()) {
- hasRunOnce = false; // Reset run flag for repeated executions
- initColumnToggle();
- }
- });
-
- // **Important: Observing the correct AG Grid body viewport**
- const gridBodyViewport = document.querySelector('.ag-body-viewport'); // Observe the grid body viewport
- if (gridBodyViewport) {
- observer.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.");
- observer.observe(document.body, { childList: true, subtree: true });
- }
-
-
- window.addEventListener('load', () => {
- applyHoverEffect();
- applyStatusCellStyle();
- if (isSpecificPage()) {
- initColumnToggle();
- }
- });
-
- // Function to set the dropdown value (keeping this separate as it seems independent)
- (function() {
- 'use strict';
-
- // Function to set the dropdown value
- 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");
- }
- }
-
- // Function to 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");
- }
-
- // Run the function when the page is fully loaded
- window.addEventListener('load', () => {
- setDropdownValue(); // Initial check
- observeDOMForDropdown(); // Start observing for dynamic changes
- });
- })();
-
- })();