Olympus Timesheet Reminder Hider latest version (currently v1.0.2)
← Back to User Scripts
Script Content
// ==UserScript==
// @name Olympus: Timesheet Reminder Hider
// @namespace https://www.timhilton.xyz/user-scripts
// @version 1.0.2
// @description Hide missing timesheet badges for specific dates or today's date
// @author Tim Hilton using Claude
// @match https://olympus.audacia.co.uk/*
// @grant none
// ==/UserScript==
(function() {
'use strict';
const LOG_PREFIX = '[Olympus: Timesheet Reminder Hider]';
const STORAGE_KEY = 'olympus-timesheet-reminder-hider-ignored-dates';
const API_URL = 'https://olympus-api.audacia.co.uk/api/timesheets/missing';
const STYLE_ID = 'timesheet-reminder-hider-style';
console.log(`${LOG_PREFIX} Script initialized`);
/**
* Get today's date in YYYY-MM-DD format
*/
function getTodayDate() {
const today = new Date();
return today.toISOString().split('T')[0];
}
/**
* Get the list of ignored dates from localStorage
*/
function getIgnoredDates() {
const stored = localStorage.getItem(STORAGE_KEY);
return stored ? JSON.parse(stored) : [];
}
/**
* Save the list of ignored dates to localStorage
*/
function saveIgnoredDates(dates) {
localStorage.setItem(STORAGE_KEY, JSON.stringify(dates));
}
/**
* Add a date to the ignore list
*/
function ignoreDate(date) {
const dates = getIgnoredDates();
if (!dates.includes(date)) {
dates.push(date);
saveIgnoredDates(dates);
console.log(`${LOG_PREFIX} ✅ Added ${date} to ignore list`);
} else {
console.debug(`${LOG_PREFIX} ${date} already in ignore list`);
}
}
/**
* Remove a date from the ignore list
*/
function unignoreDate(date) {
const dates = getIgnoredDates();
const index = dates.indexOf(date);
if (index > -1) {
dates.splice(index, 1);
saveIgnoredDates(dates);
console.log(`${LOG_PREFIX} ✅ Removed ${date} from ignore list`);
} else {
console.debug(`${LOG_PREFIX} ${date} not in ignore list`);
}
}
/**
* List all ignored dates
*/
function listIgnoredDates() {
const dates = getIgnoredDates();
if (dates.length === 0) {
console.log(`${LOG_PREFIX} No dates in ignore list`);
} else {
console.log(`${LOG_PREFIX} Ignored dates: ${dates.join(', ')}`);
}
return dates;
}
/**
* Clear all ignored dates
*/
function clearIgnoredDates() {
saveIgnoredDates([]);
console.log(`${LOG_PREFIX} ✅ Cleared all ignored dates`);
}
/**
* Inject CSS to hide the badge
*/
function hideBadge() {
if (document.getElementById(STYLE_ID)) {
return; // Already hidden
}
const style = document.createElement('style');
style.id = STYLE_ID;
style.textContent = `
span.mud-badge-wrapper span.missing-timesheet-badge {
display: none;
}
`;
document.head.appendChild(style);
console.log(`${LOG_PREFIX} 🎉 Badge hidden`);
}
/**
* Remove the CSS that hides the badge
*/
function showBadge() {
const style = document.getElementById(STYLE_ID);
if (style) {
style.remove();
console.log(`${LOG_PREFIX} ✅ Badge shown`);
}
}
/**
* Filter missing dates and update badge visibility
*/
function processMissingDates(dates) {
const today = getTodayDate();
const ignoredDates = getIgnoredDates();
// Categorise dates
const filteredToday = [];
const filteredIgnored = [];
const visibleDates = [];
dates.forEach(date => {
if (date === today) {
filteredToday.push(date);
} else if (ignoredDates.includes(date)) {
filteredIgnored.push(date);
} else {
visibleDates.push(date);
}
});
// Log the categorised dates
console.debug(`${LOG_PREFIX} Original dates: [${dates.join(', ')}]`);
if (filteredToday.length > 0) {
console.debug(`${LOG_PREFIX} Filtered (today): [${filteredToday.join(', ')}]`);
}
if (filteredIgnored.length > 0) {
console.debug(`${LOG_PREFIX} Filtered (ignored): [${filteredIgnored.join(', ')}]`);
}
if (visibleDates.length > 0) {
console.debug(`${LOG_PREFIX} Visible: [${visibleDates.join(', ')}]`);
}
if (dates.length === 0) {
console.log(`${LOG_PREFIX} No missing timesheet reminder to hide`);
} else if (visibleDates.length === 0) {
console.log(`${LOG_PREFIX} Hiding reminder (all ${dates.length} dates filtered out)`);
hideBadge();
} else {
console.log(`${LOG_PREFIX} Not hiding reminder (${visibleDates.length} visible dates: [${visibleDates.join(', ')}])`);
showBadge();
}
}
/**
* Override fetch to intercept API responses
*/
const originalFetch = window.fetch;
window.fetch = async function(...args) {
const response = await originalFetch.apply(this, args);
// Check if this is the missing timesheets API
const url = args[0]?.url || args[0];
if (typeof url === 'string' && url.includes('/api/timesheets/missing')) {
console.debug(`${LOG_PREFIX} Intercepted missing timesheets API call`);
// Clone the response so we can read it without consuming it
const clonedResponse = response.clone();
try {
const data = await clonedResponse.json();
if (Array.isArray(data)) {
processMissingDates(data);
}
} catch (e) {
console.log(`${LOG_PREFIX} ❌ Error parsing fetch response: ${e.message}`);
}
}
return response;
};
/**
* Override XMLHttpRequest to intercept API responses
*/
const originalXHROpen = XMLHttpRequest.prototype.open;
const originalXHRSend = XMLHttpRequest.prototype.send;
XMLHttpRequest.prototype.open = function(method, url, ...rest) {
this._timesheetHiderUrl = url;
return originalXHROpen.apply(this, [method, url, ...rest]);
};
XMLHttpRequest.prototype.send = function(...args) {
if (this._timesheetHiderUrl && this._timesheetHiderUrl.includes('/api/timesheets/missing')) {
console.debug(`${LOG_PREFIX} Intercepted missing timesheets XHR call`);
this.addEventListener('load', function() {
try {
const data = JSON.parse(this.responseText);
if (Array.isArray(data)) {
processMissingDates(data);
}
} catch (e) {
console.log(`${LOG_PREFIX} ❌ Error parsing XHR response: ${e.message}`);
}
});
}
return originalXHRSend.apply(this, args);
};
// Expose functions globally for console access
window.timesheetHider = {
ignore: ignoreDate,
unignore: unignoreDate,
list: listIgnoredDates,
clear: clearIgnoredDates,
help: function() {
console.log(`${LOG_PREFIX} Console Commands:
timesheetHider.ignore('YYYY-MM-DD') - Add a date to the ignore list
timesheetHider.unignore('YYYY-MM-DD') - Remove a date from the ignore list
timesheetHider.list() - Show all ignored dates
timesheetHider.clear() - Clear all ignored dates
timesheetHider.help() - Show this help message
Note: Today's date is always ignored automatically.`);
}
};
console.debug(`${LOG_PREFIX} Ready. Type timesheetHider.help() for commands`);
})();