Skip to content

Cleaned up legacy features from ECN integrations #2

Merged
merged 6 commits into from
Nov 18, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 0 additions & 57 deletions content/modules/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,64 +2,7 @@

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

12 changes: 0 additions & 12 deletions content/modules/highlighting.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,18 +19,6 @@ function handleHighlight(type, txt, element) {
var re
var style = null

if (typeof txt === "string") {
for (const [key, color] of Object.entries(colorsByStatus)) {
// Reset regex lastIndex to avoid state issues
color.re.lastIndex = 0
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
Expand Down
240 changes: 0 additions & 240 deletions content/modules/parsing.js
Original file line number Diff line number Diff line change
Expand Up @@ -247,121 +247,6 @@ function parseTicket(mutation = null) {
// Find ticket or task header element
let header = document.getElementById("thTicket_spnTitle") || document.querySelector("#upTaskHeader>div>h1")

// Find calendar inputs when editing tickets/tasks
// Currently handles start and end dates for tasks
let calendarInputs = document.querySelectorAll("#txtStartDate, #txtEndDate")
if (calendarInputs && calendarInputs.length > 0) {
[...calendarInputs].forEach(calendarInput => {
let calendarDateTime = parseDateTimeFlexible(calendarInput.value, {
formats: LEGACY_CALENDAR_PARSE_FORMATS
})

let newCalendarInput = document.createElement("input")
newCalendarInput.id = `${calendarInput.id}-new`
newCalendarInput.classList = calendarInput.classList
newCalendarInput.type = "datetime-local"

let calendarButtonContainer = document.createElement("div")
calendarButtonContainer.classList = ["calBox"]

let calendarText = document.createElement("span")
if (calendarDateTime && calendarDateTime.isValid) {
calendarText.textContent = calendarDateTime.toFormat("cccc")
}

function updateDate() {
if (!calendarDateTime || !calendarDateTime.isValid) {
return
}

const legacyFormatValue = calendarDateTime.toFormat(LEGACY_CALENDAR_OUTPUT_FORMAT)
calendarInput.value = legacyFormatValue

const isoFormatValue = calendarDateTime.toFormat(DATETIME_LOCAL_FORMAT)
newCalendarInput.value = isoFormatValue

if (calendarText) {
calendarText.textContent = formatCalendarLabel(calendarDateTime)
}
}

newCalendarInput.addEventListener("input", event => {
const parsedValue = parseDateTimeFlexible(event.target.value, {
formats: [DATETIME_LOCAL_FORMAT],
allowLoose: false
})

if (parsedValue && parsedValue.isValid) {
calendarDateTime = parsedValue
updateDate()
}
})

function modifyDate(buttonConfig) {
if (!calendarDateTime || !calendarDateTime.isValid) {
return
}

let updatedDate = calendarDateTime

if (Object.prototype.hasOwnProperty.call(buttonConfig, "add")) {
updatedDate = updatedDate.plus(buttonConfig.add)
} else if (Object.prototype.hasOwnProperty.call(buttonConfig, "set")) {
updatedDate = applyMomentLikeSet(updatedDate, buttonConfig.set)
}

const dayOfWeek = updatedDate.weekday
const hour = updatedDate.hour
const minute = updatedDate.minute

if (dayOfWeek >= 5 && (hour > 17 || (hour === 17 && minute > 0))) {
updatedDate = applyMomentLikeSet(updatedDate, {
h: 8,
d: updatedDate.day + 7,
m: 0
})
} else if (dayOfWeek > 5) {
updatedDate = applyMomentLikeSet(updatedDate, {
d: updatedDate.day + 7
})
}

calendarDateTime = updatedDate
updateDate()
}

// Define quick date modifier buttons
let dateModifierButtons = [
{ 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 } }
]

// Create and attach date modifier buttons
for (const buttonConfig of dateModifierButtons) {
let buttonElement = document.createElement("button")
buttonElement.classList = "btn btn-calendar"
buttonElement.innerText = buttonConfig.name
buttonElement.addEventListener("click", (event) => {
event.preventDefault()
modifyDate(buttonConfig)
})
calendarButtonContainer.appendChild(buttonElement)
}

updateDate()

// Hide old calendar input (still needed for format conversion)
// Append new elements to the parent
calendarInput.style.display = "none"
calendarInput.parentElement.append(newCalendarInput)
calendarInput.parentElement.append(calendarText)
calendarInput.parentElement.append(calendarButtonContainer)
});
}

// Update browser tab title with ticket title
if (header) {
let ticketTitle = header.childNodes[0].textContent
Expand All @@ -370,55 +255,12 @@ function parseTicket(mutation = null) {
return
}

// Add queue tag to ticket title with color coding
// Only add if queue block exists, header exists, and queue box doesn't already exist
if (queueBlock && header && !document.querySelector(".qBox")) {
let queueElement = queueBlock.querySelector("span.wrap-text")
if (!queueElement) {
return
}

let queueText = (queueElement.innerText || queueElement.textContent || "").trim()

if (!queueText) {
return
}

// Create queue tag element
let queueTagBox = document.createElement("span")
queueTagBox.textContent = queueText
queueTagBox.classList.add("qBox")

// Apply color coding based on queue name
let queueTextLower = queueText.toLowerCase()
for (const queueKey of Object.keys(colorsByQueue)) {
let queueColorConfig = colorsByQueue[queueKey]
if (queueTextLower === queueKey) {
queueTagBox.style.color = queueColorConfig.txt
queueTagBox.style.backgroundColor = queueColorConfig.bg
break
}
}

header.appendChild(queueTagBox)
}

// Handle button links - configure to open in new tabs
// Update ticket buttons
[...document.querySelectorAll("#btnUpdateTicket, #divUpdateFromActions")].forEach(button => {
handleLink("Update", button)
});

// Add task button
[...document.querySelectorAll("#liAddTicketTask>a")].forEach(button => {
handleLink("TicketTaskNew", button)
});

// Add task template button
[...document.querySelectorAll("#divAddTaskTemplate>a")].forEach(button => {
handleLink("TicketAddTaskTemplate", button)
});

// Adjust feed colors for dark mode compatibility
// Find feed items either from mutation or document
var feedItems
Expand Down Expand Up @@ -483,50 +325,6 @@ function parseOtherElements() {
})
}
})

// Apply custom desktop layout configuration
let desktopLayout = settings('get', 'layout')
let desktopContainer = document.querySelector("#divContent")
if (desktopContainer && desktopLayout) {
let column1 = desktopContainer.querySelector("#Column1")
let column2 = desktopContainer.querySelector("#Column2")
let column3 = desktopContainer.querySelector("#Column3")

// Apply 100% / 66-33% layout (column 2 takes 66%, column 3 takes 33%)
if (desktopLayout === "1_100-66-33" && column2 && column3) {
// Define width classes for Bootstrap grid
let column2WidthClass = "col-md-8" // 66% width
let column3WidthClass = "col-md-4" // 33% width

// Resize column 2: remove existing col-md class and add new one
for (const className of column2.classList) {
if (className.startsWith("col-md")) {
column2.classList.remove(className)
column2.classList.add(column2WidthClass)
break
}
}

// Resize column 3: remove existing col-md class and add new one
for (const className of column3.classList) {
if (className.startsWith("col-md")) {
column3.classList.remove(className)
column3.classList.add(column3WidthClass)
break
}
}
}
}

// Apply sticky column positioning if enabled
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"
});
}
}

/**
Expand Down Expand Up @@ -586,15 +384,6 @@ function parseTable(element) {
* @param {Object} item - Item object containing row data with header names as keys
*/
function parseItem(item) {
// Color queue names in "CSS Support" column
if ('CSS Support' in item && item["CSS Support"]) {
let queueCell = item["CSS Support"].cell
let queueText = (item["CSS Support"].txt || "").toLowerCase().trim()
if (queueText && queueCell && queueText in colorsByQueue) {
let queueColorConfig = colorsByQueue[queueText]
createHighlightBubble(queueCell, queueColorConfig.bg, queueColorConfig.txt)
}
}

// Convert dates to relative time format (e.g., "3 hours ago", "in 2 days")
let relativeDateColumns = ['Modified', 'Created']
Expand Down Expand Up @@ -625,22 +414,6 @@ function parseItem(item) {
}
}

let detailedDateColumns = ['Date Due', 'Due', 'Created', 'Start']
for (const dateColumnName of detailedDateColumns) {
if (dateColumnName in item) {
let dateText = item[dateColumnName].txt
let dateCell = item[dateColumnName].cell

let parsedDate = parseDateTimeFlexible(dateText)
if (parsedDate && parsedDate.isValid) {
let calendarFormatText = formatCalendarLabel(parsedDate)
if (calendarFormatText) {
dateCell.textContent = calendarFormatText
}
}
}
}

let modifiedDateColumns = ['Modified']
for (const dateColumnName of modifiedDateColumns) {
if (dateColumnName in item) {
Expand Down Expand Up @@ -697,19 +470,6 @@ function parseItem(item) {
}
}

// Highlight internal users (primary responsibility or responsibility column)
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)
}

// Apply inline highlighting for task titles
if ('Title' in item) {
let titleData = item.Title
handleHighlight("title", titleData.txt, titleData.cell)
}

// Configure links to open in new tabs (if configured)
let linkColumnTypes = ['Title', 'TicketID', 'TicketTitle']
for (const linkColumnType of linkColumnTypes) {
Expand Down
5 changes: 0 additions & 5 deletions content/modules/settings.js
Original file line number Diff line number Diff line change
Expand Up @@ -100,8 +100,3 @@ function settings(action, value = null) {
}
}

function parseCustomHighlights(data) {
// Legacy function - kept for compatibility
// Custom highlights are now handled directly in highlighting.js
}

9 changes: 7 additions & 2 deletions manifest.json
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
{
"manifest_version": 3,
"name": "TDX-Enhanced",
"manifest_version": 3,
"name": "tdx-enhanced-firefox",
"version": "0.1.0",
"description": "TDX-Enhanced userscript converted to Chrome extension. Includes RCAC Halcyon API integration for TDNext ticket detail pages.",
"author": "Purdue STEM IT, it@purdue.edu - Modified by Purdue RCAC, rcac@purdue.edu",
"browser_specific_settings": {
"gecko": {
"id": "remender@purdue.edu"
}
},
"permissions": [
"storage"
],
Expand Down