Skip to content

Instantly share code, notes, and snippets.

@AsP3X
Last active September 3, 2026 11:31
Show Gist options
  • Select an option

  • Save AsP3X/32a79618f153b86f281d9c063b58e2db to your computer and use it in GitHub Desktop.

Select an option

Save AsP3X/32a79618f153b86f281d9c063b58e2db to your computer and use it in GitHub Desktop.
A last modified filter highlighter for freshservice.
// ==UserScript==
// @name Freshservice Stale Tickets
// @namespace sth
// @version 1.4
// @description Highlight stale Freshservice tickets and open them in tabs
// @match https://*.freshservice.com/*
// @match https://*.myfreshworks.com/*
// @match *://*/a/tickets*
// @run-at document-idle
// @grant none
// ==/UserScript==
(() => {
const NS = 'sth';
const HOST_ID = `${NS}-host`;
const STYLE_ID = `${NS}-page-style`;
const ROW_MARK = `${NS}-row`;
const CELL_MARK = `${NS}-cell`;
const ROW_SEL = 'tr.et-tr';
const DATE_SEL = 'td[data-name="updated_at_date"] [data-test-id="date-cell"]';
const TICKET_LINK_SEL = 'a.subject-cell[href], a[href*="/tickets/"]';
const STORAGE_KEY = `${NS}-settings`;
const MS_DAY = 24 * 60 * 60 * 1000;
const DEFAULTS = {
days: 6,
color: '#e65100',
enabled: true,
collapsed: false,
statuses: [],
statusOpen: false,
x: null,
y: null
};
const loadSettings = () => {
try {
return { ...DEFAULTS, ...JSON.parse(localStorage.getItem(STORAGE_KEY) || '{}') };
} catch {
return { ...DEFAULTS };
}
};
const saveSettings = (s) => localStorage.setItem(STORAGE_KEY, JSON.stringify(s));
let settings = loadSettings();
if (!Array.isArray(settings.statuses)) settings.statuses = [];
if (settings.statusOpen == null) settings.statusOpen = false;
document.getElementById(HOST_ID)?.remove();
document.getElementById(STYLE_ID)?.remove();
window.__staleTicketObserver?.disconnect();
const pageStyle = document.createElement('style');
pageStyle.id = STYLE_ID;
document.head.appendChild(pageStyle);
const hexToRgba = (hex, a) => {
const h = hex.replace('#', '');
const n = h.length === 3 ? h.split('').map((c) => c + c).join('') : h;
return `rgba(${parseInt(n.slice(0, 2), 16)}, ${parseInt(n.slice(2, 4), 16)}, ${parseInt(n.slice(4, 6), 16)}, ${a})`;
};
const applyPageStyles = () => {
const c = settings.color;
pageStyle.textContent = `
.${ROW_MARK} {
background-color: ${hexToRgba(c, 0.18)} !important;
box-shadow: inset 4px 0 0 ${c} !important;
}
.${ROW_MARK} > td {
background-color: ${hexToRgba(c, 0.18)} !important;
}
.${CELL_MARK} {
background-color: ${hexToRgba(c, 0.35)} !important;
outline: 2px solid ${c} !important;
border-radius: 3px;
}
`;
};
const MONTHS = {
jan: 0, feb: 1, mar: 2, apr: 3, may: 4, jun: 5,
jul: 6, aug: 7, sep: 8, oct: 9, nov: 10, dec: 11
};
function parseTicketDate(raw) {
if (!raw) return null;
const str = String(raw).replace(/\s+/g, ' ').trim();
let m = str.match(/(\d{1,2})\s+([A-Za-z]{3})\.?,?\s+(\d{4})(?:[,\s]+(\d{1,2}):(\d{2}))?/);
if (m && MONTHS[m[2].toLowerCase()] != null) {
return new Date(+m[3], MONTHS[m[2].toLowerCase()], +m[1], +(m[4] || 0), +(m[5] || 0));
}
m = str.match(/(\d{1,2})[./](\d{1,2})[./](\d{4})(?:[,\s]+(\d{1,2}):(\d{2}))?/);
if (m) return new Date(+m[3], +m[2] - 1, +m[1], +(m[4] || 0), +(m[5] || 0));
const native = new Date(str.replace(/,/g, ''));
return Number.isNaN(native.getTime()) ? null : native;
}
function ticketHref(row) {
const a = row.querySelector(TICKET_LINK_SEL);
if (!a) return null;
try {
return new URL(a.getAttribute('href'), location.origin).href;
} catch {
return null;
}
}
function rowStatus(row) {
const el = row.querySelector('.status-result, td[data-name="status"] [title]');
return String(el?.getAttribute('title') || el?.textContent || '').replace(/\s+/g, ' ').trim();
}
function statusWanted(row) {
const tags = (settings.statuses || []).map((s) => s.toLowerCase());
if (!tags.length) return false;
return tags.includes(rowStatus(row).toLowerCase());
}
function collectStaleRows() {
const now = Date.now();
const out = [];
document.querySelectorAll(ROW_SEL).forEach((row) => {
const cell = row.querySelector(DATE_SEL);
const date = cell ? parseTicketDate(cell.getAttribute('title') || cell.textContent) : null;
const stale = !!(date && (now - date.getTime()) / MS_DAY >= settings.days);
const byStatus = statusWanted(row);
if (!stale && !byStatus) return;
out.push({ row, cell, href: ticketHref(row), date, stale, byStatus });
});
return out;
}
function clearMarks() {
document.querySelectorAll(`.${ROW_MARK}`).forEach((el) => {
el.classList.remove(ROW_MARK);
el.removeAttribute('data-stale-days');
});
document.querySelectorAll(`.${CELL_MARK}`).forEach((el) => el.classList.remove(CELL_MARK));
}
let lastStats = { tickets: 0, marked: 0 };
function markTickets() {
clearMarks();
const rows = document.querySelectorAll(ROW_SEL);
const stale = collectStaleRows();
if (settings.enabled) {
const now = Date.now();
stale.forEach(({ row, cell, date, byStatus }) => {
row.classList.add(ROW_MARK);
if (date) row.dataset.staleDays = String(Math.floor((now - date.getTime()) / MS_DAY));
if (byStatus) row.dataset.statusMark = rowStatus(row);
if (cell) cell.classList.add(CELL_MARK);
});
}
lastStats = { tickets: rows.length, marked: stale.length };
renderStats();
}
function openStaleTickets() {
markTickets();
const urls = [...new Set(collectStaleRows().map((x) => x.href).filter(Boolean))];
if (!urls.length) {
console.log('[stale-tickets] no stale ticket links on this page');
return;
}
if (urls.length > 8 && !confirm(`Open ${urls.length} stale tickets in new tabs?`)) return;
let opened = 0;
urls.forEach((url) => {
const win = window.open(url, '_blank', 'noopener');
if (win) opened += 1;
});
if (opened < urls.length) {
alert(`Opened ${opened} of ${urls.length} tabs. Allow pop-ups for this site to open the rest.`);
}
}
const host = document.createElement('div');
host.id = HOST_ID;
host.style.cssText = 'all:initial;position:fixed;z-index:2147483647;bottom:20px;right:20px;top:auto;left:auto;touch-action:none;';
document.documentElement.appendChild(host);
const shadow = host.attachShadow({ mode: 'open' });
shadow.innerHTML = `
<style>
:host { all: initial; }
* { box-sizing: border-box; font-family: Inter, ui-sans-serif, system-ui, -apple-system, Segoe UI, sans-serif; }
.fab, .panel {
color: #e8eaed;
background: linear-gradient(180deg, rgba(28,32,38,.92), rgba(18,20,24,.94));
border: 1px solid rgba(255,255,255,.10);
box-shadow: 0 18px 50px rgba(0,0,0,.35), 0 0 0 1px rgba(255,255,255,.04) inset;
backdrop-filter: blur(18px);
-webkit-backdrop-filter: blur(18px);
}
.fab {
display: none; align-items: center; gap: 8px; height: 44px;
padding: 0 14px 0 8px; border-radius: 999px;
cursor: grab; user-select: none;
}
.fab.show { display: flex; }
.fab:active, .fab.dragging { cursor: grabbing; }
.fab .dot {
width: 28px; height: 28px; border-radius: 50%;
display: grid; place-items: center; pointer-events: none;
background: var(--accent, #e65100); color: #fff; font-size: 12px; font-weight: 700;
}
.fab .label { font-size: 13px; font-weight: 600; pointer-events: none; }
.panel { width: 288px; border-radius: 18px; overflow: hidden; }
.panel.hide { display: none; }
.panel.dragging, .fab.dragging { opacity: .92; }
.head {
display: flex; align-items: center; gap: 10px;
padding: 14px 14px 12px;
border-bottom: 1px solid rgba(255,255,255,.07);
cursor: grab; user-select: none;
}
.head:active { cursor: grabbing; }
.logo {
width: 32px; height: 32px; border-radius: 9px;
display: grid; place-items: center; pointer-events: none;
background: var(--accent, #e65100); color: #fff; flex: 0 0 auto;
}
.titles { flex: 1; min-width: 0; pointer-events: none; }
.titles h1 { margin: 0; font-size: 13.5px; font-weight: 650; letter-spacing: -.01em; }
.titles p { margin: 2px 0 0; font-size: 11px; color: #9aa3ad; }
.grip { color: #6b7380; display: grid; place-items: center; pointer-events: none; }
.icon-btn {
width: 28px; height: 28px; border: 0; border-radius: 8px;
background: transparent; color: #9aa3ad; cursor: pointer;
display: grid; place-items: center;
}
.icon-btn:hover { background: rgba(255,255,255,.08); color: #fff; }
.body { padding: 14px; display: grid; gap: 14px; }
.row-between { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
.label { font-size: 11px; font-weight: 600; letter-spacing: .06em; text-transform: uppercase; color: #8b949e; }
.toggle {
width: 42px; height: 24px; border-radius: 999px; border: 0;
background: #3a4048; position: relative; cursor: pointer; padding: 0;
}
.toggle.on { background: var(--accent, #e65100); }
.toggle i {
position: absolute; top: 3px; left: 3px; width: 18px; height: 18px; border-radius: 50%;
background: #fff; transition: left .16s ease; box-shadow: 0 1px 4px rgba(0,0,0,.3);
}
.toggle.on i { left: 21px; }
.days-card {
background: rgba(255,255,255,.04);
border: 1px solid rgba(255,255,255,.06);
border-radius: 14px; padding: 12px;
}
.days-top { display: flex; align-items: baseline; justify-content: space-between; }
.days-val { font-size: 28px; font-weight: 700; letter-spacing: -.03em; line-height: 1; color: #fff; }
.days-val span { font-size: 13px; font-weight: 600; color: #9aa3ad; margin-left: 4px; }
input[type="range"] {
-webkit-appearance: none; appearance: none; width: 100%; height: 4px; margin: 14px 0 8px;
background: linear-gradient(90deg, var(--accent) var(--p, 20%), #3a4048 var(--p, 20%));
border-radius: 99px; outline: none;
}
input[type="range"]::-webkit-slider-thumb {
-webkit-appearance: none; width: 16px; height: 16px; border-radius: 50%;
background: #fff; border: 3px solid var(--accent, #e65100); cursor: pointer;
}
.presets { display: flex; gap: 6px; }
.chip {
flex: 1; height: 28px; border-radius: 8px; border: 1px solid rgba(255,255,255,.08);
background: rgba(255,255,255,.03); color: #c5cbd3; font-size: 11px; font-weight: 650; cursor: pointer;
}
.chip:hover { background: rgba(255,255,255,.07); }
.chip.on {
background: color-mix(in srgb, var(--accent) 22%, transparent);
border-color: color-mix(in srgb, var(--accent) 55%, transparent);
color: #fff;
}
.tagbox {
background: rgba(255,255,255,.04);
border: 1px solid rgba(255,255,255,.06);
border-radius: 14px; padding: 10px;
}
.tagbox-head {
width: 100%; display: flex; align-items: center; justify-content: space-between;
gap: 8px; border: 0; background: transparent; color: inherit; cursor: pointer; padding: 0;
}
.tagbox-head .chevron { color: #8b949e; transition: transform .16s ease; }
.tagbox.open .chevron { transform: rotate(180deg); }
.tagbox-body { display: none; margin-top: 8px; }
.tagbox.open .tagbox-body { display: block; }
.tag-count {
font-size: 10px; font-weight: 700; color: #9aa3ad;
background: rgba(255,255,255,.06); border-radius: 999px; padding: 2px 7px;
}
.tags { display: flex; flex-wrap: wrap; gap: 6px; }
.tag {
display: inline-flex; align-items: center; gap: 6px;
height: 24px; padding: 0 8px; border-radius: 999px;
background: color-mix(in srgb, var(--accent) 22%, transparent);
border: 1px solid color-mix(in srgb, var(--accent) 50%, transparent);
color: #fff; font-size: 11px; font-weight: 650;
}
.tag button {
width: 14px; height: 14px; border: 0; padding: 0; border-radius: 50%;
background: transparent; color: #fff; cursor: pointer; line-height: 1; font-size: 12px;
}
.tagbox input {
width: 100%; height: 30px; margin-top: 8px; border-radius: 8px;
border: 1px solid rgba(255,255,255,.10);
background: rgba(255,255,255,.05); color: #f2f4f7;
padding: 0 10px; font-size: 12px; outline: none;
}
.tagbox input::placeholder { color: #7d8692; }
.hints { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 8px; }
.hint {
height: 22px; padding: 0 8px; border-radius: 999px; cursor: pointer;
border: 1px dashed rgba(255,255,255,.16);
background: transparent; color: #9aa3ad; font-size: 11px; font-weight: 600;
}
.hint:hover { color: #fff; border-color: rgba(255,255,255,.35); }
.color-row { display: flex; gap: 8px; }
.swatch { width: 28px; height: 28px; border-radius: 8px; border: 2px solid transparent; cursor: pointer; padding: 0; }
.swatch.on { border-color: #fff; }
.picker-wrap {
position: relative; width: 28px; height: 28px; border-radius: 8px; overflow: hidden;
border: 1px dashed rgba(255,255,255,.25);
}
.picker-wrap input { position: absolute; inset: -4px; width: 36px; height: 36px; border: 0; padding: 0; cursor: pointer; background: none; }
.stats { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }
.stat { background: rgba(255,255,255,.04); border-radius: 12px; padding: 10px 12px; }
.stat b { display: block; font-size: 18px; font-weight: 700; letter-spacing: -.02em; }
.stat span { font-size: 10px; color: #8b949e; text-transform: uppercase; letter-spacing: .05em; font-weight: 600; }
.foot { display: grid; grid-template-columns: 1fr; gap: 8px; padding: 0 14px 14px; }
.ghost, .primary {
height: 34px; border-radius: 10px; font-size: 12px; font-weight: 600; cursor: pointer;
}
.ghost {
border: 1px solid rgba(255,255,255,.08);
background: transparent; color: #c5cbd3;
}
.ghost:hover { background: rgba(255,255,255,.06); color: #fff; }
.danger:hover { color: #ff8a80; border-color: rgba(255,138,128,.35); }
.primary {
grid-column: 1 / -1;
border: 0; color: #fff;
background: var(--accent, #e65100);
}
.primary:hover { filter: brightness(1.08); }
</style>
<div class="fab" id="fab" title="Drag to move · click to open">
<span class="dot" id="fabCount">0</span>
<span class="label">Stale tickets</span>
</div>
<section class="panel" id="panel">
<header class="head" id="dragHandle">
<div class="logo">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none">
<path d="M12 8v5l3 2" stroke="currentColor" stroke-width="2.2" stroke-linecap="round"/>
<circle cx="12" cy="12" r="9" stroke="currentColor" stroke-width="2.2"/>
</svg>
</div>
<div class="titles">
<h1>Stale tickets</h1>
<p>Drag to move</p>
</div>
<span class="grip" aria-hidden="true">
<svg width="12" height="16" viewBox="0 0 12 16" fill="currentColor">
<circle cx="3" cy="2" r="1.2"/><circle cx="9" cy="2" r="1.2"/>
<circle cx="3" cy="8" r="1.2"/><circle cx="9" cy="8" r="1.2"/>
<circle cx="3" cy="14" r="1.2"/><circle cx="9" cy="14" r="1.2"/>
</svg>
</span>
<button class="icon-btn" id="collapse" title="Minimize to pill">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none">
<path d="M5 12h14" stroke="currentColor" stroke-width="2.2" stroke-linecap="round"/>
</svg>
</button>
</header>
<div class="body">
<div class="row-between">
<span class="label">Highlight</span>
<button class="toggle" id="enabled" aria-label="Toggle highlight"><i></i></button>
</div>
<div class="days-card">
<div class="days-top">
<span class="label">Updated older than</span>
<div class="days-val" id="daysLabel">6<span>days</span></div>
</div>
<input type="range" id="days" min="1" max="30" step="1" />
<div class="presets">
<button class="chip" data-days="3">3d</button>
<button class="chip" data-days="6">6d</button>
<button class="chip" data-days="10">10d</button>
<button class="chip" data-days="14">14d</button>
</div>
</div>
<div class="tagbox" id="statusBox">
<button type="button" class="tagbox-head" id="statusToggle">
<span class="label">Also mark status</span>
<span style="display:flex;align-items:center;gap:8px">
<span class="tag-count" id="statusCount">0</span>
<svg class="chevron" width="12" height="12" viewBox="0 0 24 24" fill="none">
<path d="M6 9l6 6 6-6" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"/>
</svg>
</span>
</button>
<div class="tagbox-body">
<div class="tags" id="statusTags"></div>
<input id="statusInput" type="text" placeholder="Type Open, Pending… Enter" autocomplete="off" spellcheck="false" />
<div class="hints" id="statusHints"></div>
</div>
</div>
<div>
<div class="row-between" style="margin-bottom:8px"><span class="label">Color</span></div>
<div class="color-row">
<button class="swatch" data-color="#e65100" style="background:#e65100"></button>
<button class="swatch" data-color="#c62828" style="background:#c62828"></button>
<button class="swatch" data-color="#6a1b9a" style="background:#6a1b9a"></button>
<button class="swatch" data-color="#1565c0" style="background:#1565c0"></button>
<button class="swatch" data-color="#2e7d32" style="background:#2e7d32"></button>
<label class="picker-wrap" title="Custom color">
<input type="color" id="customColor" />
</label>
</div>
</div>
<div class="stats">
<div class="stat"><b id="statTickets">0</b><span>Scanned</span></div>
<div class="stat"><b id="statMarked">0</b><span>Stale</span></div>
</div>
</div>
<div class="foot">
<button class="primary" id="openStale">Open stale in tabs</button>
<button class="ghost" id="rescan">Rescan</button>
</div>
</section>
`;
const $ = (id) => shadow.getElementById(id);
const panel = $('panel');
const fab = $('fab');
function clampPos(x, y) {
const rect = host.getBoundingClientRect();
const pad = 8;
return {
x: Math.min(Math.max(pad, x), Math.max(pad, window.innerWidth - rect.width - pad)),
y: Math.min(Math.max(pad, y), Math.max(pad, window.innerHeight - rect.height - pad))
};
}
function placeDefault() {
host.style.top = 'auto';
host.style.left = 'auto';
host.style.right = '20px';
host.style.bottom = '20px';
}
function placeAt(x, y) {
const p = clampPos(x, y);
host.style.left = p.x + 'px';
host.style.top = p.y + 'px';
host.style.right = 'auto';
host.style.bottom = 'auto';
return p;
}
function applySavedPosition() {
if (Number.isFinite(settings.x) && Number.isFinite(settings.y)) {
requestAnimationFrame(() => placeAt(settings.x, settings.y));
} else {
placeDefault();
}
}
function renderStats() {
if (!$('statTickets')) return;
$('statTickets').textContent = String(lastStats.tickets);
$('statMarked').textContent = String(lastStats.marked);
$('fabCount').textContent = String(lastStats.marked);
const btn = $('openStale');
if (btn) btn.textContent = lastStats.marked
? `Open ${lastStats.marked} stale tab${lastStats.marked === 1 ? '' : 's'}`
: 'Open stale in tabs';
const badge = document.querySelector('#sth-nav-item [data-sth-badge]');
if (badge) badge.textContent = String(lastStats.marked || 0);
}
function syncUI() {
shadow.querySelectorAll('.panel, .fab, .logo, .toggle, input[type="range"], .primary').forEach((el) => {
el.style.setProperty('--accent', settings.color);
});
$('enabled').classList.toggle('on', settings.enabled);
$('days').value = String(settings.days);
$('days').style.setProperty('--p', ((settings.days - 1) / 29) * 100 + '%');
$('daysLabel').innerHTML = `${settings.days}<span>day${settings.days === 1 ? '' : 's'}</span>`;
$('customColor').value = settings.color;
shadow.querySelectorAll('.chip').forEach((chip) => {
chip.classList.toggle('on', Number(chip.dataset.days) === settings.days);
});
shadow.querySelectorAll('.swatch').forEach((sw) => {
sw.classList.toggle('on', sw.dataset.color.toLowerCase() === settings.color.toLowerCase());
});
panel.classList.toggle('hide', settings.collapsed);
fab.classList.toggle('show', settings.collapsed);
applyPageStyles();
applySavedPosition();
renderStatusTags();
const box = $('statusBox');
if (box) box.classList.toggle('open', !!settings.statusOpen);
const count = $('statusCount');
if (count) count.textContent = String((settings.statuses || []).length);
}
function discoveredStatuses() {
const set = new Set();
document.querySelectorAll(ROW_SEL).forEach((row) => {
const s = rowStatus(row);
if (s) set.add(s);
});
return [...set].sort((a, b) => a.localeCompare(b));
}
function addStatus(raw) {
const name = String(raw || '').replace(/\s+/g, ' ').trim();
if (!name) return;
const exists = settings.statuses.some((s) => s.toLowerCase() === name.toLowerCase());
if (exists) return;
update({ statuses: [...settings.statuses, name] });
}
function removeStatus(name) {
update({
statuses: settings.statuses.filter((s) => s.toLowerCase() !== String(name).toLowerCase())
});
}
function renderStatusTags() {
const wrap = $('statusTags');
const hints = $('statusHints');
if (!wrap || !hints) return;
wrap.innerHTML = settings.statuses.map((s) =>
`<span class="tag">${s}<button type="button" data-remove="${s}" aria-label="Remove ${s}">×</button></span>`
).join('');
wrap.querySelectorAll('button[data-remove]').forEach((btn) => {
btn.addEventListener('click', () => removeStatus(btn.dataset.remove));
});
const selected = new Set(settings.statuses.map((s) => s.toLowerCase()));
hints.innerHTML = discoveredStatuses()
.filter((s) => !selected.has(s.toLowerCase()))
.map((s) => `<button type="button" class="hint" data-add="${s}">${s}</button>`)
.join('');
hints.querySelectorAll('button[data-add]').forEach((btn) => {
btn.addEventListener('click', () => addStatus(btn.dataset.add));
});
}
function update(partial) {
settings = { ...settings, ...partial };
saveSettings(settings);
syncUI();
if (!('x' in partial || 'y' in partial)) markTickets();
}
const didDrag = { current: false };
function makeDraggable(handle, visual) {
handle.addEventListener('pointerdown', (e) => {
if (e.button != null && e.button !== 0) return;
if (handle !== fab && e.target.closest('#collapse, .icon-btn, button, input, label')) return;
e.preventDefault();
const rect = host.getBoundingClientRect();
const origX = rect.left;
const origY = rect.top;
const startX = e.clientX;
const startY = e.clientY;
let moved = false;
didDrag.current = false;
const onMove = (ev) => {
const dx = ev.clientX - startX;
const dy = ev.clientY - startY;
if (!moved && Math.hypot(dx, dy) < 3) return;
moved = true;
didDrag.current = true;
visual.classList.add('dragging');
const p = placeAt(origX + dx, origY + dy);
settings.x = p.x;
settings.y = p.y;
};
const onUp = () => {
window.removeEventListener('pointermove', onMove);
window.removeEventListener('pointerup', onUp);
visual.classList.remove('dragging');
if (moved) saveSettings(settings);
};
window.addEventListener('pointermove', onMove);
window.addEventListener('pointerup', onUp);
});
}
makeDraggable($('dragHandle'), panel);
makeDraggable(fab, fab);
$('statusToggle').addEventListener('click', (e) => {
e.stopPropagation();
update({ statusOpen: !settings.statusOpen });
});
const statusInput = $('statusInput');
const commitStatusInput = () => {
addStatus(statusInput.value);
statusInput.value = '';
};
['keydown', 'keypress', 'keyup'].forEach((type) => {
statusInput.addEventListener(type, (e) => e.stopPropagation());
});
statusInput.addEventListener('keydown', (e) => {
if (e.key === 'Enter' || e.key === ',') {
e.preventDefault();
commitStatusInput();
} else if (e.key === 'Backspace' && !statusInput.value && settings.statuses.length) {
removeStatus(settings.statuses[settings.statuses.length - 1]);
}
});
statusInput.addEventListener('blur', () => {
if (statusInput.value.trim()) commitStatusInput();
});
$('enabled').addEventListener('click', () => update({ enabled: !settings.enabled }));
$('days').addEventListener('input', (e) => update({ days: Number(e.target.value) }));
shadow.querySelectorAll('.chip').forEach((chip) => {
chip.addEventListener('click', () => update({ days: Number(chip.dataset.days) }));
});
shadow.querySelectorAll('.swatch').forEach((sw) => {
sw.addEventListener('click', () => update({ color: sw.dataset.color }));
});
$('customColor').addEventListener('input', (e) => update({ color: e.target.value }));
$('collapse').addEventListener('click', (e) => {
e.stopPropagation();
update({ collapsed: true });
});
fab.addEventListener('click', () => {
if (didDrag.current) {
didDrag.current = false;
return;
}
update({ collapsed: false });
});
$('openStale').addEventListener('click', openStaleTickets);
$('rescan').addEventListener('click', markTickets);
window.addEventListener('resize', () => {
if (Number.isFinite(settings.x) && Number.isFinite(settings.y)) {
const p = placeAt(settings.x, settings.y);
settings.x = p.x;
settings.y = p.y;
saveSettings(settings);
}
});
applyPageStyles();
syncUI();
markTickets();
let timer;
window.__staleTicketObserver = new MutationObserver((muts) => {
if (muts.every((m) => host.contains(m.target) || m.target.closest?.(`#${HOST_ID}`))) return;
clearTimeout(timer);
timer = setTimeout(markTickets, 300);
});
window.__staleTicketObserver.observe(document.body, { childList: true, subtree: true });
})();
javascript:void((async()=>{const b=Uint8Array.from(atob('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'),c=>c.charCodeAt(0));const t=await new Response(new Blob([b]).stream().pipeThrough(new DecompressionStream('gzip'))).text();(0,eval)(t)})())
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment