From e81b8e227f46c536714a3f36c9e853f929e92df4 Mon Sep 17 00:00:00 2001 From: Ling Zheng Date: Thu, 6 Nov 2025 12:10:15 -0500 Subject: [PATCH] Refactor TDX-Enhanced to Chrome extension with RCAC Halcyon integration. Updated manifest details, removed userscript, added new styles and UI elements for API key input, and initialized Halcyon on ticket detail pages. --- content/content.js | 16 + content/modules/halcyon.js | 539 +++++ content/modules/ui.js | 8 + content/styles.css | 18 +- manifest.json | 12 +- userscript.js | 4010 ------------------------------------ 6 files changed, 588 insertions(+), 4015 deletions(-) create mode 100644 content/modules/halcyon.js delete mode 100644 userscript.js diff --git a/content/content.js b/content/content.js index 720a6cb..9c58260 100644 --- a/content/content.js +++ b/content/content.js @@ -39,6 +39,22 @@ parseTicket() parseOtherElements() // Call parseOtherElements to inject styles into shadow DOMs (matches original) checkPath() + + // Initialize RCAC Halcyon integration on ticket detail pages + if (window.location.pathname.includes('/TDNext/Apps/33/Tickets/TicketDet.aspx')) { + // Wait for the requestor panel to be available before initializing halcyon + function tryInitHalcyon() { + const requestorPanel = document.querySelector("#divContent > div:nth-child(1) > div.col-md-5.col-sm-5.gutter-top > div.panel.panel-default.panel-person-card"); + if (requestorPanel && typeof initHalcyon === 'function') { + initHalcyon(); + } else if (!requestorPanel) { + // Retry after a short delay if element not found yet + setTimeout(tryInitHalcyon, 200); + } + } + // Start trying after a short initial delay + setTimeout(tryInitHalcyon, 300); + } } // Wait for DOM to be ready diff --git a/content/modules/halcyon.js b/content/modules/halcyon.js new file mode 100644 index 0000000..8cd6425 --- /dev/null +++ b/content/modules/halcyon.js @@ -0,0 +1,539 @@ +// RCAC Halcyon API integration module + +function initHalcyon() { + "use strict"; + + const BASE = "https://www.rcac.purdue.edu"; + + // grab api from settings + function getApiToken() { + const apiKey = settings('get', 'rcacApiKey'); + return apiKey || null; + } + + // Shared style constants using extension CSS variables + const PANEL_STYLE = "margin:0;border:0;background:var(--bg-0);color:var(--txt-1);"; + const HEAD_STYLE = "border-bottom:1px solid var(--border-0);background:var(--bg-0);color:var(--txt-1);"; + const BODY_STYLE = "padding:10px;background:var(--bg-0);color:var(--txt-1);"; + + const requestorPanel = document.querySelector("#divContent > div:nth-child(1) > div.col-md-5.col-sm-5.gutter-top > div.panel.panel-default.panel-person-card"); + if (!requestorPanel) return; + + const mailLink = requestorPanel.querySelector('a[href^="mailto:"]'); + if (!mailLink) return makeBubble(requestorPanel, "Requester email not found."); + + const email = (mailLink.getAttribute("href") || "").replace(/^mailto:/i, "").trim(); + if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email)) { + return makeBubble(requestorPanel, "Invalid requester email."); + } + + const apiToken = getApiToken(); + if (!apiToken || apiToken.trim() === "" || apiToken === "Enter API KEY") { + return makeBubble(requestorPanel, "Halcyon API key not configured. Please set it in extension settings."); + } + + const bubble = makeBubble(requestorPanel, "Looking up user…"); + doInitial(email, bubble); + + function doInitial(email, bubble) { + lookupUserByEmail(email, { timeoutMs: 3000 }) + .then((items) => { + if (!items.length) { + bubble.innerHTML = renderPanel(emptyStateWithRetry("No matching users were found.")); + attachRetry(bubble, () => doInitial(email, bubble)); + return; + } + bubble.innerHTML = renderLinksPanel(items); + wireExpandHandlers(bubble); + }) + .catch((err) => { + const msg = err?.auth ? "Authentication failed. Please check your API key." : err?.timeout ? "Request timed out." : "Network error."; + bubble.innerHTML = renderPanel(emptyStateWithRetry(msg)); + attachRetry(bubble, () => doInitial(email, bubble)); + }); + } + + function wireGroupExpandHandlers(detail) { + // Remove any existing listeners to prevent duplicates + const existingHandler = detail._rcacGroupHandler; + if (existingHandler) { + detail.removeEventListener("click", existingHandler); + } + + const handler = (e2) => { + // Check if this is a link click - let links work normally + if (e2.target.tagName === 'A' || e2.target.closest('a')) { + return; // Let link clicks work normally + } + + // Check if this is a group expand button click + const gbtn = e2.target.closest(".rcac-group-expand"); + if (!gbtn) { + // Not a group expand button, let other clicks work normally + return; + } + + // Only prevent default for the expand button + e2.preventDefault(); // Prevent default button behavior + e2.stopPropagation(); // Prevent event bubbling that could crash TDX + e2.stopImmediatePropagation(); // Stop all other handlers + + // Prevent any form submission or navigation + if (gbtn.type === 'submit') { + gbtn.type = 'button'; + } + + const id = gbtn.getAttribute("data-group-id"); + const body = detail.querySelector(`.rcac-group-body[data-group-id="${cssEscape(id)}"]`); + if (!body) return; + + const hidden = body.style.display === "none"; + body.style.display = hidden ? "block" : "none"; + gbtn.textContent = hidden ? "Hide queues" : "Show queues"; + + return false; // Ensure no further processing + }; + + detail._rcacGroupHandler = handler; + detail.addEventListener("click", handler); + } + + function wireExpandHandlers(root) { + // Prevent duplicate event listeners + if (root._rcacExpandHandler) return; + + const handler = async (ev) => { + const btn = ev.target.closest(".rcac-expand-btn"); + if (!btn) return; + + ev.preventDefault(); + ev.stopPropagation(); + + const li = btn.closest("li[data-user-id]"); + if (!li) return; + + const userId = li.getAttribute("data-user-id"); + const detail = li.querySelector(".rcac-details"); + + if (li.dataset.loaded === "1") { + const hidden = detail.style.display === "none"; + detail.style.display = hidden ? "block" : "none"; + btn.textContent = hidden ? "Collapse" : "Expand"; + return; + } + + btn.disabled = true; + btn.textContent = "Loading…"; + detail.style.display = "block"; + detail.innerHTML = miniLoading(); + + try { + const notes = []; + + // Fetch memberships + const membershipsJson = await safeApiGET("/api/queues/users", { + userid: String(userId), + limit: "999" + }, { timeoutMs: 8000 }); + + const memberships = Array.isArray(membershipsJson?.data) ? membershipsJson.data : []; + if (!membershipsJson) notes.push("queues/users failed"); + + // Fetch queue details + const queueIds = dedupe(memberships.map((m) => m.queueid).filter(Boolean)); + const queues = queueIds.length + ? (await pAll( + queueIds.map((qid) => () => safeApiGET(`/api/queues/${qid}`, { expand: "resource,group" })), + 8 + )).filter(Boolean) + : []; + + if (queueIds.length && !queues.length) notes.push("queue details failed"); + + // Extract clusters + const clusters = dedupe( + queues.map((q) => pickClusterName(q?.resource)).filter(Boolean) + ).sort(); + + // Build groups map + const groupsMap = new Map(); + for (const q of queues) { + const g = q?.group; + if (!g?.id) continue; + if (!groupsMap.has(g.id)) { + groupsMap.set(g.id, { id: g.id, name: g.name || `Group #${g.id}`, owneruserid: g.owneruserid || null, queues: [], piName: null }); + } + groupsMap.get(g.id).queues.push(q); + } + + // Fetch group memberships + const gmJson = await safeApiGET("/api/groups/members", { + userid: String(userId), + state: "all", + limit: "999", + expand: "group" + }, { timeoutMs: 8000 }); + + if (!gmJson) notes.push("groups/members failed"); + const gm = Array.isArray(gmJson?.data) ? gmJson.data : []; + for (const m of gm) { + const gid = m.groupid || m.group?.id; + if (!gid) continue; + if (!groupsMap.has(gid)) { + groupsMap.set(gid, { + id: gid, + name: m.group?.name || `Group #${gid}`, + owneruserid: m.group?.owneruserid || null, + queues: [], + piName: null + }); + } else { + const g = groupsMap.get(gid); + if (m.group?.name && !g.name) g.name = m.group.name; + if (m.group?.owneruserid && !g.owneruserid) g.owneruserid = m.group.owneruserid; + } + } + + // Fetch PI names + const ownerIds = dedupe([...groupsMap.values()].map((g) => g.owneruserid).filter(Boolean)); + if (ownerIds.length) { + const owners = (await pAll(ownerIds.map((oid) => () => safeApiGET(`/api/users/${oid}`)), 8)).filter(Boolean); + const ownerNameById = new Map(owners.map((u) => [u.id, u.name || u.username || `User #${u.id}`])); + for (const g of groupsMap.values()) { + if (g.owneruserid && ownerNameById.has(g.owneruserid)) g.piName = ownerNameById.get(g.owneruserid); + } + } + + const groupsArr = [...groupsMap.values()].sort((a, b) => a.name.localeCompare(b.name)); + + if (clusters.length === 0 && groupsArr.length === 0 && notes.length === 0) { + notes.push("No data found"); + } + + detail.innerHTML = renderDetail({ clusters, groups: groupsArr, notes }); + wireGroupExpandHandlers(detail); + + li.dataset.loaded = "1"; + btn.disabled = false; + btn.textContent = "Collapse"; + } catch (e) { + detail.innerHTML = `
Failed to load details: ${escapeHTML(e?.message || String(e))}
`; + btn.disabled = false; + btn.textContent = "Expand"; + } + }; + + root._rcacExpandHandler = handler; + root.addEventListener("click", handler); + } + + // ===== lookups ===== + async function lookupUserByEmail(email, { timeoutMs = 3000 } = {}) { + // Try username first (faster for Purdue emails), then fall back to full email if needed + const local = email.split("@")[0]; + + // First try username search (most common case for Purdue emails) + try { + const usernameResult = await apiGET("/api/users", { search: local }, { timeoutMs }); + if (usernameResult && Array.isArray(usernameResult.data) && usernameResult.data.length > 0) { + return usernameResult.data + .map((u) => { + const adminUrl = apiToAdminUrl(u.api) || `${BASE}/admin/users/${u.id}`; + return u.id && adminUrl ? { + name: u.name || "Unnamed user", + id: u.id, + username: u.username, + puid: u.puid, + email: u.email, + adminUrl + } : null; + }) + .filter(Boolean); + } + } catch (e) { + // If username search fails, continue to email search + } + + // Fall back to full email search (for non-Purdue emails or if username search found nothing) + try { + const emailResult = await apiGET("/api/users", { search: email }, { timeoutMs }); + if (emailResult && Array.isArray(emailResult.data) && emailResult.data.length > 0) { + return emailResult.data + .map((u) => { + const adminUrl = apiToAdminUrl(u.api) || `${BASE}/admin/users/${u.id}`; + return u.id && adminUrl ? { + name: u.name || "Unnamed user", + id: u.id, + username: u.username, + puid: u.puid, + email: u.email, + adminUrl + } : null; + }) + .filter(Boolean); + } + } catch (e) { + // If both searches fail, return empty array + } + + return []; + } + + // ===== API core ===== + function apiGET(pathOrUrl, params = {}, opts = {}) { + const url = (pathOrUrl.startsWith("http") ? pathOrUrl : BASE + pathOrUrl) + buildQuery(params); + const timeout = Number(opts.timeoutMs) || 8000; + const apiToken = getApiToken(); + + if (!apiToken) { + return Promise.reject({ auth: true }); + } + + const controller = new AbortController(); + const timeoutId = setTimeout(() => controller.abort(), timeout); + + return fetch(url, { + method: "GET", + headers: { + Accept: "application/json", + Authorization: `Bearer ${apiToken}` + }, + signal: controller.signal + }) + .then((resp) => { + clearTimeout(timeoutId); + if (resp.status === 401 || resp.status === 403) { + throw { auth: true }; + } + if (resp.status < 200 || resp.status >= 300) { + throw { status: resp.status }; + } + return resp.json(); + }) + .catch((err) => { + clearTimeout(timeoutId); + if (err.name === 'AbortError') { + throw { timeout: true }; + } + if (err.auth || err.status) { + throw err; + } + throw { cors: true }; + }); + } + + async function safeApiGET(path, params = {}, opts = {}) { + try { + // don't over-munge expand; server accepts "resource,group" or "resource, group" + return await apiGET(path, params, opts); + } catch (e) { + return null; + } + } + + // ===== rendering ===== + function makeBubble(referencePanel, initialText) { + const container = document.createElement("div"); + container.style.marginTop = "8px"; + container.style.border = `1px solid var(--border-0)`; + container.style.borderRadius = "4px"; + container.style.boxShadow = "0 1px 1px var(--shadow-2)"; + container.style.background = "var(--bg-0)"; + container.innerHTML = renderPanel(initialText || ""); + referencePanel.insertAdjacentElement("afterend", container); + return container; + } + + function renderPanel(contentText) { + return ` +
+
+ RCAC Lookup +
+
+
${escapeHTML(contentText)}
+
+
+ `; + } + + function emptyStateWithRetry(text) { + return `${escapeHTML(text)} `; + } + function attachRetry(root, fn) { + const btn = root.querySelector(".rcac-retry"); + if (!btn) return; + btn.addEventListener("click", () => fn()); + } + + function renderLinksPanel(items) { + const liBorder = "border-bottom:1px solid var(--border-0);"; + + const list = items.map(({ name, id, username, puid, email, adminUrl }) => { + const bits = [ + email ? escapeHTML(email) : null, + id ? `ID: ${escapeHTML(String(id))}` : null, + username ? `@${escapeHTML(username)}` : null, + puid ? `PUID: ${escapeHTML(String(puid))}` : null + ].filter(Boolean).join(" • "); + return ` +
  • +
    + ${escapeHTML(name)} +
    +
    ${bits}
    +
    + +
    + +
  • `; + }).join(""); + + return ` +
    +
    + RCAC Lookup +
    +
    +
      + ${list} +
    +
    +
    `; + } + + function renderDetail({ clusters, groups, notes = [] }) { + const title = (t) => + `
    ${escapeHTML(t)}
    `; + const chips = (items) => + `
    ${items.map( + (c) => `${escapeHTML(c)}` + ).join("")}
    `; + + const groupsHtml = groups.length === 0 + ? `
    No groups found.
    ` + : groups.map((g) => { + const groupUrl = `https://www.rcac.purdue.edu/account/groups/${g.id}`; + const header = ` +
    +
    +
    + ${escapeHTML(g.name)} +
    +
    PI: ${escapeHTML(g.piName || "Unknown")}
    +
    + +
    `; + + const qList = g.queues.length === 0 ? "" : + ``; + + return ` +
    + ${header} + +
    `; + }).join('
    '); + + const notesHtml = notes.length + ? `
    Note: ${escapeHTML(notes.join("; "))}
    ` + : ""; + + return ` +
    + ${title("Clusters")}${clusters.length ? chips(clusters) : `
    None detected
    `} + ${title("Groups")} + ${groupsHtml} + ${notesHtml} +
    `; + } + + // ===== utils ===== + function dedupe(arr) { return [...new Set(arr)]; } + + function apiToAdminUrl(apiUrl) { + try { + const u = new URL(apiUrl); + const path = u.pathname.replace(/^\/api\//, "/admin/"); + return `${u.origin}${path}`; + } catch { return ""; } + } + + function buildQuery(params) { + const kv = Object.entries(params).filter(([, v]) => v !== undefined && v !== null && v !== ""); + if (!kv.length) return ""; + const qs = kv.map(([k, v]) => `${encodeURIComponent(k)}=${encodeURIComponent(String(v))}`).join("&"); + return `?${qs}`; + } + + function pAll(tasks, concurrency = 8) { + const results = []; + let i = 0, active = 0; + return new Promise((resolve) => { + const next = () => { + if (i >= tasks.length && active === 0) return resolve(results); + while (active < concurrency && i < tasks.length) { + const idx = i++; + active++; + tasks[idx]().then((r) => (results[idx] = r)).catch(() => (results[idx] = null)).finally(() => { + active--; next(); + }); + } + }; + next(); + }); + } + + function pickClusterName(resource) { + if (!resource) return null; + return resource.rolename || resource.listname || resource.name || null; + } + + function readWalltime(queue) { + const wt = Array.isArray(queue?.walltimes) && queue.walltimes[0]?.walltime; + if (!wt) return ""; + const secs = Number(wt); + if (!Number.isFinite(secs)) return ""; + const d = Math.floor(secs / 86400); + const h = Math.floor((secs % 86400) / 3600); + const m = Math.floor((secs % 3600) / 60); + const out = []; + if (d) out.push(`${d}d`); + if (h) out.push(`${h}h`); + if (m) out.push(`${m}m`); + return out.join(" ") || `${secs}s`; + } + + function miniLoading() { + return `
    Loading…
    `; + } + + function escapeHTML(s) { + return String(s).replace(/[&<>"']/g, (ch) => ({ "&":"&","<":"<",">":">","\"":""","'":"'" }[ch])); + } + + function cssEscape(s) { + // Escape quotes and other special characters for CSS attribute selectors + return String(s).replace(/"/g, '\\"').replace(/'/g, "\\'"); + } +} + diff --git a/content/modules/ui.js b/content/modules/ui.js index 977068c..14ed440 100644 --- a/content/modules/ui.js +++ b/content/modules/ui.js @@ -98,6 +98,14 @@ async function injectToolbar() {
    +
    +

    RCAC Integration

    +
    + + +
    API key for RCAC Halcyon lookup integration
    +
    +
    diff --git a/content/styles.css b/content/styles.css index f84298b..fb41106 100644 --- a/content/styles.css +++ b/content/styles.css @@ -2272,7 +2272,23 @@ color: var(--col-400); } .tdx-hover-darken:hover { -color: var(--col-300); + color: var(--col-300); +} + +/* RCAC Halcyon Integration Styles */ +.rcac-expand-btn, .rcac-retry, .rcac-group-expand { + transition: background-color 0.2s, border-color 0.2s, color 0.2s; +} + +.rcac-expand-btn:hover:not(:disabled), .rcac-retry:hover, .rcac-group-expand:hover:not(:disabled) { + background-color: var(--col-200) !important; + border-color: var(--border-1) !important; + color: var(--txt-2) !important; +} + +.rcac-expand-btn:disabled, .rcac-group-expand:disabled { + opacity: 0.6; + cursor: not-allowed; } .form-group>a, .form-group>.checkbox>a, .disp-group>a, .form-group>.control-label>a, .checkbox>label>a { diff --git a/manifest.json b/manifest.json index 9ee2e3e..014b27a 100644 --- a/manifest.json +++ b/manifest.json @@ -1,9 +1,9 @@ { "manifest_version": 3, - "name": "tdx-enhanced", + "name": "TDX-Enhanced", "version": "0.1.0", - "description": "Enhanced TDX coloring & formatting. Follows system color scheme.", - "author": "Purdue STEM IT - it@purdue.edu", + "description": "TDX-Enhanced userscript converted to Chrome extension. Includes RCAC Halcyon API integration for TDNext ticket detail pages.", + "author": "Purdue RCAC - rcac@purdue.edu", "permissions": [ "storage" ], @@ -22,7 +22,10 @@ "https://service.purdue.edu/*", "https://purdue.teamdynamixpreview.com/*", "https://it.purdue.edu/*", - "https://engineering.purdue.edu/*" + "https://engineering.purdue.edu/*", + "https://www.rcac.purdue.edu/*", + "https://rcac.purdue.edu/*", + "https://*.rcac.purdue.edu/*" ], "content_scripts": [ { @@ -47,6 +50,7 @@ "content/modules/parsing.js", "content/modules/ui.js", "content/modules/observer.js", + "content/modules/halcyon.js", "content/content.js" ], "run_at": "document_end" diff --git a/userscript.js b/userscript.js deleted file mode 100644 index bd9a6ba..0000000 --- a/userscript.js +++ /dev/null @@ -1,4010 +0,0 @@ -// ==UserScript== -// @name tdx-enhanced -// @namespace purdue-it -// @version 2025-07-31-01 -// @description enhanced tdx coloring & formatting. follows system color scheme. -// @author Purdue STEM IT - it@purdue.edu -// @match https://service.purdue.edu/TDWorkManagement* -// @match https://service.purdue.edu/tdworkmanagement* -// @match https://service.purdue.edu/TDNext* -// @match https://service.purdue.edu/TDWebApi* -// @match https://purdue.teamdynamixpreview.com/TDWorkManagement* -// @match https://purdue.teamdynamixpreview.com/TDNext* -// @require https://momentjs.com/downloads/moment.min.js -// @require https://cdnjs.cloudflare.com/ajax/libs/tinycolor/1.6.0/tinycolor.min.js -// @downloadURL https://raw.github.itap.purdue.edu/remender/tdx-userscript-rcac/refs/heads/main/tdx-enhanced.js -// @updateURL https://raw.github.itap.purdue.edu/remender/tdx-userscript-rcac/refs/heads/main/tdx-enhanced.js -// @grant GM_getResourceText -// @grant GM_addStyle -// @run-at document-end -// ==/UserScript== - -(function() { - 'use strict'; - - const primaryTitle = "Purdue University IT" - - /* QUEUE COLORS */ - - //from main webqueue script - var colorsByQueue = { - 'aae': {'bg' : '#7030A0', 'txt' : 'white' }, - 'abe' : {'bg' : '#256f78', 'txt' : 'white'}, - 'bidc' : {'bg' : '#C5FFC5', 'txt' : 'black'}, - 'biology' : {'bg' : '#67c1ee', 'txt' : 'black'}, - 'bme' : {'bg' : '#0D69FF', 'txt' : 'white'}, - 'ce' : {'bg' : '#008000', 'txt' : 'white' }, - 'che' : {'bg' : '#00FF00', 'txt' : 'black'}, - 'chem' : {'bg' : '#ffb1b7', 'txt' : 'black'}, - 'coea' : {'bg' : '#00D6BD', 'txt' : 'black'}, - 'coep' : {'bg' : '#FFDDB7', 'txt' : 'black'}, - 'comp.sci.' : {'bg' : '#772212', 'txt' : 'white'}, - 'dp' : {'bg' : '#0070A8', 'txt' : 'white'}, - 'doe': {'bg' : 'red', 'txt' : 'white'}, - 'ece' : {'bg' : '#FF6600', 'txt' : 'white'}, - 'ecnaccts' : {'bg' : '#98A4AE', 'txt' : 'white'}, - 'students' : {'bg' : '#98A4AE', 'txt' : 'white'}, - 'eaps' : {'bg' : '#629454', 'txt': 'white'}, - 'eee' : {'bg' : '#F66A6A', 'txt' : 'white'}, - 'ene': {'bg' : '#A45CD0', 'txt': 'white' }, - 'epics': {'bg' : '#E399E3', 'txt' : 'black'}, - 'flex' : {'bg' : '#A7ECFF', 'txt' : 'black'}, - 'helpdesk' : {'bg' : '#98A4AE', 'txt' : 'white'}, - 'ie' : {'bg' : '#FFB7B7', 'txt' : 'black'}, - 'imi' : {'bg' : '#FFB96D', 'txt' : 'black'}, - 'apple' : {'bg' : '#666666', 'txt' : 'white'}, - 'mailman' : {'bg' : 'white', 'txt' : 'black'}, - 'math' : {'bg' : '#f7977a', 'txt' : 'black'}, - 'me' : {'bg' : '#b30000', 'txt' : 'white'}, - 'mse': {'bg' : '#EFD3F5', 'txt' : 'black'}, - 'ne': {'bg' : '#af6377', 'txt' : 'white'}, - 'pari' : {'bg' : '#3f5c8a', 'txt': 'white'}, - 'physics' : {'bg' : '#07622f', 'txt': 'white'}, - //'potr' : {'bg' : '#663300', 'txt' : 'white'}, - 'president' : {'bg' : '#cfb991', 'txt' : 'black'}, - 'sitemgrs' : {'bg' : '#98A4AE', 'txt' : 'white'}, - 'stat' : {'bg' : '#ff6f44', 'txt' : 'white'}, - 'swt' : {'bg' : '#000ED6', 'txt' : '#FFEE00'}, - 'polytechnic' : {'bg' : 'black', 'txt' : 'white'}, - 'cnit' : {'bg' : '#434343', 'txt' : 'white'}, - 'uds' : {'bg' : '#98A4AE', 'txt' : 'white'}, - 'udsprojects': {'bg' : '#98A4AE', 'txt' : 'white'}, - //'wang' : {'bg' : '#000099', 'txt' : 'white'}, - 'web' : {'bg' : '#B46086', 'txt' : 'white'}, - 'windows' : {'bg' : '#b77729', 'txt' : 'white'}, - 'zsite' : {'bg' : '#98A4AE', 'txt' : 'white'}, - }; - - var tdxtoolsUrl = "https://engineering.purdue.edu" - - //regex for matching inline highlights - var colorsByStatus = { - '!!': {style: {background: 'var(--col-highlight-1)'}, type: 'highlight', re: new RegExp("\!! (.*) \!!","g")}, - '~~': {style: {background: 'var(--col-highlight-2)'}, type: 'highlight', re: new RegExp("\~~ (.*) \~~","g")}, - } - - var colorScheme - - /* BEGIN FUNCTIONS */ - - //color manipulation via css filters: https://github.com/angel-rs/css-color-filter-generator - //modified to return an object instead of filter string - - class Color { - constructor(r, g, b) { - this.set(r, g, b); - } - - toString() { - return `rgb(${Math.round( - this.r - )}, ${Math.round(this.g)}, ${Math.round(this.b)})`; - } - - set(r, g, b) { - this.r = this.clamp(r); - this.g = this.clamp(g); - this.b = this.clamp(b); - } - - hueRotate(angle = 0) { - angle = (angle / 180) * Math.PI; - const sin = Math.sin(angle); - const cos = Math.cos(angle); - - this.multiply([ - 0.213 + cos * 0.787 - sin * 0.213, - 0.715 - cos * 0.715 - sin * 0.715, - 0.072 - cos * 0.072 + sin * 0.928, - 0.213 - cos * 0.213 + sin * 0.143, - 0.715 + cos * 0.285 + sin * 0.14, - 0.072 - cos * 0.072 - sin * 0.283, - 0.213 - cos * 0.213 - sin * 0.787, - 0.715 - cos * 0.715 + sin * 0.715, - 0.072 + cos * 0.928 + sin * 0.072 - ]); - } - - grayscale(value = 1) { - this.multiply([ - 0.2126 + 0.7874 * (1 - value), - 0.7152 - 0.7152 * (1 - value), - 0.0722 - 0.0722 * (1 - value), - 0.2126 - 0.2126 * (1 - value), - 0.7152 + 0.2848 * (1 - value), - 0.0722 - 0.0722 * (1 - value), - 0.2126 - 0.2126 * (1 - value), - 0.7152 - 0.7152 * (1 - value), - 0.0722 + 0.9278 * (1 - value) - ]); - } - - sepia(value = 1) { - this.multiply([ - 0.393 + 0.607 * (1 - value), - 0.769 - 0.769 * (1 - value), - 0.189 - 0.189 * (1 - value), - 0.349 - 0.349 * (1 - value), - 0.686 + 0.314 * (1 - value), - 0.168 - 0.168 * (1 - value), - 0.272 - 0.272 * (1 - value), - 0.534 - 0.534 * (1 - value), - 0.131 + 0.869 * (1 - value) - ]); - } - - saturate(value = 1) { - this.multiply([ - 0.213 + 0.787 * value, - 0.715 - 0.715 * value, - 0.072 - 0.072 * value, - 0.213 - 0.213 * value, - 0.715 + 0.285 * value, - 0.072 - 0.072 * value, - 0.213 - 0.213 * value, - 0.715 - 0.715 * value, - 0.072 + 0.928 * value - ]); - } - - multiply(matrix) { - const newR = this.clamp( - this.r * matrix[0] + this.g * matrix[1] + this.b * matrix[2] - ); - const newG = this.clamp( - this.r * matrix[3] + this.g * matrix[4] + this.b * matrix[5] - ); - const newB = this.clamp( - this.r * matrix[6] + this.g * matrix[7] + this.b * matrix[8] - ); - this.r = newR; - this.g = newG; - this.b = newB; - } - - brightness(value = 1) { - this.linear(value); - } - contrast(value = 1) { - this.linear(value, -(0.5 * value) + 0.5); - } - - linear(slope = 1, intercept = 0) { - this.r = this.clamp(this.r * slope + intercept * 255); - this.g = this.clamp(this.g * slope + intercept * 255); - this.b = this.clamp(this.b * slope + intercept * 255); - } - - invert(value = 1) { - this.r = this.clamp((value + (this.r / 255) * (1 - 2 * value)) * 255); - this.g = this.clamp((value + (this.g / 255) * (1 - 2 * value)) * 255); - this.b = this.clamp((value + (this.b / 255) * (1 - 2 * value)) * 255); - } - - hsl() { - // Code taken from https://stackoverflow.com/a/9493060/2688027, licensed under CC BY-SA. - const r = this.r / 255; - const g = this.g / 255; - const b = this.b / 255; - const max = Math.max(r, g, b); - const min = Math.min(r, g, b); - let h, - s, - l = (max + min) / 2; - - if (max === min) { - h = s = 0; - } else { - const d = max - min; - s = l > 0.5 ? d / (2 - max - min) : d / (max + min); - switch (max) { - case r: - h = (g - b) / d + (g < b ? 6 : 0); - break; - - case g: - h = (b - r) / d + 2; - break; - - case b: - h = (r - g) / d + 4; - break; - } - h /= 6; - } - - return { - h: h * 100, - s: s * 100, - l: l * 100 - }; - } - - clamp(value) { - if (value > 255) { - value = 255; - } else if (value < 0) { - value = 0; - } - return value; - } - } - - class Solver { - constructor(target, baseColor) { - this.target = target; - this.targetHSL = target.hsl(); - this.reusedColor = new Color(0, 0, 0); - } - - solve() { - const result = this.solveNarrow(this.solveWide()); - return { - values: result.values, - loss: result.loss, - filter: this.css(result.values) - }; - } - - solveWide() { - const A = 5; - const c = 15; - const a = [60, 180, 18000, 600, 1.2, 1.2]; - - let best = { loss: Infinity }; - for (let i = 0; best.loss > 25 && i < 3; i++) { - const initial = [50, 20, 3750, 50, 100, 100]; - const result = this.spsa(A, a, c, initial, 1000); - if (result.loss < best.loss) { - best = result; - } - } - return best; - } - - solveNarrow(wide) { - const A = wide.loss; - const c = 2; - const A1 = A + 1; - const a = [0.25 * A1, 0.25 * A1, A1, 0.25 * A1, 0.2 * A1, 0.2 * A1]; - return this.spsa(A, a, c, wide.values, 500); - } - - spsa(A, a, c, values, iters) { - const alpha = 1; - const gamma = 0.16666666666666666; - - let best = null; - let bestLoss = Infinity; - const deltas = new Array(6); - const highArgs = new Array(6); - const lowArgs = new Array(6); - - for (let k = 0; k < iters; k++) { - const ck = c / Math.pow(k + 1, gamma); - for (let i = 0; i < 6; i++) { - deltas[i] = Math.random() > 0.5 ? 1 : -1; - highArgs[i] = values[i] + ck * deltas[i]; - lowArgs[i] = values[i] - ck * deltas[i]; - } - - const lossDiff = this.loss(highArgs) - this.loss(lowArgs); - - for (let i = 0; i < 6; i++) { - const g = (lossDiff / (2 * ck)) * deltas[i]; - const ak = a[i] / Math.pow(A + k + 1, alpha); - values[i] = fix(values[i] - ak * g, i); - } - - const loss = this.loss(values); - if (loss < bestLoss) { - best = values.slice(0); - bestLoss = loss; - } - } - return { values: best, loss: bestLoss }; - - function fix(value, idx) { - let max = 100; - if (idx === 2 /* saturate */) { - max = 7500; - } else if (idx === 4 /* brightness */ || idx === 5 /* contrast */) { - max = 200; - } - - if (idx === 3 /* hue-rotate */) { - if (value > max) { - value %= max; - } else if (value < 0) { - value = max + (value % max); - } - } else if (value < 0) { - value = 0; - } else if (value > max) { - value = max; - } - return value; - } - } - - loss(filters) { - // Argument is array of percentages. - const color = this.reusedColor; - color.set(0, 0, 0); - - color.invert(filters[0] / 100); - color.sepia(filters[1] / 100); - color.saturate(filters[2] / 100); - color.hueRotate(filters[3] * 3.6); - color.brightness(filters[4] / 100); - color.contrast(filters[5] / 100); - - const colorHSL = color.hsl(); - return ( - Math.abs(color.r - this.target.r) + - Math.abs(color.g - this.target.g) + - Math.abs(color.b - this.target.b) + - Math.abs(colorHSL.h - this.targetHSL.h) + - Math.abs(colorHSL.s - this.targetHSL.s) + - Math.abs(colorHSL.l - this.targetHSL.l) - ); - } - - css(filters) { - function fmt(idx, multiplier = 1) { - return Math.round(filters[idx] * multiplier); - } - - //modified here - return { - invert: `${fmt(0)}%`, - sepia: `${fmt(1)}%`, - saturate: `${fmt(2)}%`, - hue_rotate: `${fmt(3, 3.6)}deg`, - brightness: `${fmt(4)}%`, - contrast: `${fmt(5)}%` - } - - //return `filter: invert(${fmt( - // 0 - //)}%) sepia(${fmt(1)}%) saturate(${fmt(2)}%) hue-rotate(${fmt(3, 3.6)}deg) brightness(${fmt(4)}%) contrast(${fmt(5)}%);`; - } - } - - function hexToRgb(hex) { - // Expand shorthand form (e.g. "03F") to full form (e.g. "0033FF") - const shorthandRegex = /^#?([a-f\d])([a-f\d])([a-f\d])$/i; - hex = hex.replace(shorthandRegex, (m, r, g, b) => { - return r + r + g + g + b + b; - }); - - const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex); - return result - ? [ - parseInt(result[1], 16), - parseInt(result[2], 16), - parseInt(result[3], 16) - ] - : null; - } - - function getFilterForColor(rgbColor) { - let bestResult = null; - let iterationCount = 0; // Initialize a counter for iterations - - for (let i = 0; i < 200; i++) { - iterationCount++; // Increment the counter for each iteration - const color = new Color(rgbColor[0], rgbColor[1], rgbColor[2]); - const solver = new Solver(color); - const result = solver.solve(); - - if (!bestResult || result.loss < bestResult.loss) { - bestResult = result; - if (bestResult.loss <= 0.01) { - // exit early if good result is found - break; - } - } - } - - console.log("Total iterations: ", iterationCount); // Log the total iterations - return bestResult; - } - - //end color manipulation - - function updateHeading(mutation) { - let headings = mutation.querySelectorAll(".tdx-control-bar__title") - - for (const heading of headings) { - //color the header if queue name is found - let headingTxt = heading.innerText - let headingFirst = headingTxt.split(" ")[0] - headingFirst = headingFirst.toLowerCase() - - let parent = heading.parentElement - - handleHighlight("report",headingTxt,heading) - - //try embedding - if (headingTxt.startsWith("{")) { - try { - let embedData = JSON.parse(headingTxt) - - let title = document.createElement("h4") - title.classList = heading.classList - title.innerText = embedData.name - let moduleBody = heading.parentNode.parentNode.parentNode.querySelector(".tdx-widget") - let embed = document.createElement("iframe") - embed.classList = "customEmbed" - embed.src = embedData.url - heading.replaceWith(title) - moduleBody.replaceWith(embed) - } catch { - } - } - } - } - - function parseTicket(mutation=null) { - - let qBlock = document.querySelector("#ctlAttribute2285") - //ticket or task - let header = document.getElementById("thTicket_spnTitle") || document.querySelector("#upTaskHeader>div>h1") - - //find calendar inputs when editing tickets/tasks - //let calendars = document.querySelectorAll("input.hasDatepicker") - let calendars = document.querySelectorAll("#txtStartDate, #txtEndDate") //tasks for now, will add more as found - if (calendars) { - let originalFormat = "M/D/YYYY h:mm A"; - let newFormat = "YYYY-MM-DDTHH:mm"; - [...calendars].forEach(calendar=>{ - let date = moment(calendar.value,originalFormat) - - let newCal = document.createElement("input") - newCal.id = `${calendar.id}-new` - newCal.classList = calendar.classList - newCal.type = "datetime-local" - - function updateDate() { - //update old tdx calendar - let parsedFormat = date.format(originalFormat) - calendar.value = parsedFormat - - //update new calendar - let iso = date.format(newFormat) - newCal.value = iso - calTxt.innerText = date.calendar() - - console.log("Cal update!",date) - } - - //convert to original format - newCal.addEventListener("input",event=>{ - let parsedValue = moment(event.target.value,newFormat) - date = parsedValue - updateDate() - }) - - //date modifier shortcuts - let calBox = document.createElement("div") - calBox.classList = ["calBox"] - let calTxt = document.createElement("span") - calTxt.innerText = date.format('dddd') - - //modify date - function btnModify(btn) { - console.log("Modify date:",btn) - if ('add' in btn) { - date.add(btn.add) - } else if ('set' in btn) { - date.set(btn.set) - } - - //check business days - let day = date.isoWeekday() - let hour = date.hour() - let min = date.minute() - let wkday = date.weekday() - - console.log("WkDay:",wkday,"Day:",day,"hour:",hour,"min:",min) - - //if Friday after 5pm - if (day>=5 && (hour>17 || (hour==17 && min>0))) { - date.set({ - h: 8, - d: 1+7, - m: 0 - }) - } else if (day>5) { - //if sat/sun - date.set({ - d: 1+7 - }) - } - - - updateDate() - } - - let buttons = [ - {name:"+1 day",add: {days:1}}, - {name:"+1 week",add: {weeks:1}}, - {name:"+1 month",add: {months:1}}, - {name:"12PM",set: {h:12,m:0}}, - {name:"5PM",set: {h:17,m:0}} - ] - - for (const btn of buttons) { - let button = document.createElement("button") - button.classList = "btn btn-calendar" - button.innerText = btn.name - button.addEventListener("click",(event)=>{ - event.preventDefault() - btnModify(btn) - }) - calBox.appendChild(button) - } - - updateDate() - - //old input still needs to exist for proper format conversion - calendar.style.display = "none" - calendar.parentElement.append(newCal) - calendar.parentElement.append(calTxt) - calendar.parentElement.append(calBox) - }); - } - - //change tab title - if (header) { - let ticketTitle = header.childNodes[0].textContent - document.title = ticketTitle - } else { - return - } - - //add queue tag to ticket title - if (qBlock && !document.querySelector(".qBox")) { - let qElement = qBlock.querySelector("span.wrap-text") - let qTxt = qElement.innerText - - //console.log("GOT QUEUE:",qTxt) - - let newBox = document.createElement("span") - newBox.innerText = qTxt - newBox.classList.add("qBox") - - for (const qK of Object.keys(colorsByQueue)) { - let q = colorsByQueue[qK] - if (qTxt.toLowerCase() == qK) { - newBox.style.color = q.txt - newBox.style.backgroundColor = q.bg - } - - } - - header.appendChild(newBox) - } - - //handle button links - updates/tasks for now - //update buttons - [...document.querySelectorAll("#btnUpdateTicket, #divUpdateFromActions")].forEach(button=>{ - handleLink("Update",button) - }); - - //task button - [...document.querySelectorAll("#liAddTicketTask>a")].forEach(button=>{ - handleLink("TicketTaskNew",button) - }); - - //task template button - [...document.querySelectorAll("#divAddTaskTemplate>a")].forEach(button=>{ - handleLink("TicketAddTaskTemplate",button) - }); - - //color the feed if darkmode - var feedItems - - if (mutation) { - feedItems = mutation - } else { - feedItems = document.querySelectorAll("#ttDescription") - } - - //console.log("Feed items:",feedItems) - - if (feedItems) { - for (const feedItem of feedItems) { - [...feedItem.querySelectorAll("*[style*='color']")].forEach(feedElement=>{ - let color = tinycolor(feedElement.style.color) - let brightness = color.getBrightness() - //console.warn("ELEMENT:",feedElement) - //console.log("Brightness:",brightness) - - //if color is too dark - if (brightness < 100 && colorScheme == "darkMode") { - - var newColor - var isGrey = true - let rgb = color.toRgb() - - if (rgb.r == rgb.b && rgb.r == rgb.g) { - isGrey = true - } else { - isGrey = false - } - - //if color is shade of grey - if (isGrey) { - let flippedColor = tinycolor(invertHex(color.spin(180).toHex())) - newColor = flippedColor - //console.log(feedElement.innerText,"is grey") - } else { - let threshold = 50 - let diff = (threshold - brightness) + brightness - newColor = color.brighten(diff) - //console.log(feedElement.innerText,"is a color") - } - //console.log("oldColor:",color.toHex(),"newColor:",newColor.toHex()) - - feedElement.style.color = newColor.toHexString() - } - }); - } - } - } - - function parseOtherElements() { - let path = document.location.pathname; - - //inject styles into search bar - [...document.querySelectorAll("tdx-search-bar, .js_sidePanelX")].forEach(searchBar=>{ - //console.log("SEARCH BAR:",searchBar) - let shadow = searchBar.shadowRoot - if (shadow) { - - injectOtherStyles(shadow); - - //check nested shadows - [...shadow.querySelectorAll("tdx-close-x")].forEach(nested=>{ - let nestedShadow = nested.shadowRoot - //console.log("NESTED:",nestedShadow) - if (nestedShadow) { - injectOtherStyles(nestedShadow) - } - }) - } - }) - - let desktopLayout = settings('get','layout') - let desktop = document.querySelector("#divContent") - if (desktop && desktopLayout) { - let col1 = desktop.querySelector("#Column1") - let col2 = desktop.querySelector("#Column2") - let col3 = desktop.querySelector("#Column3") - - //100% / 33-66% - if (desktopLayout=="1_100-66-33" && col2 && col3) { - console.log("Applying layout:",desktopLayout) - - //define width classes - let col2WidthClass = "col-md-8" - let col3WidthClass = "col-md-4" - - //resize column 2 - for (const cls of col2.classList) { - if (cls.startsWith("col-md")) { - console.log("Found col2 width class:",cls) - col2.classList.remove(cls) - col2.classList.add(col2WidthClass) - break - } - } - - //resize column 3 - for (const cls of col3.classList) { - if (cls.startsWith("col-md")) { - col3.classList.remove(cls) - col3.classList.add(col3WidthClass) - break - } - } - } - } - - //apply sticky columns - let stickyColumns = settings('get','stickyColumns') - if (stickyColumns) { - [...document.querySelectorAll(".tdx-dashboard__column")].forEach(column=>{ - column.style.position = "sticky" - column.style.alignSelf = "flex-start" - column.style.top = "4px" - }); - } - } - - function invertHex(hex) { - return (Number(`0x1${hex}`) ^ 0xFFFFFF).toString(16).substr(1).toUpperCase() - } - - function parseTable(element) { - //let t = mutation.target; - //console.error("BEGIN MUTATION",t) - let table = element.querySelector("table") - let items = []; - - if (table) { - let headers = []; - //console.log("Table",table); - - //get headers of the tables - [...table.querySelectorAll("th")].forEach((header)=>{ - var txt = header.querySelector("span") - //txt = txt.dataset.sort - //txt = txt.split(" ")[0] - if (txt) { - headers.push(txt.textContent) - } - //console.log("i:",header.cellIndex,txt) - }); - - //console.log("Headers:",headers); - - //parse rows - [...table.querySelectorAll("tr:has(td)")].forEach((row)=>{ - //console.log("row:",row); - let item = {}; - //parse each cell - let i = 0; - [...row.querySelectorAll("td:not(:has(input))")].forEach((cell)=>{ - //let i = cell.cellIndex; //can't use cellindex if there's a checkbox in the table - let txt = cell.textContent; - txt = txt.trim() - - //console.log("Cell:",i,cell); - - item[headers[i]] = {txt:txt,cell:cell} - i++ - }) - - item.row = row - items.push(item) - //console.log("ITEM:",item) - - //being coloring - parseItem(item) - }) - } - - //updateHeading(element) - } - - function createHighlightBubble(element,bgColor,txtColor) { - - //should the bubble carry links over? - //let copy = element.cloneNode(true) - - //create new element to highlight - let newSpan = document.createElement("span") - newSpan.innerText = element.innerText //item["2285"].txt - newSpan.style.backgroundColor = bgColor - newSpan.style.color = txtColor - newSpan.classList.add("qHighlight") - - //if we use the copy method - //newSpan.appendChild(copy) - - //replace cell with new span - element.replaceChildren(newSpan) - return newSpan - } - - //modify/color the cells - function parseItem(item) { - - //console.log("Parse item:",item) - - //color queue names - if ('CSS Support' in item) { - let qCell = item["CSS Support"].cell - let qTxt = item["CSS Support"].txt.toLowerCase() - if (qTxt in colorsByQueue) { - let q = colorsByQueue[qTxt] - - createHighlightBubble(qCell,q.bg,q.txt) - } - } - - //change date modified - let relativeDates = ['Modified','Created'] - for (const dType of relativeDates) { - if (dType in item) { - let dTxt = item[dType].txt - let dCell = item[dType].cell - - let date = moment(dTxt) - let dTxtNew = date.fromNow() - - if (dTxtNew == "Invalid date") { - //console.warn("Failed date:",dTxt,item) - } else { - dCell.innerText = dTxtNew - } - } - } - - let detailedDates = ['Date Due','Due','Created','Start'] - for (const dType of detailedDates) { - if (dType in item) { - let dTxt = item[dType].txt - let dCell = item[dType].cell - - let date = moment(dTxt) - let dTxtNew = date.calendar() - - if (dTxtNew == "Invalid date") { - //console.warn("Failed date:",dTxt,item) - } else { - dCell.innerText = dTxtNew - } - } - } - - //highlight modified/age red - let modifiedDates = ['Modified'] - for (const dType of modifiedDates) { - if (dType in item) { - let modDate = item[dType] - const ageThreshold = 336 - - let date = moment(modDate.txt) - let duration = moment.duration(moment().diff(date)) - let hours = duration.asHours() - - let alpha = hours / ageThreshold - alpha = alpha > 1 ? 1 : alpha - - let cell = modDate.cell - handleHighlight("dateModified",alpha,cell) - cell.classList.add(alpha > 0.5 ? "light" : "dark") - } - } - - //find user replies & last modified by internal - if ('Requestor' in item && 'Modified By' in item && 'Prim Resp' in item) { - let fromUser = item["Requestor"] - let lastModified = item["Modified By"] - let assignedTo = item["Prim Resp"] - - //reply from user - if (fromUser.txt == lastModified.txt && fromUser.txt != assignedTo.txt && assignedTo.txt != "Unassigned") { - //item.row.style.backgroundColor = "var(--col-reply)"; - handleHighlight("reply",null,item.row) - } - - //modified by internal - if (lastModified.txt != fromUser.txt && lastModified.txt != assignedTo.txt) { - let cell = lastModified.cell - //cell.style.backgroundColor = "var(--col-modified)" - handleHighlight("userModified",null,cell) - } - } - - //find internal users and highlight them - if ('Prim Resp' in item) { - handleHighlight("person",item['Prim Resp'].txt,item['Prim Resp'].cell) - } else if ('Responsibility' in item) { - handleHighlight("person",item.Responsibility.txt,item.Responsibility.cell) - } - - //find inline highlights for tasks - if ('Title' in item) { - let title = item.Title - handleHighlight("title",title.txt,title.cell) - } - - //find links & open in new tab, if configured - //let linkTypes = ['Title','TicketID','CustomerName','ResponsibleFullName','LastModifiedByFullName'] //open people in new tabs - let linkTypes = ['Title','TicketID','TicketTitle'] - for (const linkType of linkTypes) { - if (linkType in item) { - let link = item[linkType].cell.querySelector("a") - if (link) { - //override function that opens in windows - handleLink("report",link) - } - } - } - } - - function handleLink(source,link) { - let behavior = settings('get','linkBehavior') - - let relL = window.screenLeft != undefined ? window.screenLeft : screen.left - let relT = window.screenTop != undefined ? window.screenTop : screen.top - - if (behavior=="tabs") { - - switch(source) { - case 'report': { - link.onclick = null - link.target = "_blank" - break - } - - case 'Update': - case 'TicketTaskNew': - case 'TicketAddTaskTemplate': { - link.onclick = (event)=>{ - event.preventDefault() - let w = (window.screen.width / 1.75) - let h = (window.screen.height / 1.25) - let l = ((window.screen.width / 2) - (w/2)) + relL - let t = ((window.screen.height / 2) - (h/2)) + relT - - //restructure url for updating - let location = window.location.pathname - let baseHref = location.substr(0, location.lastIndexOf('/')) - let href = `${baseHref}/${source}${window.location.search}` - - let params = `width=${w}px,height=${h}px,left=${l}px,top=${t}px` - return window.open(href,'_blank',params) - } - break - } - } - - } else { - return - //leave default - link.onclick = (event)=>{ - event.preventDefault() - var params - var href - let w = (window.screen.width / 2.1) - let h = (window.screen.height / 1.25) - let l = 20 + relL - let t = 50 + relT - - switch(source) { - case 'report': { - href = link.href - break - } - - case 'Update': - case 'TicketTaskNew': - case 'TicketAddTaskTemplate': { - l = (window.screen.width / 2) + l - - //restructure url for updating - let location = window.location.pathname - let baseHref = location.substr(0, location.lastIndexOf('/')) - href = `${baseHref}/${source}${window.location.search}` - break - } - } - - params = `width=${w}px,height=${h}px,left=${l}px,top=${t}px` - return window.open(href,'_blank',params) - } - } - - } - - function handleHighlight(type, txt, element) { - let behavior = settings('get','highlightBehavior') - - var re - var style = null - - for (const [key,color] of Object.entries(colorsByStatus)) { - re = color.re.exec(txt) - if (re) { - style = color.style - break - } - } - - const customHighlights = settings('get','customHighlights') || [] - for (const customHighlight of customHighlights) { - let customType = customHighlight.type - if (customType=="highlight") { - let char = customHighlight.value - let reg = new RegExp(`\\${char} (.*) \\${char}`,"g") - re = reg.exec(txt) - if (re) { - style = customHighlight.style - break - } - } - - if (type=="reply" && customType=="reply") { - style = customHighlight.style - } - - if (type=="dateModified" && customType=="dateModified") { - style = customHighlight.style - if (style.background) { - let a = Math.floor(txt * 255).toString(16); - style.background = style.background + a - } - } - - if (type=="userModified" && customType=="userModified") { - style = customHighlight.style - } - - if (type=="report" && customType=="report") { - if (customHighlight.value==txt) { - element.classList.add("reportTitle") - style = customHighlight.style - } - } - - if (type=="report" && customType=="report-regex") { - if ((new RegExp(customHighlight.value).exec(txt))) { - element.classList.add("reportTitle") - style = customHighlight.style - } - } - - if (type=="person" && customType=="person") { - if (customHighlight.value==txt) { - element = createHighlightBubble(element) - style = customHighlight.style - } - } - } - - if (style) { - //console.log("Apply custom highlight:",txt) - - let link = element.querySelector("a") - if (behavior==="block") { - if (re && link) { - let newTitle = re[1] - link.innerText = newTitle - //reset regex - re.lastIndex = 0 - } - } else { - if (re && link) { - let text = link.innerText - link.innerText = "" - element = link.appendChild(document.createElement("span")) - element.innerText = text - element.style.lineHeight = "1.4" - //reset regex - re.lastIndex = 0 - } - } - - for (const [attr,val] of Object.entries(style)) { - element.style[attr] = val - } - //element.style.backgroundColor = style.background - - } else { - //apply defaults - if (type=="reply") { - element.style.backgroundColor = "var(--col-reply)"; - } - if (type=="userModified") { - element.style.backgroundColor = "var(--col-modified)"; - } - if (type=="dateModified") { - element.style.backgroundColor = `rgba(255,0,0,${txt}`; - } - } - } - - function generatePopup(href,w,h,l,t,source) { - - } - - function injectOtherStyles(element) { - - let s = document.createElement("style") - s.id = "customStyles" - s.innerText = customStyles - - //find iframes - likely text editors - if (element.tagName == "IFRAME") { - let frame = element.contentWindow.document; - - //attempt color coded tables on non-desktop pages - /*let tables = frame.querySelectorAll("table"); - [...tables].forEach(table=>{ - parseTable(table.parentElement) - })*/ - - //console.log("Found iFrame:",frame) - - //check for existing style block - if (!frame.querySelector("#customStyles")) { - let head = frame.querySelector("head") - let html = frame.querySelector("html") - html.classList.add(settings("get","colorMode")) - head.appendChild(s) - } - } else { - if (!element.querySelector("#customStyles")) { - setCssFilters(s) - element.appendChild(s) - } - } - } - - //setup observer to watch report/table changes/refreshes - let observer = new MutationObserver((mutations) => { - mutations.forEach((mutation) => { - let t = mutation.target - //console.error("Mutation:",t) - if (t.querySelector("div > table")) { - //let table = t.firstElementChild.querySelector("table") - //console.log("Matched table",t) - parseTable(t) - } - - //parse the feed if it updates - if (t.classList.contains("feed")) { - parseTicket(mutation.addedNodes) - } else if (t.classList.contains("feed-body")) { - parseTicket(t.querySelectorAll(".feed-reply")) - } - - //parse dashboard widgets - if (t.id=="tdx-workmgmt-container-collection") { - parseOtherElements() - } - - //parse side panels - if (t.classList.contains("tdx-right-side-panel")) { - parseOtherElements() - } - - let module = t.querySelector("div > .tdx-dashboard__widget-container") - if (module) { - updateHeading(t) - } - - //search whole document, frames may reset when reopened - let frames = document.querySelectorAll("iframe:not(.customEmbed)") - if (frames) { - [...frames].forEach(frame=>{ - injectOtherStyles(frame) - }); - } - }); - }); - - if (true) { - console.log("Observing...") - observer.observe(document.body, { - characterDataOldValue: true, - subtree: true, - childList: true, - characterData: true - }); - } - - async function changeTitle() { - let title = document.querySelector(".tdx-headerbar-headline a") - if (title) { - title.innerText = primaryTitle - } - - await injectToolbar() - } - - function colorChange(color) { - localStorage.setItem("colors",color) - setColors(color) - } - - function setColors(color,value) { - console.log("Setting",color,"to",value) - //let col = tinycolor(value).toRgbString() - let col = value - let style = document.documentElement.style - - switch(color) { - case 'primaryColor': - style.setProperty('--dark-col-primary', col); - style.setProperty('--light-col-primary', col); - break - - case 'backgroundColor': - style.setProperty('--dark-bg-primary', col); - style.setProperty('--light-bg-primary', col); - break - - case 'theme': { - - for (const col of ["dark","light"]) { - let accent = `var(--${col}-${value}-accent)` - let bg = `var(--${col}-${value}-bg)` - style.setProperty(`--${col}-col-primary`, accent) - style.setProperty(`--${col}-bg-primary`, `var(--${col}-bg-default)`) - - } - - break - } - } - } - - function setCssFilters(element=null) { - let style = element ? element.style : document.documentElement.style - //quick test for filter generation - let mode = getColorMode().split("Mode")[0] - let priCol = window.getComputedStyle(document.body).getPropertyValue("--dark-col-primary") - let rgb = hexToRgb(priCol) - //let filters = getFilterForColor(rgb) - - const color = new Color(rgb[0], rgb[1], rgb[2]); - const solver = new Solver(color); - const result = solver.solve(); - let filters = result.filter - - //console.log("STYLES:",priCol) - //console.log("FILTERS:",priCol,rgb,filters) - - style.setProperty("--filter-brightness",filters.brightness) - style.setProperty("--filter-contrast",filters.contrast) - style.setProperty("--filter-hue-rotate",filters.hue_rotate) - style.setProperty("--filter-invert",filters.invert) - style.setProperty("--filter-saturate",filters.saturate) - style.setProperty("--filter-sepia",filters.sepia) -} - - /* - function toggleColorMode() { - let mode = getColorMode() == "darkMode" ? "lightMode" : "darkMode" - setColorMode(mode) - } - - */ - - function getColorMode() { - let mode = window.matchMedia('(prefers-color-scheme: dark)').matches ? "darkMode" : "lightMode" - return mode - } - - function setColorMode(mode,store=true) { - if (!mode) { - mode = "auto" - } - console.log("Set color mode to",mode) - colorScheme = mode - var storageMode = mode - - let autoScheme = getColorMode() - if (autoScheme == mode) { - storageMode = "auto" - } - - if (mode == "auto" || storageMode == "auto") { - mode = autoScheme - document.documentElement.classList.remove("lightMode") - document.documentElement.classList.remove("darkMode") - } else { - document.documentElement.classList.add(mode) - } - - if (store) { - localStorage.setItem("styles",storageMode) - } - - } - - async function injectToolbar() { - let iconBar = document.querySelector("#globalSearchBar") - - let statusHTML = ` -
    - - -
    - ` - - let toolsHTML = ` -
    - -
    - ` - - let buttonHTML = ` -
    - -
    - ` - - let settingsHTML = ` - - - ` - - let settingsButton = document.createElement("span") - settingsButton.innerHTML = buttonHTML - - let settingsPage = document.createElement("div") - settingsPage.innerHTML = settingsHTML - - let statusLink = document.createElement("span") - statusLink.innerHTML = statusHTML - - let toolsLink = document.createElement("span") - toolsLink.innerHTML = toolsHTML - - if (iconBar) { - iconBar.after(settingsButton) - - //settings - //settingsPage.querySelector("#colorMode").onclick = toggleColorMode - settingsButton.querySelector("#settingsButton").addEventListener("click",()=>{ - settings("toggle",settingsPage) - }) - settingsButton.appendChild(settingsPage) - - //form changes - let form = settingsPage.querySelector("form") - form.addEventListener("change", (event)=>{ - settings("update",form) - }); - form.addEventListener("submit", (event)=>{ - event.preventDefault() - }); - - //send/recieve data from popup - let customColorButton = settingsPage.querySelector("#colorPopup") - customColorButton.addEventListener("click", (event)=>{ - let url = `${tdxtoolsUrl}/ecnuds/tdx/userscript/coloreditor` - let colorWindow = window.open(url,"TDX Color Editor","popup=true") - colorWindow.onload = function() { - colorWindow.postMessage({msg:"here's the data"},"*") - } - }); - - //links - let parent = iconBar.parentElement - - //tools - parent.prepend(toolsLink) - - //status - parent.prepend(statusLink) - let statusData = await getITStatus() - let statusIcon = statusLink.querySelector("#statusIcon") - let statusTime = statusLink.querySelector("#statusTime") - let statusText = statusLink.querySelector("#statusText") - - let operationalText = "All systems operational." - //check the first 5 words. do they contain operational or green? - //since the default message can vary sometimes - let operationalRegex = /^(?=(?:\w+\s){0,5}?(?:operational|green)\b(?!-))(\w+(?:\s\w+){0,5})/gm - - if (statusData) { - if (statusData.msg.length==0) { - statusData.msg = operationalText - } - } else { - statusData = { - msg: operationalText - } - } - - if (!operationalRegex.test(statusData.msg)) { - statusIcon.classList = ("fa-solid fa-triangle-exclamation") - } else { - statusIcon.classList = ("fa-solid fa-check") - } - - let statusTimeParsed = moment(statusData.time) - statusTime.innerText = statusTimeParsed.fromNow() - statusText.innerText = statusData.msg - } - } - - async function getITStatus() { - let url = "https://it.purdue.edu/api-status/messages.php" - let res = await fetch(url) - let data = await res.json() - - let msg = {} - - let msgs = data.Results - if (msgs.length>0) { - msg = { - time: msgs[0], - msg: msgs[1] - } - console.warn("IT Message:",msg) - } else { - msg = null - } - - return msg - } - - /* SETTINGS */ - - function settings(action,value=null) { - var data - var menu - try { - data = JSON.parse(localStorage.getItem("userSettings")) - - if (!data) { - throw "Data is null" - } else { - //resolve stringified objects - if ('customHighlights' in data) { - data.customHighlights = JSON.parse(data.customHighlights) - } - } - } catch(e) { - //console.error("Couldn't grab settings!",e) - //set defaults - data = { - colorMode: getColorMode(), - linkBehavior: "tabs", - highlightBehavior: "block", - customHighlights: [], - } - } - - switch(action) { - case 'apply': { - for (const setting in data) { - let form = document.forms.settingsForm - let value = data[setting] - - if (typeof value == "object") { - value = JSON.stringify(value) - } - - console.log("Apply setting:",setting,value) - try { - if (form) { - let elements = form.elements - form[setting].value = value - if (form[setting].type=="checkbox") { - form[setting].checked = value=="enabled" ? true : false - } - } - } catch {} - } - - if ('colorMode' in data) { - setColorMode(data.colorMode) - } - - if ('theme' in data) { - if (data.theme=="custom") { - setColors('primaryColor',data.primaryColor) - setColors('backgroundColor',data.backgroundColor) - } else { - setColors('theme',data.theme) - } - } - break - } - - case 'get': { - if (value) { - return value in data ? data[value] : null - } else { - return data - } - break - } - - case 'toggle': { - let menu = document.querySelector("#settingsMenu") - let newState = menu.classList.contains("show") ? "hide" : "show" - let oldState = newState=="show" ? "hide" : "show" - menu.classList.add(newState) - menu.classList.remove(oldState) - break - } - - case 'update': { - let form = document.querySelector("#settingsForm") - let formData = new FormData(form) - data = Object.fromEntries([...formData]) - console.log("Settings update!",data) - localStorage.setItem("userSettings",JSON.stringify(data)) - settings("apply") - setCssFilters() - } - } - } - - function parseCustomHighlights(data) { - console.log("Custom highlights:",data) - } - - /* TDX TOOLS */ - function checkPath() { - let path = document.location.pathname - if (path=="/TDWebApi/api/auth/loginsso") { - let pre = document.querySelector("pre") - if (pre) { - console.log("Got key!",pre.innerText) - let key = pre.innerText - window.opener.postMessage({tdxkey:key},tdxtoolsUrl) - window.close() - } - } - } - - window.addEventListener("message",(event) => { - let data = event.data - let origin = event.origin - let trgt = event.currentTarget - console.log("Message from:",origin,data,event) - - if (data.colorsReady) { - let colors = settings('get','customHighlights') - event.source.postMessage({ customColors: colors }, "*") - } - if (data.colorData) { - let element = document.getElementById("customHighlights") - let strData = JSON.stringify(data.colorData) - element.value = strData - settings('update') - } - },false); - - changeTitle() - //checkColorMode() - settings("apply") - parseTicket() - checkPath() - - addEventListener("storage", (event) => { - //console.log("Storage event:",event) - if (event.key == "userSettings") { - settings("apply") - } - }); - - var customStyles = ` - -/* Root Styles */ - -:root { - - --dark-bg-default: #000; - --light-bg-default: #fff; - - --dark-col-default: #ab9266; - --light-col-default: #cbb080; - - --dark-col-primary: var(--dark-col-default); - --light-col-primary: var(--light-col-default); - - --dark-bg-primary: var(--dark-bg-default); - --light-bg-primary: var(--light-bg-default); - - --dark-gold-accent: #ab9266; - --light-gold-accent: #c3aa7f; - - --dark-col-green: #295f29; - --dark-col-red: #912c2c; - --dark-col-blue: #32577a; - --dark-col-yellow: #654a24; - - --light-col-green: #e3fcea; - --light-col-red: #ff6190; - --light-col-blue: #e1f5fc; - --light-col-yellow: #ffefd8; - - /* Original TDX blue */ - --dark-blue-accent: #4c778d; - --light-blue-accent: #4b3bb9; - - --dark-green-accent: #559170; - --light-green-accent: var(--dark-green-accent); - - --filter-invert: 0; - --filter-sepia: 0; - --filter-saturate: 0; - --filter-hue-rotate: 0; - --filter-brightness: 0; - --filter-contrast: 0; - - --dark-bg-0: color-mix(in srgb,var(--dark-bg-primary),#fff 5%); - --dark-bg-1: color-mix(in srgb,var(--dark-bg-primary),#fff 12%); - --dark-bg-2: color-mix(in srgb,var(--dark-bg-primary),#fff 20%); - --dark-bg-3: color-mix(in srgb,var(--dark-bg-primary),#fff 25%); - --dark-bg-4: color-mix(in srgb,var(--dark-bg-primary),#fff 30%); - --dark-col-100: color-mix(in srgb,var(--dark-col-primary),#000 70%); - --dark-col-200: color-mix(in srgb,var(--dark-col-primary),#000 60%); - --dark-col-300: color-mix(in srgb,var(--dark-col-primary),#000 50%); - --dark-col-400: var(--dark-col-primary); - --dark-col-500: color-mix(in srgb, var(--dark-col-primary), #aaa 50%); - --dark-col-600: color-mix(in srgb,var(--dark-col-primary),#fff 35%); - --dark-col-700: color-mix(in srgb,var(--dark-col-primary),#fff 25%); - --dark-col-link: #d1dbff; - --dark-txt-0: #bbb; - --dark-txt-1: #fff; - --dark-txt-2: #ececec; - --dark-txt-3: #929292; - --dark-txt-4: #ffffff8c; - --dark-txt-5: var(--light-txt-1); - --dark-border-0: color-mix(in srgb,var(--dark-bg-primary),#fff 18%); - --dark-border-1: color-mix(in srgb,var(--dark-bg-primary),#fff 30%); - --dark-col-reply: #1e3438; - --dark-col-highlight-1: #ffdb0059; - --dark-col-highlight-2: #5f00ff5e; - --dark-col-currentuser: #09482f; - --dark-col-modified: #ff660012; - --dark-txt-invert: 1; - --dark-txt-hue: 180deg; - --dark-shadow-1: rgba(200, 200, 200, 0.1); - --dark-shadow-2: rgba(200, 200, 200, 0.06); - - --light-txt-1: #000; - --light-txt-2: #222; - --light-txt-3: #333; - --light-txt-4: #0000008c; - --light-txt-5: var(--dark-txt-1); - --light-col-100: color-mix(in srgb,var(--light-col-primary),#fff 85%); - --light-col-200: color-mix(in srgb,var(--light-col-primary),#fff 75%); - --light-col-300: color-mix(in srgb,var(--light-col-primary),#fff 65%); - --light-col-400: var(--light-col-primary); - --light-col-500: color-mix(in srgb, var(--light-col-primary), #aaa 50%); - --light-col-600: color-mix(in srgb,var(--light-col-primary),#111 70%); - --light-col-700: color-mix(in srgb,var(--light-col-primary),#000 75%); - --light-bg-0: color-mix(in srgb,var(--light-bg-primary),#000 0%); - --light-bg-1: color-mix(in srgb,var(--light-bg-primary),#000 7%); - --light-bg-2: color-mix(in srgb,var(--light-bg-primary),#000 13%); - --light-bg-3: color-mix(in srgb,var(--light-bg-primary),#000 20%); - --light-bg-4: color-mix(in srgb,var(--light-bg-primary),#000 25%); - --light-bg-5: color-mix(in srgb,var(--light-col-primary),#ffffffd7 75%); - --light-border-0: color-mix(in srgb,var(--light-bg-primary),#000 18%); - --light-border-1: color-mix(in srgb,var(--light-bg-primary),#000 30%); - --light-col-reply: #d3f2ff; - --light-col-highlight-1: #fff3c4; - --light-col-highlight-2: #e3c4ff; - --light-col-currentuser: #5de2ad; - --light-col-modified: #ffe8d1; - --light-txt-invert: 0; - --light-txt-hue: 0deg; - --light-shadow-1: rgba(50, 50, 50, 0.1); - --light-shadow-2: rgba(50, 50, 50, 0.06); -} - -@media (prefers-color-scheme: light) { - :root { - color-scheme: light; - --bg-0: var(--light-bg-0); - --bg-1: var(--light-bg-1); - --bg-2: var(--light-bg-2); - --bg-3: var(--light-bg-3); - --bg-4: var(--light-bg-4); - --bg-5: var(--light-bg-5); - --col-100: var(--light-col-100); - --col-200: var(--light-col-200); - --col-300: var(--light-col-300); - --col-400: var(--light-col-400); - --col-500: var(--light-col-500); - --col-600: var(--light-col-600); - --col-700: var(--light-col-700); - --col-link: var(--light-col-link); - --txt-0: var(--light-txt-0); - --txt-1: var(--light-txt-1); - --txt-2: var(--light-txt-2); - --txt-3: var(--light-txt-3); - --txt-4: var(--light-txt-4); - --txt-5: var(--light-txt-5); - --txt-invert: var(--light-txt-invert); - --txt-hue: var(--light-txt-hue); - --border-0: var(--light-border-0); - --border-1: var(--light-border-1); - --col-reply: var(--light-col-reply); - --col-highlight-1: var(--dark-col-highlight-1); - --col-highlight-2: var(--dark-col-highlight-2); - --col-currentuser: var(--light-col-currentuser); - --col-modified: var(--dark-col-modified); - --shadow-1: var(--light-shadow-1); - --shadow-2: var(--light-shadow-2); - --filter-brightness: var(--light-filter-brightness); - --filter-invert: var(--light-filter-invert); - } -} - -@media (prefers-color-scheme: dark) { - :root { - color-scheme: dark; - --bg-0: var(--dark-bg-0); - --bg-1: var(--dark-bg-1); - --bg-2: var(--dark-bg-2); - --bg-3: var(--dark-bg-3); - --bg-4: var(--dark-bg-4); - --bg-5: var(--dark-bg-5); - --col-100: var(--dark-col-100); - --col-200: var(--dark-col-200); - --col-300: var(--dark-col-300); - --col-400: var(--dark-col-400); - --col-500: var(--dark-col-500); - --col-600: var(--dark-col-600); - --col-700: var(--dark-col-700); - --col-red: var(--dark-col-red); - --col-green: var(--dark-col-green); - --col-blue: var(--dark-col-blue); - --col-yellow: var(--dark-col-yellow); - --col-link: var(--dark-col-link); - --txt-0: var(--dark-txt-0); - --txt-1: var(--dark-txt-1); - --txt-2: var(--dark-txt-2); - --txt-3: var(--dark-txt-3); - --txt-4: var(--dark-txt-4); - --txt-5: var(--dark-txt-5); - --txt-invert: var(--dark-txt-invert); - --txt-hue: var(--dark-txt-hue); - --border-0: var(--dark-border-0); - --border-1: var(--dark-border-1); - --col-reply: var(--dark-col-reply); - --col-highlight-1: var(--dark-col-highlight-1); - --col-highlight-2: var(--dark-col-highlight-2); - --col-currentuser: var(--dark-col-currentuser); - --col-modified: var(--dark-col-modified); - --shadow-1: var(--dark-shadow-1); - --shadow-2: var(--dark-shadow-2); - --filter-brightness: var(--dark-filter-brightness); - --filter-invert: var(--dark-filter-invert); - } -} - -:root.darkMode { - color-scheme: dark; - --bg-0: var(--dark-bg-0); - --bg-1: var(--dark-bg-1); - --bg-2: var(--dark-bg-2); - --bg-3: var(--dark-bg-3); - --bg-4: var(--dark-bg-4); - --bg-5: var(--dark-bg-5); - --col-100: var(--dark-col-100); - --col-200: var(--dark-col-200); - --col-300: var(--dark-col-300); - --col-400: var(--dark-col-400); - --col-500: var(--dark-col-500); - --col-600: var(--dark-col-600); - --col-700: var(--dark-col-700); - --col-red: var(--dark-col-red); - --col-green: var(--dark-col-green); - --col-blue: var(--dark-col-blue); - --col-yellow: var(--dark-col-yellow); - --col-link: var(--dark-col-link); - --txt-0: var(--dark-txt-0); - --txt-1: var(--dark-txt-1); - --txt-2: var(--dark-txt-2); - --txt-3: var(--dark-txt-3); - --txt-4: var(--dark-txt-4); - --txt-5: var(--dark-txt-5); - --txt-invert: var(--dark-txt-invert); - --txt-hue: var(--dark-txt-hue); - --border-0: var(--dark-border-0); - --border-1: var(--dark-border-1); - --col-reply: var(--dark-col-reply); - --col-highlight-1: var(--dark-col-highlight-1); - --col-highlight-2: var(--dark-col-highlight-2); - --col-currentuser: var(--dark-col-currentuser); - --col-modified: var(--dark-col-modified); - --shadow-1: var(--dark-shadow-1); - --shadow-2: var(--dark-shadow-2); - --filter-brightness: var(--dark-filter-brightness); - --filter-invert: var(--dark-filter-invert); -} - -:root.lightMode { - color-scheme: light; - --bg-0: var(--light-bg-0); - --bg-1: var(--light-bg-1); - --bg-2: var(--light-bg-2); - --bg-3: var(--light-bg-3); - --bg-4: var(--light-bg-4); - --bg-5: var(--light-bg-5); - --col-100: var(--light-col-100); - --col-200: var(--light-col-200); - --col-300: var(--light-col-300); - --col-400: var(--light-col-400); - --col-500: var(--light-col-500); - --col-600: var(--light-col-600); - --col-700: var(--light-col-700); - --col-red: var(--light-col-red); - --col-green: var(--light-col-green); - --col-blue: var(--light-col-blue); - --col-yellow: var(--light-col-yellow); - --col-link: var(--light-col-link); - --txt-0: var(--light-txt-0); - --txt-1: var(--light-txt-1); - --txt-2: var(--light-txt-2); - --txt-3: var(--light-txt-3); - --txt-4: var(--light-txt-4); - --txt-5: var(--light-txt-5); - --txt-invert: var(--light-txt-invert); - --txt-hue: var(--light-txt-hue); - --border-0: var(--light-border-0); - --border-1: var(--light-border-1); - --col-reply: var(--light-col-reply); - --col-highlight-1: var(--dark-col-highlight-1); - --col-highlight-2: var(--dark-col-highlight-2); - --col-currentuser: var(--light-col-currentuser); - --col-modified: var(--dark-col-modified); - --shadow-1: var(--light-shadow-1); - --shadow-2: var(--light-shadow-2); - --filter-brightness: var(--light-filter-brightness); - --filter-invert: var(--light-filter-invert); -} - -/* Body */ - -body { - background-color: var(--bg-0) !important; - color: var(--txt-1) !important; -} - -::-webkit-scrollbar-track { - background: var(--bg-0) !important; -} - -::-webkit-scrollbar-thumb { - background: var(--col-400) !important; - border: 5px solid var(--bg-0) !important; -} - -::-webkit-scrollbar-thumb:hover { - border: 3px solid var(--bg-0) !important; - background: var(--col-400) !important; -} - -::-webkit-scrollbar-corner { - background-color: var(--bg-0) !important; - } - -.tdx-overlay { - background-color: color-mix(in srgb,var(--col-400),#00000000 25%) !important; -} - -.tdx-overlay__item { - background-color: var(--bg-0) !important; - color: var(--col-400) !important; -} - -.tdx-overlay__item:hover, .tdx-overlay__item:focus-visible { - background-color: var(--col-400) !important; - color: var(--col-100) !important; -} - -.tdx-navigation-tab-bar { - background-color: initial !important; -} - -.tdx-leftnav__container { - background-color: var(--bg-0) !important; - border-color: var(--border-0) !important; - box-shadow: 0 1px 3px var(--shadow-1),0 2px 10px var(--shadow-2) !important; -} - -.tdx-leftnav__item { - color: var(--txt-1) !important; -} - -.tdx-leftnav__item--active .tdx-leftnav__link { - background-color: var(--col-100) !important; - color: var(--col-400) !important; -} - -.tdx-leftnav__link:hover, .tdx-leftnav__link:focus-visible { - background-color: var(--col-100) !important; -} - -.tdx-main-container { - background-color: var(--bg-0) !important; -} - -.tdx-layout-option__layout-preview { - background-color: var(--col-100) !important; -} - -.tdx-layout-option__column { - background-color: var(--bg-0) !important; -} - -.tdx-layout-selector__layout-option:hover, .tdx-layout-selector__layout-option:focus, .tdx-layout-selector__layout-option--selected { - background-color: var(--col-400) !important; -} - -.tdx-list__section { - color: var(--txt-2); -} - -/* Script-Specific Additions */ -#settingsMenu { - right: 50px; - padding: 10px; - width: 250px; - background: var(--bg-1); -} - -#settingsMenu.hide { - visibility: hidden; -} - -#settingsMenu h5 { - margin-bottom: 2px; -} - -#settingsMenu h3 { - padding-top: 10px; - font-weight: 500; - font-size: 18px; -} - -#settingsForm .flex { - display: flex; - gap: 24px; - align-items: baseline; -} - -#settingsForm .textBox { - display: flex; - flex-direction: column; - gap: 8px; -} - -.customEmbed { - border: 0; - width: 100%; - height: 400px; -} - -.calBox { - display: flex; - justify-content: space-around; - flex-wrap: wrap; - padding-top: 4px; - gap: 4px; - max-width: 220px; -} - -#statusBox:hover #statusMsg { - display: block; - width: 400px; - line-height: 22px; - padding: 8px; - right: 390px; -} - -#statusTime, #statusText { - margin: 6px; -} - -#statusTime { - font-size: 12px; -} - -#statusBox .fa-triangle-exclamation { - color: #ff8c4c; -} - -#statusBox .fa-check { - color: #0dbb28; -} - -.qBox { - margin-left: 10px; - padding: 5px; - font-size: 20px; - border-radius: 7px; -} - -.qHighlight { - padding: 4px; - border-radius: 8px; - white-space: nowrap; -} - -.btn-calendar { - flex-grow: 1; - padding: 2px; - background-color: var(--col-500); - color: var(--txt-5); -} - -.btn-calendar:hover { - background-color: var(--col-400); - color: var(--txt-5) -} - -.reportTitle { - border-radius: 12px; - padding-left: 10px !important; - padding-right: 10px !important; -} - -/* Others */ -.tdx-loading-animation { - color: var(--col-400) !important; -} - -.refresh-indicator { - background: linear-gradient(180deg,var(--bg-0),hsla(0,0%,100%,0)) !important; -} - -.breadcrumb { - background-color: var(--bg-0); -} - -.breadcrumb>.active { - color: var(--txt-3); -} - -p.row { - gap: 8px; -} - -/* Headers */ - -h1, h2, h3, h4, h5 { - color: var(--txt-1) !important; -} - -.tdx-header-container { - background-color: var(--col-100) !important; -} - -.tdx-headerbar-headline, .tdx-headerbar-headline a { - color: var(--col-1) !important; -} - -.tdx-headline { - color: var(--txt-1) !important; -} - -.tdx-headline--underline { - border-color: var(--border-0); -} - -.tdx-navigation-tabs__tab { - color: var(--col-600) !important; -} - -.tdx-navigation-tabs__home-tab--active, .tdx-navigation-tabs__tab--active { - background-color: var(--bg-0) !important; - color: var(--col-400) !important; -} - -.tdx-navigation-tabs__tab:hover:not(.tdx-navigation-tabs__tab--active) { - background-color: var(--col-200) !important; -} - -.tdx-navigation-tabs__home-tab:hover { - background-color: var(--col-200) !important; -} - -.tdx-navigation-tabs__home-tab--active:hover { - background-color: var(--bg-0) !important; -} - -.tdx-dropdown--headline { - color: var(--txt-1) !important; -} - -.tdx-dropdown:hover { - background-color: var(--col-200) !important; -} - -.tdx-dropdown.active { - background-color: var(--col-300) !important; -} - -.tdx-dropdown-popout, -.tdx-dropdown-popout__menu { - background-color: var(--bg-0) !important; -} - -.tdx-dropdown-popout__menu-item { - background-color: var(--bg-0) !important; - color: var(--txt-1) !important; -} - -.tdx-dropdown-popout__menu-item:hover, .tdx-dropdown-popout__menu-item:focus { - color: var(--txt-1) !important; - background-color: var(--col-300) !important; -} - -.tdx-dropdown-popout__menu-item--selected { - color: var(--col-400) !important; -} - -.tdx-dropdown-popout__header { - background-color: var(--bg-0) !important; - color: var(--col-600) !important; -} - -.tdx-dropdown-popout__break { - border-color: var(--border-0) !important; -} - -.tdx-dropdown__divider { - background-color: var(--bg-0) !important; -} - -.tdx-dropdown__divider::before { - background: linear-gradient(90deg,var(--bg-0),var(--border-0),var(--border-0),var(--border-0),var(--bg-0)) !important; -} - -.tdx-label { - color: var(--txt-1) !important; -} - -/* Inputs */ - -.tdx-dropdown--dark, -.tdx-searchbar__textbox--dark { - background-color: var(--col-200) !important; - color: var(--txt-1) !important; -} - -.tdx-dropdown--dark:hover, .tdx-dropdown--dark:focus-visible { - background-color: var(--col-300) !important; -} - -.tdx-searchbar__textbox:not(.tdx-searchbar__textbox--dark) { - background-color: var(--bg-0) !important; - color: var(--txt-1) !important; -} - -.tdx-searchbar__textbox:hover:not(:focus), .tdx-searchbar:hover .tdx-searchbar__textbox:not(:focus) { - background-color: var(--col-200) !important; -} - -.tdx-searchbar__textbox:focus, .tdx-searchbar__textbox:active, .tdx-searchbar__textbox:focus-within { - border-color: var(--col-400) !important; -} - -.tdx-searchbar__textbox::placeholder { - color: var(--col-400) !important; -} - -.tdx-searchbar__textbox--dark:hover:not(:focus)::placeholder, .tdx-searchbar:hover .tdx-searchbar__textbox--dark:not(:focus)::placeholder, -.tdx-searchbar__textbox:hover:not(:focus)::placeholder, .tdx-searchbar:hover .tdx-searchbar__textbox:not(:focus)::placeholder { - color: var(--col-400) !important; -} - -input[type=checkbox], input[type=radio] { - accent-color: var(--col-400) !important; -} - -.tdx-checkbox { - background-color: var(--bg-0) !important; - border-color: var(--border-0) !important; -} - -.tdx-checkbox:checked { - background-color: var(--col-400) !important; -} - -.tdx-checkbox:checked:disabled { - background-color: var(--col-200) !important; -} - -.control-label, label { - color: var(--txt-2) !important; -} - -.form-control { - background-color: var(--bg-0); - color: var(--txt-2); - border-color: var(--border-0); -} - -.form-control:hover { - border-color: var(--border-0); -} - -.form-control:focus { - border-color: var(--col-400); -} - -.talu_holder .luac_default { - color: var(--col-500); -} - -.talu_holder .bit-input input { - background-color: var(--bg-0); -} - -.talu_holder .bit-box { - background-color: var(--col-100); - color: var(--col-600); -} - -.talu_holder .bit-box:hover, .talu_holder .bit-box:active { - background-color: var(--col-300); - color: var(--col-500); -} - -.talu_holder .bit-box a.closebutton { - color: var(--col-600); -} - -.lu_tdac-auto ul { - background: var(--bg-0) !important; - box-shadow: 0 1px 3px var(--shadow-1),0 2px 10px var(--shadow-2) !important; -} - -.lu_tdac-auto ul li { - color: var(--txt-1) !important; -} - -.lu_tdac-auto ul .auto-focus { - background-color: var(--col-300); - color: var(--col-500); -} - -.lu_tdac-auto ul .auto-focus div.talu_subcaption { - color: var(--col-400); -} - -div.WhiteOut { - background-color: var(--bg-0) !important; -} - -[role=status]:has(div>div>.tdx-loading-animation) { - background-color: var(--bg-0) !important; -} - -.ms-drop .ms-search input::placeholder { - color: var(--txt-3); -} - -.ms-choice { - background-color: var(--bg-0); - color: var(--txt-3); -} - -.ms-drop { - background-color: var(--bg-0); - border-color: var(--border-0); -} - -button.ms-choice { - border-color: var(--border-0) !important; -} - -button.ms-choice:hover { - border-color: var(--border-0) !important; -} - -button.ms-choice:focus { - border-color: var(--col-400) !important; -} - -.form-control[disabled], .form-control[readonly], fieldset[disabled] .form-control { - background-color: var(--bg-1); -} - -.tdx-lookup-group div.select2-container.form-control a.select2-choices, .input-group div.select2-container.form-control a.select2-choice { - border-color: var(--border-0) !important; -} - -.input-group:not(:has(.input-group-section)):not(.input-group--no-border) { - border-color: var(--border-0); -} - -.input-group:focus, .input-group:active, .input-group:focus-within { - border-color: var(--col-400) !important; -} - -div.input-group .input-group-btn .btn-file:last-child { - color: var(--txt-3); -} - -.tdx-lookup-group { - background-color: var(--bg-0); - border-color: var(--border-0); -} - -.tdx-lookup-group:hover { - border-color: var(--border-0); -} - -.tdx-lookup-group .k-input:hover, .tdx-lookup-group .k-input:focus, .tdx-lookup-group .k-input:focus-within, .tdx-lookup-group.input-group:hover, .tdx-lookup-group.input-group:focus, .tdx-lookup-group.input-group:focus-within, .tdx-lookup-group select:hover, .tdx-lookup-group select:focus, .tdx-lookup-group select:focus-within, .tdx-lookup-group input:hover, .tdx-lookup-group input:focus, .tdx-lookup-group input:focus-within, .tdx-lookup-group input.form-control:hover, .tdx-lookup-group input.form-control:focus, .tdx-lookup-group input.form-control:focus-within { - border-color: var(--border-0); -} - -.tdx-lookup-group .k-input, .tdx-lookup-group.input-group, .tdx-lookup-group select, .tdx-lookup-group input, .tdx-lookup-group input.form-control { - border-color: var(--border-0); -} - -.tdx-lookup-group .k-svg-icon.k-svg-i-caret-alt-down::after { - color: var(--txt-1); -} - -.tdx-lookup-group:focus, .tdx-lookup-group:active, .tdx-lookup-group:focus-within { - border-color: var(--col-400); -} - -.tdx-lookup-group .k-input .k-input-inner::selection, .tdx-lookup-group.input-group .k-input-inner::selection, .tdx-lookup-group select .k-input-inner::selection, .tdx-lookup-group input .k-input-inner::selection, .tdx-lookup-group input.form-control .k-input-inner::selection { - background-color: var(--bg-2); -} - -.tdx-lookup-group>.select2-container-multi .select2-choices:not(div.attributeValue .select2-container-multi .select2-choices) { - border-color: var(--border-0) !important; -} - -.tdx-searchbar__textbox--border { - border-color: var(--border-0) !important; -} - -.tdx-lookup-group__input { - border-color: var(--border-0) !important; -} - -.tdx-input-group__textbox, -.tdx-input-group__textarea { - color: var(--txt-1) !important; - background-color: var(--bg-0) !important; - border-color: var(--border-0) !important; -} - -.k-input-solid { - background-color: var(--bg-0); -} - -.k-list { - background-color: var(--bg-0); - color: var(--txt-1); -} - -.k-list-container.k-popup { - background-color: var(--bg-0); -} - -.k-list-content .k-list-item:hover, .k-list-content .k-list-item:focus, .k-list-content .k-list-item.k-focus { - background-color: var(--col-300); - color: var(--txt-1); -} - -.k-list-content .k-list-item { - color: var(--txt-1); - background-color: var(--bg-0); -} - -.k-popup { - color: var(--txt-1); -} - -.k-popup:has(.k-list) { - box-shadow: 0 1px 3px var(--shadow-1),0 2px 10px var(--shadow-2); -} - -.tdx-lookup-group .k-input, .tdx-lookup-group.input-group, .tdx-lookup-group select, .tdx-lookup-group input, .tdx-lookup-group input.form-control { - color: var(--txt-1); -} - -.tdx-lookup-group .k-input .k-button-solid-base, .tdx-lookup-group.input-group .k-button-solid-base, .tdx-lookup-group select .k-button-solid-base, .tdx-lookup-group input .k-button-solid-base, .tdx-lookup-group input.form-control .k-button-solid-base { - background-color: var(--bg-0); -} - -.k-input-md .k-input-inner::placeholder, -.form-control::placeholder { - color: var(--txt-3) !important; -} - -.select2-container .select2-choice, .select2-container .select2-choices, .select2-container .select2-choices .select2-search-field input { - background: var(--bg-0) !important; -} - -div.select2-container.form-control .select2-choice.select2-default { - border-color: var(--border-0); -} - -.select2-container .select2-choice>.select2-chosen { - color: var(--txt-1) !important; -} - -.select2-container .select2-choice.select2-default>.select2-chosen { - color: var(--txt-3) !important; -} - -.tdx-lookup-group>.select2-container-multi .select2-choices:not(div.attributeValue .select2-container-multi .select2-choices) .select2-search-field input.select2-default { - color: var(--txt-3) !important; -} - -.select2-results .select2-no-results, .select2-results .select2-selection-limit { - background: var(--bg-1) !important; -} - -.select2-results .select2-no-results, .select2-results .select2-searching, .select2-results .select2-selection-limit { - color: var(--txt-1) !important; -} - -.select2-drop { - background: var(--bg-0); - color: var(--txt-1); -} - -.select2-drop { - color: var(--txt-1) !important; - background-color: var(--bg-0); -} - -.select2-drop .select2-search input { - background-color: var(--bg-0); - border-color: var(--border-0); -} - -.select2-search input { - color: var(--txt-1); -} - -div.select2-drop.select2-drop-active, div.select2-drop.select2-drop-above.select2-drop-active { - box-shadow: 0 1px 3px var(--shadow-1),0 2px 10px var(--shadow-2); -} - -.select2-drop .select2-results .select2-highlighted { - color: var(--txt-1) !important; - background-color: var(--col-300); -} - -.select2-results div.select2-result-label { - color: var(--txt-1); -} - -.select2-container:focus-within, .select2-container:focus-within a { - border-color: var(--col-400) !important; -} - -.form-group:has(select:not([multiple]):not([size])):hover::after { - color: var(--col-400) !important; -} - -div.select2-container.form-control .select2-choice, div.js-tagformfield .select2-container-multi .select2-choices, div.js-tags-inlineedit .select2-container-multi .select2-choices, div.attributeValue .select2-container-multi .select2-choices, div.select2-listbox .select2-container-multi .select2-choices, div.select2-container.form-control.select2-container-multi .select2-choices { - border-color: var(--border-0); -} - -div.select2-container.form-control .select2-choice:hover, div.js-tagformfield .select2-container-multi .select2-choices:hover, div.js-tags-inlineedit .select2-container-multi .select2-choices:hover, div.attributeValue .select2-container-multi .select2-choices:hover, div.select2-listbox .select2-container-multi .select2-choices:hover, div.select2-container.form-control.select2-container-multi .select2-choices:hover { - border-color: var(--border-0); -} - -div.select2-container-multi .select2-choices .select2-search-choice { - background-color: var(--col-100); - color: var(--col-600); -} - -div.select2-container-multi .select2-choices .select2-search-choice>.select2-search-choice-close { - color: var(--col-600) !important; -} - -div.select2-container-multi .select2-choices .select2-search-choice>.select2-search-choice-close:hover, div.select2-container-multi .select2-choices .select2-search-choice>.select2-search-choice-close:focus-visible, div.select2-container-multi .select2-choices .select2-search-choice>.select2-search-choice-close:active, div.select2-container-multi .select2-choices .select2-search-choice>.select2-search-choice-close:active:hover, div.select2-container-multi .select2-choices .select2-search-choice>.select2-search-choice-close:focus:active, div.select2-container-multi .select2-choices .select2-search-choice>.select2-search-choice-close:focus:hover { - color: var(--col-400) !important; -} - -div.select2-container-multi .select2-choices .select2-search-choice:hover, div.select2-container-multi .select2-choices .select2-search-choice:active { - background-color: var(--col-300); - color: var(--col-500); -} - -select.form-control:hover:not(:focus), -select.form-control { - border-color: var(--border-0); -} - -.k-chip-solid-base { - background-color: var(--col-100) !important; - color: var(--col-600) !important; -} - -.k-chip-action { - color: var(--col-600) !important; -} - -.k-chip-action:hover, .k-chip-action:focus-visible, .k-chip-action:active, .k-chip-action:active:hover, .k-chip-action:focus:active, .k-chip-action:focus:hover { - color: var(--col-400) !important; -} - -.tooltip-inner { - background-color: var(--bg-0); - color: var(--txt-1); - box-shadow: 0 .5px 1px 1px var(--shadow-1),0 2px 4px var(--shadow-2),0 4px 6px var(--shadow-2); -} - -div#ui-datepicker-div .ui-datepicker-title select, div#ui-datepicker-div .ui-timepicker-div.ui-timepicker-oneLine select, div.ui-datepicker .ui-datepicker-title select, div.ui-datepicker .ui-timepicker-div.ui-timepicker-oneLine select { - color: var(--txt-1); - border-color: var(--bg-0); - background-color: var(--bg-0); -} - -div#ui-datepicker-div .ui-datepicker-title select:hover, div#ui-datepicker-div .ui-timepicker-div.ui-timepicker-oneLine select:hover, div.ui-datepicker .ui-datepicker-title select:hover, div.ui-datepicker .ui-timepicker-div.ui-timepicker-oneLine select:hover { - border-color: var(--border-0); -} - -div#ui-datepicker-div .ui-state-default, div#ui-datepicker-div .ui-state-default:hover, div.ui-datepicker .ui-state-default, div.ui-datepicker .ui-state-default:hover { - border-color: var(--bg-0) !important; -} - -div#ui-datepicker-div .ui-datepicker-header, div.ui-datepicker .ui-datepicker-header { - background: var(--col-100) !important; -} - -div#ui-datepicker-div th, div#ui-datepicker-div td, div.ui-datepicker th, div.ui-datepicker td { - color: var(--txt-1); -} - -div#ui-datepicker-div .ui-state-highlight, div#ui-datepicker-div .ui-widget-content .ui-state-highlight, div#ui-datepicker-div .ui-widget-header .ui-state-highlight, div.ui-datepicker .ui-state-highlight, div.ui-datepicker .ui-widget-content .ui-state-highlight, div.ui-datepicker .ui-widget-header .ui-state-highlight { - background: var(--col-100) !important; - color: var(--col-400) !important; -} - -button:has(>.ui-icon-circle-triangle-e), span:has(>.ui-icon-circle-triangle-e), a:has(>.ui-icon-circle-triangle-e), button:has(>.fa-chevron-circle-right), span:has(>.fa-chevron-circle-right), a:has(>.fa-chevron-circle-right), -button:has(>.ui-icon-circle-triangle-w), span:has(>.ui-icon-circle-triangle-w), a:has(>.ui-icon-circle-triangle-w), button:has(>.fa-chevron-circle-left), span:has(>.fa-chevron-circle-left), a:has(>.fa-chevron-circle-left) { - color: var(--col-400); -} - -/* Links */ - -.tdx-dashboard__widget-container a:not(.btn):not(.k-icon) { - color: var(--col-400) !important; -} - -.tdx-dashboard__widget-container a:not(.btn):not(.k-icon):hover, .tdx-dashboard__widget-container a:not(.btn):not(.k-icon):focus-visible { - color: var(--col-500) !important; -} - -a { - color: var(--col-400); - background-color: initial !important; -} - -a:hover, a:focus-visible, -.tdworkmgmt td a.visited-link:hover, .tdworkmgmt td a.visited-link:focus-visible { - color: var(--col-500) !important; -} - -a:visited, -.tdworkmgmt td a.visited-link, -.tdworkmgmt td a:visited, .tdworkmgmt.table .hilite a:visited { - color: var(--col-400); -} - -.tdworkmgmt.table-contents div.row > div > a { - color: var(--col-400); -} - -.tdworkmgmt.table-striped > tbody > tr.tdx-grid__group-header > td, .tdworkmgmt.table-bordered > tbody > tr.tdx-grid__group-header > td { - background-color: var(--col-100); -} - -.tdx-time-panel, .tdx-time-panel__heading { - color: var(--txt-1) !important; - background-color: var(--bg-1) !important; - border: 1px solid var(--border-0) !important; -} - -.tdx-leftnav__badge { - color: var(--txt-1) !important; - background-color: var(--col-300) !important; -} - -body .tdworkmgmt.table.table--vertical-lines > tbody > tr > td:not(:last-of-type) { - border-right: 1px solid var(--border-0); -} - -.TDGroupingRow { - color: var(--txt-1); -} - -a.disabledLink { - color: var(--txt-1) !important; -} - -.k-grid a.tdx-link { - color: var(--col-400) !important; -} - -.tdx-link:visited { - color: var(--col-400) !important; -} - -.tdx-btn--link { - color: var(--col-400) !important; -} - -/* Buttons */ -.tdx-btn--secondary { - background-color: var(--col-200) !important; - color: var(--col-400) !important; - border: none !important; -} - -.tdx-btn--secondary > a { - color: var(--col-400) !important; -} - -.tdx-btn--secondary:hover, .tdx-btn--secondary:hover:focus, .tdx-btn--secondary:focus-visible { - background-color: var(--col-300) !important; - color: var(--col-600) !important; -} - -.tdx-action-menu-dropdown__popout { - background-color: var(--bg-0) !important; - box-shadow: 0 1px 3px var(--shadow-1),0 2px 10px var(--shadow-2) !important; -} - -.tdx-action-menu-dropdown-popout__menu-item:not(.tdx-dropdown-popout__header) { - background-color: var(--bg-0) !important; - color: var(--txt-1) !important; -} - -.tdx-action-menu-dropdown-popout__menu-item:hover, .tdx-action-menu-dropdown-popout__menu-item:focus { - background-color: var(--col-300) !important; -} - -.tdx-action-menu__item--primary { - color: var(--txt-5) !important; - background: var(--col-600) !important; - border-color: var(--col-600) !important; -} - -.tdx-action-menu__item--primary:hover, .tdx-action-menu__item--primary:hover:focus, .tdx-action-menu__item--primary:focus-visible { - color: var(--txt-5) !important; - background: var(--col-400) !important; - border-color: var(--col-400) !important; -} - -.tdx-action-menu__item:not(.tdx-action-menu__item--primary) { - color: var(--txt-1) !important; - background: var(--bg-0) !important; -} - -.tdx-action-menu__item:not(.tdx-action-menu__item--primary):hover, .tdx-action-menu__item.tdx-action-menu__item:not(.tdx-action-menu__item--primary):hover:focus, .tdx-action-menu__item.tdx-action-menu__item:not(.tdx-action-menu__item--primary):focus-visible { - background: var(--col-200) !important; - color: var(--txt-2) !important; -} - -.tdx-primary-button-override { - background-color: var(--col-600) !important; - color: var(--txt-5) !important; - border-color: var(--col-600) !important; -} - -.tdx-primary-button-override:hover, .tdx-primary-button-override:hover:focus, .tdx-primary-button-override:focus-visible { - background: var(--col-400) !important; - border-color: var(--col-400) !important; - color: var(--txt-5) !important; -} - -.tdx-primary-button-override.active, .tdx-primary-button-override.active:hover, .tdx-primary-button-override.active:focus, .tdx-primary-button-override:active, .tdx-primary-button-override:active:hover, .tdx-primary-button-override:active:focus, -.tdx-primary-button-override:focus:not(:focus-visible,.active,:active,:hover) { - background-color: var(--col-600) !important; - color: var(--txt-5) !important; - border-color: var(--col-600) !important; -} - -span.input-group-btn .btn-default { - color: var(--txt-3); -} - -span.input-group-btn .btn-default:hover, span.input-group-btn .btn-default:focus-visible, span.input-group-btn .btn-default:active, span.input-group-btn .btn-default:active:hover, span.input-group-btn .btn-default:focus:active, span.input-group-btn .btn-default:focus:hover { - color: var(--txt-2); -} - -div.input-group .input-group-btn .btn-file:last-child:hover, div.input-group .input-group-btn .btn-file:last-child:hover:focus, div.input-group .input-group-btn .btn-file:last-child:focus-visible { - background-color: var(--col-100); - color: var(--txt-2); -} - -.btn.active, .btn.active:hover, .btn.active:focus, .btn:active, .btn:active:hover, .btn:active:focus { - background: var(--col-300); - color: var(--txt-5); -} - -.btn-default { - color: var(--txt-1); -} - -.btn-default:hover, .btn-default:hover:focus, .btn-default:focus-visible { - background: var(--col-200); - color: var(--txt-1); -} - -.tdx-btn--tertiary { - color: var(--txt-1); -} - -.tdx-btn--tertiary:hover { - background: var(--col-200); - color: var(--txt-2); -} - -.tdx-btn--primary { - background-color: var(--col-600) !important; - color: var(--txt-5) !important; - border-color: var(--col-600) !important; -} - -.tdx-btn--primary:hover, .tdx-btn--primary:hover:focus, .tdx-btn--primary:focus-visible { - background: var(--col-400) !important; - border-color: var(--col-400) !important; - color: var(--txt-5) !important; -} - -.feed-button-group .btn-primary:hover, .feed-button-group .btn-primary:hover:focus, .feed-button-group .btn-primary:focus-visible { - background: var(--col-200); -} - -.feed-button-group .btn-primary.active, .feed-button-group .btn-primary.active:hover, .feed-button-group .btn-primary.active:focus, .feed-button-group .btn-primary:active, .feed-button-group .btn-primary:active:hover, .feed-button-group .btn-primary:active:focus { - background: var(--col-300); -} - -#btnSave.btn-primary, #btnClientSave.btn-primary, #btnRunReport.btn-primary, #btnApply.btn-primary, #btnAddSelected.btn-primary, #btnSubmit.btn-primary { - color: var(--txt-5) !important; - background-color: var(--col-500) !important; - border-color: var(--col-500) !important; -} - -#btnSave.btn-primary:hover, #btnSave.btn-primary:hover:focus, #btnSave.btn-primary:focus-visible, #btnClientSave.btn-primary:hover, #btnClientSave.btn-primary:hover:focus, #btnClientSave.btn-primary:focus-visible, #btnRunReport.btn-primary:hover, #btnRunReport.btn-primary:hover:focus, #btnRunReport.btn-primary:focus-visible, #btnApply.btn-primary:hover, #btnApply.btn-primary:hover:focus, #btnApply.btn-primary:focus-visible, #btnAddSelected.btn-primary:hover, #btnAddSelected.btn-primary:hover:focus, #btnAddSelected.btn-primary:focus-visible, #btnSubmit.btn-primary:hover, #btnSubmit.btn-primary:hover:focus, #btnSubmit.btn-primary:focus-visible { - background: var(--col-400) !important; - border-color: var(--col-400) !important; - color: var(--txt-5) !important; -} - -#btnSave.btn-primary.active, #btnSave.btn-primary.active:hover, #btnSave.btn-primary.active:focus, #btnSave.btn-primary:active, #btnSave.btn-primary:active:hover, #btnSave.btn-primary:active:focus, #btnClientSave.btn-primary.active, #btnClientSave.btn-primary.active:hover, #btnClientSave.btn-primary.active:focus, #btnClientSave.btn-primary:active, #btnClientSave.btn-primary:active:hover, #btnClientSave.btn-primary:active:focus, #btnRunReport.btn-primary.active, #btnRunReport.btn-primary.active:hover, #btnRunReport.btn-primary.active:focus, #btnRunReport.btn-primary:active, #btnRunReport.btn-primary:active:hover, #btnRunReport.btn-primary:active:focus, #btnApply.btn-primary.active, #btnApply.btn-primary.active:hover, #btnApply.btn-primary.active:focus, #btnApply.btn-primary:active, #btnApply.btn-primary:active:hover, #btnApply.btn-primary:active:focus, #btnAddSelected.btn-primary.active, #btnAddSelected.btn-primary.active:hover, #btnAddSelected.btn-primary.active:focus, #btnAddSelected.btn-primary:active, #btnAddSelected.btn-primary:active:hover, #btnAddSelected.btn-primary:active:focus, #btnSubmit.btn-primary.active, #btnSubmit.btn-primary.active:hover, #btnSubmit.btn-primary.active:focus, #btnSubmit.btn-primary:active, #btnSubmit.btn-primary:active:hover, #btnSubmit.btn-primary:active:focus { - background: var(--col-600) !important; - border-color: var(--col-600) !important; - color: var(--txt-5) !important; -} - -#btnSave.btn-primary:focus:not(:focus-visible,.active,:active,:hover), #btnClientSave.btn-primary:focus:not(:focus-visible,.active,:active,:hover), #btnRunReport.btn-primary:focus:not(:focus-visible,.active,:active,:hover), #btnApply.btn-primary:focus:not(:focus-visible,.active,:active,:hover), #btnAddSelected.btn-primary:focus:not(:focus-visible,.active,:active,:hover), #btnSubmit.btn-primary:focus:not(:focus-visible,.active,:active,:hover) { - background: var(--col-400) !important; - border-color: var(--col-400) !important; - color: var(--txt-5) !important; -} - -.btn-tertiary, .btn-info, .ButtonCellTopPadding .ButtonCellTop .btn-primary { - color: var(--txt-1); - background-color: var(--col-100); -} - -.btn-tertiary:hover, .btn-tertiary:hover:focus, .btn-tertiary:focus-visible, .btn-info:hover, .btn-info:hover:focus, .btn-info:focus-visible, .ButtonCellTopPadding .ButtonCellTop .btn-primary:hover, .ButtonCellTopPadding .ButtonCellTop .btn-primary:hover:focus, .ButtonCellTopPadding .ButtonCellTop .btn-primary:focus-visible { - background-color: var(--col-200); - color: var(--txt-1); -} - -.modal-footer .btn-default { - background-color: var(--col-200) !important; - color: var(--col-400) !important; - border: none !important; -} - -.modal-footer .btn-default:hover, .modal-footer .btn-default:hover:focus, .modal-footer .btn-default:focus-visible { - background-color: var(--col-300) !important; - color: var(--col-600) !important; -} - -/* .btn.btn-primary:not(.btn-sm) { - color: var(--txt-1); - background-color: var(--bg-5); - border-color: var(--bg-5); -} */ - -.TabButtonCell .btn-primary, .TabButtonCell .btn-info, .tab-row .btn-primary, #divViewButtons, .TabButtonCell .btn-primary:active, .tab-row .btn-primary:active { - color: var(--txt-2); -} - -.TabButtonCell .btn-primary:hover, .TabButtonCell .btn-primary:hover:focus, .TabButtonCell .btn-primary:focus-visible, .TabButtonCell .btn-info:hover, .TabButtonCell .btn-info:hover:focus, .TabButtonCell .btn-info:focus-visible, .tab-row .btn-primary:hover, .tab-row .btn-primary:hover:focus, .tab-row .btn-primary:focus-visible, #divViewButtons:hover, #divViewButtons:hover:focus, #divViewButtons:focus-visible, .TabButtonCell .btn-primary:active:hover, .TabButtonCell .btn-primary:active:hover:focus, .TabButtonCell .btn-primary:active:focus-visible, .tab-row .btn-primary:active:hover, .tab-row .btn-primary:active:hover:focus, .tab-row .btn-primary:active:focus-visible { - background: var(--col-200); - color: var(--txt-2); -} - -.TabButtonCell .btn-danger, .tab-row .btn-danger { - background: var(--bg-5); - color: var(--txt-2); -} - -.TabButtonCell .btn-danger:hover, .TabButtonCell .btn-danger:hover:focus, .TabButtonCell .btn-danger:focus-visible, .tab-row .btn-danger:hover, .tab-row .btn-danger:hover:focus, .tab-row .btn-danger:focus-visible { - background: var(--col-0); - color: var(--txt-2); -} - -.ButtonCellTop { - background: var(--bg-0); -} - -.feed-button-group .btn-primary { - color: var(--txt-2) !important; -} - -.btn-secondary { - background-color: var(--col-200); - color: var(--col-400); - border-color: var(--col-200); -} - -.btn-secondary:hover, .btn-secondary:hover:focus, .btn-secondary:focus-visible { - background-color: var(--col-300) !important; - color: var(--col-500) !important; - border-color: var(--col-300) !important; -} - -.btn-danger { - background-color: var(--col-200); - color: var(--col-400); - border-color: var(--col-200); -} - -.btn-danger:hover, .btn-danger:hover:focus, .btn-danger:focus-visible { - background-color: var(--col-300); - color: var(--col-500); - border-color: var(--col-300); -} - -.tdx-button-bar .btn-primary { - color: var(--txt-1); - background-color: var(--col-100); - border-color: var(--col-100); -} - -.tdx-button-bar .btn-primary:hover, .tdx-button-bar .btn-primary:hover:focus, .tdx-button-bar .btn-primary:focus-visible { - background-color: var(--col-300); - background: var(--col-300); - color: var(--txt-2); - border-color: var(--col-300); -} - -.tdx-button-bar .btn-primary:visited { - color: var(--txt-1); -} - -.tdx-button-bar .btn-danger { - color: var(--col-400); -} - -.tdx-button-bar .btn-danger:hover, .tdx-button-bar .btn-danger:hover:focus, .tdx-button-bar .btn-danger:focus-visible { - background-color: var(--col-300); - color: var(--col-500); - border-color: var(--col-300); -} - -.tdx-tile-list__item-container, -.tdx-tile-list__item-container:visited { - background-color: var(--col-100) !important; - color: var(--col-400) !important; -} - -.tdx-tile-list__item-container:hover, .tdx-tile-list__item-container:focus { - background-color: var(--col-400) !important; - color: var(--col-100) !important; -} - -a.btn.btn-primary { - background-color: var(--col-600) !important; - color: var(--txt-5) !important; - border-color: var(--col-600) !important; -} - -a.btn.btn-primary:hover { - background-color: var(--col-400) !important; - color: var(--txt-5) !important; - border-color: var(--col-400) !important; -} - -.btn-primary { - background-color: var(--col-600); - color: var(--txt-5); - border-color: var(--col-600); -} - -.btn-primary:hover, .btn-primary:hover:focus, .btn-primary:focus-visible { - background: var(--col-400); - color: var(--txt-5); - border-color: var(--col-400); -} - -td > a.btn.btn-primary { - background-color: var(--col-400) !important; - color: var(--txt-5) !important; - border-color: var(--col-400); -} - -td > a.btn.btn-primary:hover { - background-color: var(--col-500) !important; - color: var(--txt-5) !important; - border-color: var(--col-500); -} - -.btn-default.active, .btn-default.active:hover, .btn-default.active:focus, .btn-default:active, .btn-default:active:hover, .btn-default:active:focus { - background: var(--col-100) !important; - color: var(--txt-1) !important; - border-color: var(--col-100) !important; -} - -a.btn.btn-link.tdx-primary-button-override { - color: var(--txt-5) !important; -} - -.btn-link, .btn.btn-link, .sidebar-btn.btn-link { - color: var(--col-400) !important; -} - -.btn-link:hover, .btn.btn-link:hover, .sidebar-btn.btn-link:hover { - color: var(--col-400) !important; -} - -.btn-link[role=button]:hover, .btn.btn-link[role=button]:hover, .sidebar-btn.btn-link[role=button]:hover, -a.btn.btn-link.tdx-tertiary-button-override:hover { - background-color: var(--col-200) !important; -} - -.tdx-calendar .cal-views { - border-color: var(--col-400) !important; -} - -.tdx-calendar .cal-view { - color: var(--txt-2) !important; -} - -.tdx-calendar .cal-view.light-blue-bg { - background-color: var(--col-400) !important; - color: var(--txt-2) !important; -} - -.tdx-calendar .cal-view:not(.cal-view.light-blue-bg):hover, .tdx-calendar .cal-view:hover:focus, .tdx-calendar .cal-view:focus-visible { - background-color: var(--col-200) !important; -} - -.tdx-calendar #btnDatePicker { - background-color: var(--bg-0) !important; - color: var(--col-400) !important; -} - -.tdx-calendar #btnDatePicker:hover, .tdx-calendar #btnDatePicker:focus-visible, .tdx-calendar #btnDatePicker:active, .tdx-calendar #btnDatePicker:active:hover, .tdx-calendar #btnDatePicker:focus:active, .tdx-calendar #btnDatePicker:focus:hover { - color: var(--col-600) !important; -} - -button:has(.ui-icon-circle-triangle-w), span:has(.ui-icon-circle-triangle-w), -button:has(.ui-icon-circle-triangle-e), span:has(.ui-icon-circle-triangle-e) { - color: var(--col-400) !important; -} - -button:has(.ui-icon-circle-triangle-e):hover, button:has(.ui-icon-circle-triangle-e):focus-visible, button:has(.ui-icon-circle-triangle-e):active, button:has(.ui-icon-circle-triangle-e):active:hover, button:has(.ui-icon-circle-triangle-e):focus:active, button:has(.ui-icon-circle-triangle-e):focus:hover, span:has(.ui-icon-circle-triangle-e):hover, span:has(.ui-icon-circle-triangle-e):focus-visible, span:has(.ui-icon-circle-triangle-e):active, span:has(.ui-icon-circle-triangle-e):active:hover, span:has(.ui-icon-circle-triangle-e):focus:active, span:has(.ui-icon-circle-triangle-e):focus:hover, -button:has(.ui-icon-circle-triangle-w):hover, button:has(.ui-icon-circle-triangle-w):focus-visible, button:has(.ui-icon-circle-triangle-w):active, button:has(.ui-icon-circle-triangle-w):active:hover, button:has(.ui-icon-circle-triangle-w):focus:active, button:has(.ui-icon-circle-triangle-w):focus:hover, span:has(.ui-icon-circle-triangle-w):hover, span:has(.ui-icon-circle-triangle-w):focus-visible, span:has(.ui-icon-circle-triangle-w):active, span:has(.ui-icon-circle-triangle-w):active:hover, span:has(.ui-icon-circle-triangle-w):focus:active, span:has(.ui-icon-circle-triangle-w):focus:hover { - color: var(--col-600) !important; -} - -.ui-widget-header { - background: var(--bg-0) !important; -} - -.ui-state-default, .ui-widget-content .ui-state-default, .ui-widget-header .ui-state-default, -.ui-widget-content, .ui-widget.ui-widget-content { - background: var(--bg-0) !important; - border-color: var(--border-0) !important; -} - -.tdx-calendar .fc-day-header { - color: var(--col-400) !important; -} - -.tdx-calendar .fc-day-number.fc-other-month a:first-child { - color: var(--col-200) !important; -} - -.tdx-calendar .fc-day-number a { - color: var(--col-600) !important; -} - -.tdx-calendar .ui-state-highlight a, .tdx-calendar .ui-widget-content .ui-state-highlight a, .tdx-calendar .ui-widget-header .ui-state-highlight a { - color: var(--col-400) !important; -} - -.tdx-calendar .ui-state-highlight { - background: var(--col-100) !important; -} - -.td-day-off { - background: var(--bg-2) !important; -} - -.label-primary, .tdworkmgmt.table .hilite .label.label-primary { - background-color: var(--col-300); -} - -.label-info, .label-success, .label-default { - color: var(--col-200); - background-color: var(--col-500); -} - -.tdTilemd, -.tdTilesm { - background-color: var(--col-300); - border-color: var(--col-300); -} - -.tdTilemd.secondary, -.tdTilesm.secondary { - background-color: var(--col-300); - border-color: var(--col-300); -} - -.tdTilesm.tertiary { - background-color: var(--col-300); - border-color: var(--col-300); -} - -.block-actions .btn.btn-link { - color: var(--txt-1); -} - -.block-actions .btn.btn-link:hover, .block-actions .btn.btn-link:hover:focus, .block-actions .btn.btn-link:focus-visible { - background: var(--bg-5); - color: var(--txt-1); -} - -.btn-link:hover, .btn-link:focus-visible, .btn.btn-link:hover, .btn.btn-link:focus-visible, .sidebar-btn.btn-link:hover, .sidebar-btn.btn-link:focus-visible { - color: var(--col-500); -} - -ul.dropdown-menu .btn.btn-link[data-v-775a00fa] { - color: var(--txt-1) !important; -} - -ul.dropdown-menu .btn.btn.btn-link[data-v-775a00fa]:hover { - background-color: var(--col-300) !important; - color: var(--txt-1) !important; -} - -.copyButton { - color: var(--txt-2) !important; - background-color: var(--bg-0) !important; - border-color: var(--border-0) !important; -} - -.copyButton:hover { - background-color: var(--bg-2) !important; -} - -.js-open-monitor .btn { - color: var(--col-1); -} - -.js-open-monitor .btn:hover { - color: var(--col-2); -} - -/* .btn:hover, .btn:hover:focus, .btn:focus-visible { - background: var(--bg-1); -} */ - -.btn:focus:not(:focus-visible,.active,:active,:hover) { - color: var(--txt-5); - background-color: var(--col-400); -} - -.btn:hover, .btn:hover:focus, .btn:focus-visible { - color: var(--txt-5); - background-color: var(--col-600); -} - -.popover { - background-color: var(--bg-0); - box-shadow: 0 5px 10px var(--shadow-1); - border-color: var(--border-0); -} - -.popover.right > .arrow { - border-right-color: var(--border-0); -} - -.popover.right > .arrow::after { - border-right-color: var(--bg-0); -} - -/* Tables */ - -table.table { - color: var(--txt-1) !important; - border-color: var(--border-0); -} - -.tdx-table__th { - background-color: var(--bg-0) !important; - color: var(--col-600) !important; -} - -.tdx-table__td { - color: var(--txt-2) !important; -} - -.tdx-table-fade-right { - background: linear-gradient(to right,transparent,var(--bg-0)) !important; -} - -thead, tbody, tfoot, tr, td, th { - border-color: var(--border-0); -} - -.tdx-pagination-bar { - background-color: var(--bg-0) !important; -} - -.tdx-pagination-bar__item-count { - color: var(--txt-2) !important; -} - -.tdx-dashboard__widget-container { - box-shadow: 0 .5px 1px 1px var(--shadow-1),0 2px 4px var(--shadow-2),0 4px 6px var(--shadow-1) !important; -} - -.tdx-widget-selector__widget-option { - box-shadow: 0 .5px 1px 1px var(--shadow-1),0 2px 4px var(--shadow-2),0 4px 6px var(--shadow-2) !important; -} - -.tdx-widget-selector__widget-name { - color: var(--txt-1) !important; -} - -.tdx-widget-selector__category { - color: var(--col-600) !important; -} - -.tdx-widget-selector__widget-option:hover, .tdx-widget-selector__widget-option:focus { - outline-color: var(--col-400) !important; -} - -.tdx-dashboard-row-editor { - background-color: var(--col-100) !important; - box-shadow: 0 .5px 1px 1px var(--shadow-1),0 2px 4px var(--shadow-2),0 4px 6px var(--shadow-2) !important; -} - -.tdx-dashboard-row-editor__column { - background-color: var(--bg-0) !important; -} - -.tdx-dashboard-row-editor__selected-widget { - background-color: var(--bg-0) !important; - outline-color: var(--border-0) !important; -} - -.tdx-dashboard-row-editor__selected-widget-category-text { - color: var(--col-600) !important; -} - -.tdx-dashboard-editor__add-widget { - color: var(--txt-3) !important; -} - -.tdx-dashboard-editor__add-widget:hover, .tdx-dashboard-editor__add-widget:focus-visible { - box-shadow: 0 .5px 1px 1px var(--shadow-1),0 2px 4px var(--shadow-2),0 4px 6px var(--shadow-2) !important; -} - -.tdx-control-bar { - background-color: var(--bg-0) !important; -} - -.tdx-control-bar__title { - color: var(--txt-1) !important; -} - -.tdx-confirmation-dialog { - background-color: var(--bg-0); - color: var(--col-600); -} - -.tdx-confirmation-dialog__text-area { - color: var(--col-600); -} - -.k-grid, .k-pager, .k-table { - background-color: var(--bg-0) !important; - color: var(--txt-1) !important; -} - -.k-table-tbody>.k-table-row:not(.k-table-group-row):first-child>.k-table-td, -.k-table-tbody>.k-table-row:not(.k-table-group-row)>.k-table-td { - border-color: var(--border-0) !important; -} - -.k-grid-header, .k-grid-pager { - background-color: var(--bg-0) !important; - color: var(--txt-0) !important; -} - -.k-grid .k-table-row.k-table-alt-row { - background-color: var(--bg-0); -} - -.k-grid .k-table-row { - background-color: var(--bg-1); /* can change to 0 for non-striped rows */ -} - -td.k-table-td { - /* background-color: var(--bg-1); */ -} - -tr.k-alt td.k-table-td { - background-color: var(--bg-0) -} - -.k-table-th { - background-color: var(--bg-0) !important; -} - -.k-grid .k-grid-header .k-table-th { - color: var(--txt-4) !important; -} - -.k-grid .k-grid-header .k-table-th, .k-table-tbody .k-group-cell { - background-color: unset; -} - -.k-table-th, .k-table-td, -td.k-table-td { - background-color: unset; -} - -.k-grid .k-table-tbody>.k-table-row:not(.k-detail-row):not([style]):hover, .k-grid .k-table-tbody>.k-table-row:not(.k-detail-row).k-hover { - background-color: var(--bg-1) !important; -} - -.k-grid .k-table-tbody>.k-table-alt-row:not(.k-detail-row):not([style]):hover, .k-grid .k-table-tbody>.k-table-alt-row:not(.k-detail-row).k-hover:not([style]) { - background-color: var(--bg-0) !important; -} - -button.k-pager-nav.k-button.k-button-flat.k-button-flat-base.k-icon-button.k-button-md { - background-color: var(--bg-0) !important; - color: var(--col-400) !important; -} - -.k-pager-md .k-pager-numbers-wrap .k-button.k-pager-nav.k-disabled, -button.k-pager-nav.k-button.k-button-flat.k-button-flat-base.k-icon-button.k-pager-last.k-button-md { - background-color: var(--bg-0) !important; - color: var(--col-400) !important; -} - -button.k-pager-nav.k-button.k-button-flat.k-button-flat-base.k-icon-button.k-pager-last.k-button-md.k-disabled, -button.k-pager-nav.k-button.k-button-flat.k-button-flat-base.k-icon-button.k-button-md.k-disabled { - color: var(--bg-2) !important; -} - -.k-pager-md .k-pager-numbers-wrap .k-button.k-pager-nav:hover { - color: var(--col-600) !important; -} - -#lookupIframeWrapper { - background-color: var(--bg-0); -} - -.k-window, .k-window:focus { - background: var(--bg-0); - box-shadow: 0 8px 16px var(--shadow-1),0 24px 38px var(--shadow-2); -} - -.k-window-titlebar { - background-color: var(--bg-0) !important; -} - -.k-window-content { - background-color: var(--bg-0) !important; -} - -.k-window-title { - color: var(--col-500) !important; -} - -.k-button .k-svg-i-window { - color: var(--col-500); -} - -.k-button .k-svg-i-x { - color: var(--col-500); -} - -button.k-button.k-button-md.k-button-flat.k-button-flat-primary.k-selected { - background-color: var(--col-100) !important; -} - -button.k-selected { - background-color: var(--col-1) !important; - color: var(--col-400) !important; -} - -.k-pager-md .k-pager-numbers-wrap .k-button { - color: var(--col-400) !important; -} - -button.k-button.k-button-md.k-button-flat.k-button-flat-primary:hover { - color: var(--col-500); - background-color: var(--col-100)!important; -} - -.k-pager-md .k-pager-numbers-wrap .k-button.k-pager-nav { - background-color: var(--bg-0) !important; -} - -.tdx-pagination-bar { - background-color: var(--bg-0); -} - -.tdx-pagination-bar__active-page-item { - color: var(--col-400); - background-color: var(--col-200); -} - -.tdx-pagination-bar__page-item:hover:not(.tdx-pagination-bar__active-page-item,.tdx-pagination-bar__separator) { - color: var(--col-500); - background-color: var(--col-100); -} - -.tdx-pagination-bar .fa, .tdx-pagination-bar a { - color: var(--col-400); -} - -.tdx-pager-button .fa-chevron-right, .tdx-pager-button .fa-chevron-left { - -webkit-text-stroke-color: var(--bg-0); -} - -.hilite, .hilite .btn-link, .hilite a, .hilite td, .table>tbody>tr.hilite label, .table>tbody>tr.hilite.active, .table>tbody>tr.hilite.danger, .table>tbody>tr.hilite.info, .table>tbody>tr.hilite.success, .table>tbody>tr.hilite.warning, .table>tbody>tr.hilite>td.active, .table>tbody>tr.hilite>td.danger, .table>tbody>tr.hilite>td.info, .table>tbody>tr.hilite>td.success, .table>tbody>tr.hilite>td.warning { - color: var(--txt-5); - background-color: var(--bg-5) !important; -} - -.tdworkmgmt.table-header > div { - background-color: var(--bg-1); - color: var(--col-400); -} - -/* Side Panels */ - -.tdx-right-side-panel { - background-color: var(--bg-0) !important; - box-shadow: 0 8px 16px var(--shadow-1),0 24px 38px var(--shadow-2) !important; -} - -.white-bg, .white-hover-bg:hover { - background-color: var(--bg-0) !important; -} - -.tdx-right-side-panel__drag-border { - background: linear-gradient(var(--col-400),var(--col-400)) no-repeat left/1px 10% !important; -} - -.tdx-right-side-panel__drag-border:hover { - border-color: var(--col-400) !important; -} - -.tdx-right-side-panel__header-title { - color: var(--txt-2) !important; -} - -.tdx-right-side-panel__drag-border:focus-visible, .tdx-right-side-panel__drag-border.active { - border-color: var(--col-500) !important; -} - - -.tdx-right-side-panel__home-button { - color: var(--col-400) !important; - border-color: var(--col-500) !important; -} - -.tdx-right-side-panel__home-button:hover { - color: var(--col-200) !important; - border-color: var(--col-300) !important; -} - -.tdx-leftnav-drag-handle { - background: linear-gradient(var(--col-400),var(--col-400)) no-repeat right/1px 10% !important; -} - -.tdx-leftnav-drag-handle:hover { - background-color: var(--col-400) !important; -} - -.tdx-leftnav-drag-handle:focus-visible, .tdx-leftnav-drag-handle.active { - background-color: var(--col-500) !important;; -} - -/* Tickets */ - -.control-label, label.control-label, span.control-label { - color: var(--txt-3) !important; -} - -.control-label~* { - color: var(--txt-1) !important; -} - -.black { - color: var(--txt-1) !important; -} - -nav#divTabHeader, -.TabButtonCell, .tab-row, -.tdx-button-bar { - background-color: var(--col-100) !important; -} - -.panel-default>.panel-heading { - background-color: var(--bg-0) !important; - border-color: var(--border-0) !important; -} - -.panel-body, .panel-footer { - background-color: var(--bg-0) !important; - border-color: var(--border-0) !important; -} - -.panel { - background-color: var(--bg-0) !important; -} - -.panel-body, .panel-footer { - color: var(--txt-3) !important; -} - -.h2, h2, h2.h3, .panel-title { - color: var(--txt-1) !important; - border-color: var(--border-0) !important; -} - -.alert-info, div.alert-info { - color: var(--txt-1) !important; - background-color: var(--col-blue) !important; -} - -.alert-warning, div.alert-warning { - color: var(--txt-1) !important; - background-color: var(--col-yellow) !important; -} - -.nav-tabs>li.active>a, .nav-tabs>li.active>button, .nav-pills>li.active>a, .nav-pills>li.active>button { - color: var(--col-600) !important; - background-color: var(--bg-0) !important; - border-color: var(--border-0); - box-shadow: 0 .5px 1px 1px var(--shadow-1),0 2px 4px var(--shadow-2),0 4px 6px var(--shadow-2) !important; -} - -.nav-tabs>li>a, .nav-tabs>li>a:hover, .nav-tabs>li>button, .nav-tabs>li>button:hover, .nav-pills>li>a, .nav-pills>li>a:hover { - color: var(--txt-3); -} - -.nav-tabs>li>a:hover, .nav-tabs>li>a:hover:hover { - color: var(--txt-2); - border-color: var(--border-0); -} - -.nav-tabs>li>a:hover { - color: var(--col-600); -} - -a.btn.btn-link.tdx-tertiary-button-override { - background-color: var(--col-100) !important; - color: var(--txt-1) !important; -} - -.gray, .gray-hover:hover { - color: var(--txt-3) !important; -} - -.dropdown-menu { - background-color: var(--bg-0) !important; - color: var(--txt-1) !important; - box-shadow: 0 1px 3px var(--shadow-1),0 2px 10px var(--shadow-2); -} - -.dropdown-menu li { - color: var(--txt-1); - background-color: var(--bg-0); -} - -.dropdown-menu>span>li>a:hover, .dropdown-menu>span>li>a:focus, .dropdown-menu>span>li:hover, .dropdown-menu>span>li:focus, .dropdown-menu>li>a:hover, .dropdown-menu>li>span>a:hover, .dropdown-menu>li>a:focus, .dropdown-menu>li>span>a:focus, -.dropdown-menu li:hover { - color: var(--txt-1); - background-color: var(--col-300); -} - -.TabButtonCell .btn-primary.active, .TabButtonCell .btn-primary.active:hover, .TabButtonCell .btn-primary.active:focus, .TabButtonCell .btn-primary:active, .TabButtonCell .btn-primary:active:hover, .TabButtonCell .btn-primary:active:focus, .TabButtonCell .btn-info.active, .TabButtonCell .btn-info.active:hover, .TabButtonCell .btn-info.active:focus, .TabButtonCell .btn-info:active, .TabButtonCell .btn-info:active:hover, .TabButtonCell .btn-info:active:focus, .tab-row .btn-primary.active, .tab-row .btn-primary.active:hover, .tab-row .btn-primary.active:focus, .tab-row .btn-primary:active, .tab-row .btn-primary:active:hover, .tab-row .btn-primary:active:focus, #divViewButtons.active, #divViewButtons.active:hover, #divViewButtons.active:focus, #divViewButtons:active, #divViewButtons:active:hover, #divViewButtons:active:focus, .TabButtonCell .btn-primary:active.active, .TabButtonCell .btn-primary:active.active:hover, .TabButtonCell .btn-primary:active.active:focus, .TabButtonCell .btn-primary:active:active, .TabButtonCell .btn-primary:active:active:hover, .TabButtonCell .btn-primary:active:active:focus, .tab-row .btn-primary:active.active, .tab-row .btn-primary:active.active:hover, .tab-row .btn-primary:active.active:focus, .tab-row .btn-primary:active:active, .tab-row .btn-primary:active:active:hover, .tab-row .btn-primary:active:active:focus { - background: var(--col-600); - color: var(--txt-1); -} - -div.btn-group.open>.dropdown-toggle.btn-primary, .open>.dropdown-toggle.btn-primary, .open>.dropdown-toggle.btn-primary:hover, .open>.dropdown-toggle.btn-primary:focus { - background: var(--col-100); - color: var(--txt-1); -} - -.TabButtonCell .btn-primary:focus:not(:focus-visible,.active,:active,:hover), .TabButtonCell .btn-info:focus:not(:focus-visible,.active,:active,:hover), .tab-row .btn-primary:focus:not(:focus-visible,.active,:active,:hover), #divViewButtons:focus:not(:focus-visible,.active,:active,:hover), .TabButtonCell .btn-primary:active:focus:not(:focus-visible,.active,:active,:hover), .tab-row .btn-primary:active:focus:not(:focus-visible,.active,:active,:hover) { - background: var(--col-100); - color: var(--txt-1); -} - -.btn-primary--tertiary { - background-color: var(--bg-0) !important; - color: var(--txt-1) !important; - border-color: var(--bg-0) !important; -} - -.btn-primary--tertiary:hover, .btn-primary--tertiary:hover:focus, .btn-primary--tertiary:focus-visible { - background-color: var(--col-200) !important; - color: var(--col-400) !important; -} - -.time-cell-approved { - background-color: var(--col-green); -} - -.time-cell-rejected { - background-color: var(--col-red); -} - -[class^=fa-].red, [class^=fa-].red:hover { - color: var(--col-red) !important; -} - -[class^=fa-].green, [class^=fa-].green:hover { - color: var(--col-green) !important; -} - -.tdx-error-text, span.tdx-error-text, -.tdx-error-text:hover, span.tdx-error-text:hover { - /* color: var(--col-red) !important; */ - color: var(--col-600) !important; -} - -.red-bg, -.status.red, .status-danger, .pri-hi { - background-color: var(--col-red) !important; - color: var(--txt-1) !important; -} - -.status.blue, .status.gray, .status-primary, .status-default { - background-color: var(--col-blue); - color: var(--txt-1) !important; -} - -.status-warning { - background-color: var(--col-yellow); - color: var(--txt-1) !important; -} - -.status.green, .status-success, -.js-open-monitor .btn .label-success { - background-color: var(--col-green); - color: var(--txt-1) !important; -} - -div.feed-body>div.feed-child-box { - background-color: var(--col-100); - color: var(--txt-1); -} - -.modal-content { - background-color: var(--bg-0); -} - -.modal-dialog { - box-shadow: 0 8px 16px var(--shadow-1),0 24px 38px var(--shadow-2); -} - -.modal-title { - color: var(--txt-1); -} - -.tdx-modal { - background-color: var(--bg-0) !important; - box-shadow: 0 0 8px var(--shadow-1),0 5px 12px var(--shadow-1),0 15px 35px var(--shadow-2); -} - -.tdx-modal .modal-content { - color: var(--txt-1) !important; -} - -.tdx-modal__iframe-header, -.tdx-modal__iframe-footer { - background-color: var(--bg-0) !important; -} - -.modal-content { - background-color: var(--bg-0) !important; -} - -hr { - background-color: var(--col-300); -} - -blockquote { - border-color: var(--border-0); -} - -.code, code, pre { - background-color: var(--bg-1); - color: var(--txt-1); - border-color: var(--border-0); -} - -div.comment { - background-color: var(--col-100); -} - -.block-actions { - background-color: var(--bg-0); -} - -body .tdworkmgmt.table>thead>tr>th, body .tdworkmgmt.table>tbody>tr>th, body .tdworkmgmt.table>tfoot>tr>th, body .tdworkmgmt.table>tbody>tr.TDGridHeader>td, body .tdworkmgmt.table>thead>tr.TDGridHeader>td { - background-color: var(--bg-0); - color: var(--txt-1); -} - -body .tdworkmgmt.table>tbody>tr:not(.tdx-grid__group-header):not(.TDGridHeader)>td { - color: var(--txt-1); - border-color: var(--border-0); -} - -body .tdworkmgmt.table>tbody>tr:not(.tdx-grid__group-header):not(.TDGridHeader):last-child:not(.TDPagerRow) th, body .tdworkmgmt.table>tbody>tr:not(.tdx-grid__group-header):not(.TDGridHeader):last-child:not(.TDPagerRow) td { - border-color: var(--border-0); -} - -.tdworkmgmt td a, .tdworkmgmt.table .hilite a { - color: var(--col-400); -} - -.tdworkmgmt td a:hover, .tdworkmgmt td a:focus-visible, .tdworkmgmt.table .hilite a:hover, .tdworkmgmt.table .hilite a:focus-visible { - color: var(--col-0); -} - -.input-group-addon { - background-color: var(--bg-5); - color: var(--txt-1); -} - -.list-group-item { - background-color: var(--bg-0); - border-color: var(--border-0); -} - -/* Text Editor */ -.cke_editable { - color: var(--txt-1); - background-color: var(--bg-4); -} - -.cke_wysiwyg_div, .cke_wysiwyg_frame { - background: var(--bg-0) !important; -} - -.cke_combo_button, .cke_toolgroup { - background: var(--bg-0) !important; -} - -.cke_button_icon { - opacity: 1 !important; - filter: invert(var(--txt-invert)) !important; -} - -.cke_combo_text { - color: var(--txt-2) !important; -} - -.cke_panel_grouptitle { - background: var(--bg-2) !important; - color: var(--txt-1); -} - -.cke_panel_listItem a:active, .cke_panel_listItem a:focus, .cke_panel_listItem a:hover { - background: var(--bg-3) !important; -} - -a.cke_button_disabled:active, a.cke_button_disabled:focus, a.cke_button_disabled:hover, a.cke_button_off:active, a.cke_button_off:focus, a.cke_button_off:hover { - background: var(--bg-3) !important; -} - -.cke_bottom, .cke_top, .cke_chrome { - background-color: var(--bg-1) !important; - color: var(--txt-2) !important; -} - -.cke_combo_button, -.cke_toolgroup, -.cke_contents { - border-color: var(--border-0) !important; -} - -div .cke_top, div .cke_bottom, div .comment-options, div .cke_chrome { - background-color: var(--col-100) !important; -} - -.cke_panel_listItem a { - border: none; -} - -.cke_panel, -.cke_panel_grouptitle { - border-color: var(--border-0) !important; -} - -a.cke_colorbox, -a.cke_colorauto, a.cke_colormore { - border-color: var(--border-0) !important; -} - -.cke_colorblock, .cke_colorblock a { - color: var(--txt-1); -} - -a:active.cke_colorauto, a:active.cke_colormore, a:focus.cke_colorauto, a:focus.cke_colormore, a:hover.cke_colorauto, a:hover.cke_colormore { - background: var(--bg-3) !important; -} - -a:active.cke_colorbox, a:focus.cke_colorbox, a:hover.cke_colorbox { - background: var(--bg-3) !important; -} - -.cke_dialog_contents, .cke_dialog_body { - color: var(--txt-1) !important; - background: var(--bg-2) !important; -} - -.cke_dialog_footer, .cke_dialog_title { - background: var(--bg-1) !important; -} - -.cke_reset_all, .cke_reset_all * { - color: var(--txt-2) !important; -} - -.cke_dialog_page_contents a.cke_dialog_ui_button, a.cke_dialog_ui_button_cancel { - background: var(--bg-3) !important; -} - -input.cke_dialog_ui_input_password, input.cke_dialog_ui_input_text, textarea.cke_dialog_ui_input_textarea { - background: var(--bg-3) !important; -} - -a.cke_dialog_tab_selected { - background: var(--bg-2) !important; -} - -a.cke_dialog_tab { - background: var(--bg-3) !important; -} - -select.cke_dialog_ui_input_select { - background-color: var(--bg-4) !important; -} - -.cke_button_on { - background: var(--bg-2) !important; -} - -.dropdown-menu>li>a, .dropdown-menu>span>li>a, .dropdown-menu>li>span>a { - color: var(--txt-1) !important; -} - -/* Icons */ -.js-help a, .js-help .fa-solid, .js-default-help a, .js-default-help .fa-solid, -.disp-group .control-label>a>span { - color: var(--col-400); -} - -.js-help a:hover, .js-help a:focus-visible, .js-help a:active, .js-help a:active:hover, .js-help a:focus:active, .js-help a:focus:hover, .js-help .fa-solid:hover, .js-help .fa-solid:focus-visible, .js-help .fa-solid:active, .js-help .fa-solid:active:hover, .js-help .fa-solid:focus:active, .js-help .fa-solid:focus:hover, .js-default-help a:hover, .js-default-help a:focus-visible, .js-default-help a:active, .js-default-help a:active:hover, .js-default-help a:focus:active, .js-default-help a:focus:hover, .js-default-help .fa-solid:hover, .js-default-help .fa-solid:focus-visible, .js-default-help .fa-solid:active, .js-default-help .fa-solid:active:hover, .js-default-help .fa-solid:focus:active, .js-default-help .fa-solid:focus:hover, -.disp-group .control-label>a>span:hover, .disp-group .control-label>a>span:focus-visible, .disp-group .control-label>a>span:active, .disp-group .control-label>a>span:active:hover, .disp-group .control-label>a>span:focus:active, .disp-group .control-label>a>span:focus:hover { - color: var(--col-500); -} - -.tdx-lookup-button-group a, .tdx-lookup-button-group button, .input-btn-group a, .input-btn-group button, -div.select2-container.select2-allowclear .select2-choice abbr { - color: var(--col-400); -} - -.tdx-lookup-button-group a:hover, .tdx-lookup-button-group a:focus-visible, .tdx-lookup-button-group a:active, .tdx-lookup-button-group a:active:hover, .tdx-lookup-button-group a:focus:active, .tdx-lookup-button-group a:focus:hover, .tdx-lookup-button-group button:hover, .tdx-lookup-button-group button:focus-visible, .tdx-lookup-button-group button:active, .tdx-lookup-button-group button:active:hover, .tdx-lookup-button-group button:focus:active, .tdx-lookup-button-group button:focus:hover, .input-btn-group a:hover, .input-btn-group a:focus-visible, .input-btn-group a:active, .input-btn-group a:active:hover, .input-btn-group a:focus:active, .input-btn-group a:focus:hover, .input-btn-group button:hover, .input-btn-group button:focus-visible, .input-btn-group button:active, .input-btn-group button:active:hover, .input-btn-group button:focus:active, .input-btn-group button:focus:hover { - color: var(--col-500); -} - -.tdx-icon__encircled--active { - background-color: var(--col-200) !important; -} - -.tdx-icon__encircled--active:hover { - background-color: var(--col-300) !important; -} - -.tdx-icon__encircled:not(.tdx-icon__encircled--active) { - background-color: var(--bg-0) !important; -} - -.tdx-icon__encircled:not(.tdx-icon__encircled--active):hover { - background-color: var(--col-200) !important; -} - -.tdx-user-icon, .tdx-multiuser-icon, -div.profile-image.red-bg, div.profile-image.green-bg, div.profile-image.red-bg, div.profile-image.blue-bg, div.profile-image.yellow-bg, div.profile-image.gray-bg, div.profile-image.initials.red-bg, div.profile-image.initials.green-bg, div.profile-image.initials.red-bg, div.profile-image.initials.blue-bg, div.profile-image.initials.yellow-bg, div.profile-image.initials.gray-bg { - background-color: var(--col-400) !important; - color: var(--col-100) !important; -} - -.tdx-widget-indicator-icon { - color: var(--col-600) !important; -} - -.tdx-dirty-indicator { - color: var(--col-400) !important; -} - -.tdx-hover-darken { - color: var(--col-400); -} - -.tdx-hover-darken:hover { - color: var(--col-300); -} - -.form-group>a, .form-group>.checkbox>a, .disp-group>a, .form-group>.control-label>a, .checkbox>label>a { - color: var(--col-400) !important; -} - -.form-group>a:hover, .form-group>.checkbox>a:hover, .disp-group>a:hover, .form-group>.control-label>a:hover, .checkbox>label>a:hover { - color: var(--col-500) !important; -} - -.k-table-th[data-role=columnsorter] .k-link:not(:has(>.k-sort-icon)):after { - color: var(--col-400) !important; -} - -.k-table-th[data-role=columnsorter] .k-link:not(:has(>.k-sort-icon)):hover:after { - color: var(--col-500) !important; -} - -.tdx-calendar .fa-plus { - color: var(--col-300) !important; -} - -/* Icons + Filters */ -.tdx-dropdown__menu-icon, -.tdx-dropdown--headline:after, -.tdx-dropdown:after, -.tdx-icon--search, -.k-icon -{ - filter: brightness(0) invert(var(--filter-invert)) sepia(var(--filter-sepia)) saturate(var(--filter-saturate)) hue-rotate(var(--filter-hue-rotate)) brightness(var(--filter-brightness)) contrast(var(--filter-contrast)); -} - -/* Same but with !important */ -.tdx-icon__encircled--active .tdx-icon, -.tdx-icon--filter-purple, -.tdx-navigation-tabs__tab--active .tdx-close-x, -.tdx-icon--new-browser, -.tdx-close-x, button.tdx-close-x, -.tdx-action-menu__item--primary:after, -.tdx-action-menu-dropdown:after, -.tdx-icon.tdx-icon--hover-darken, .tdx-icon--hover-darken>.tdx-icon, -.tdx-dropdown__menu-icon, .tdx-dropdown--headline:after, .tdx-dropdown:after, .tdx-icon--search, .tdx-icon:not(.label), -div.select2-container-multi .select2-choices .select2-search-choice>.select2-search-choice-close:hover, div.select2-container-multi .select2-choices .select2-search-choice>.select2-search-choice-close:focus-visible, div.select2-container-multi .select2-choices .select2-search-choice>.select2-search-choice-close:active, div.select2-container-multi .select2-choices .select2-search-choice>.select2-search-choice-close:active:hover, div.select2-container-multi .select2-choices .select2-search-choice>.select2-search-choice-close:focus:active, div.select2-container-multi .select2-choices .select2-search-choice>.select2-search-choice-close:focus:hover -{ - filter: brightness(0) invert(var(--filter-invert)) sepia(var(--filter-sepia)) saturate(var(--filter-saturate)) hue-rotate(var(--filter-hue-rotate)) brightness(var(--filter-brightness)) contrast(var(--filter-contrast)) !important; -} - -/* Hover + !important */ -.tdx-icon__encircled:hover .tdx-icon, -.tdx-close-x:hover, button.tdx-close-x:hover, -.tdx-icon.tdx-icon--hover-darken:hover, .tdx-icon.tdx-icon--hover-darken:focus, .tdx-icon--hover-darken>.tdx-icon:hover, .tdx-icon--hover-darken>.tdx-icon:focus, -.tdx-leftnav__item-expander:hover .tdx-icon, .tdx-leftnav__item-expander:focus .tdx-icon, -.tdx-action-menu-dropdown--no-arrow:hover .tdx-icon, .tdx-action-menu-dropdown--no-arrow.active .tdx-icon, -div.select2-container-multi .select2-choices .select2-search-choice>.select2-search-choice-close -{ - filter: brightness(0) invert(var(--filter-invert)) sepia(var(--filter-sepia)) saturate(var(--filter-saturate)) hue-rotate(var(--filter-hue-rotate)) brightness(var(--filter-brightness)) contrast(var(--filter-contrast)) brightness(125%) !important; -} - - ` - - //const customStyles = GM_getResourceText("IMPORTED_CSS"); - GM_addStyle(customStyles); - setCssFilters() - parseOtherElements() - -})(); \ No newline at end of file