105 lines
4.1 KiB
JavaScript
105 lines
4.1 KiB
JavaScript
javascript:(async function() {
|
|
console.log(">>> LINK HARVESTER STARTED");
|
|
const wait = (ms) => new Promise(resolve => setTimeout(resolve, ms));
|
|
const capturedLinks = [];
|
|
const dateCounts = {};
|
|
|
|
let capturedUrl = null;
|
|
const originalWindowOpen = window.open;
|
|
|
|
function enableInterceptor() {
|
|
capturedUrl = null;
|
|
window.open = function(url) {
|
|
if (url) {
|
|
capturedUrl = url;
|
|
return { focus:()=>{}, close:()=>{} };
|
|
}
|
|
const spyWindow = {
|
|
focus: () => {}, close: () => {},
|
|
document: { write: () => {}, close: () => {} }
|
|
};
|
|
Object.defineProperty(spyWindow, 'location', {
|
|
set: function(val) { capturedUrl = val; },
|
|
get: function() { return { set href(val) { capturedUrl = val; }, assign: (val) => { capturedUrl = val; }, replace: (val) => { capturedUrl = val; } }; }
|
|
});
|
|
return spyWindow;
|
|
};
|
|
}
|
|
function disableInterceptor() { window.open = originalWindowOpen; }
|
|
|
|
const rows = Array.from(document.querySelectorAll("mat-row"));
|
|
if (rows.length === 0) {
|
|
alert("No rows found. Please go to the Billing/Documents list.");
|
|
return;
|
|
}
|
|
|
|
for (const row of rows) {
|
|
const dateCell = row.querySelector(".mat-column-date");
|
|
if (!dateCell) continue;
|
|
|
|
const rawDate = dateCell.innerText.trim();
|
|
const d = new Date(rawDate);
|
|
if (isNaN(d.getTime())) continue;
|
|
|
|
const yyyy = d.getFullYear();
|
|
const mm = String(d.getMonth() + 1).padStart(2, '0');
|
|
const dd = String(d.getDate()).padStart(2, '0');
|
|
const baseDate = yyyy + "-" + mm + "-" + dd;
|
|
|
|
if (!dateCounts[baseDate]) dateCounts[baseDate] = 0;
|
|
dateCounts[baseDate]++;
|
|
const suffix = dateCounts[baseDate] > 1 ? " (" + dateCounts[baseDate] + ")" : "";
|
|
|
|
const filename = "Roundpoint - Myrtlewood - " + baseDate + suffix + ".pdf";
|
|
|
|
const downloadCell = row.querySelector(".mat-column-download");
|
|
const clickTarget = downloadCell ? (downloadCell.querySelector("i") || downloadCell) : null;
|
|
|
|
if (!clickTarget) continue;
|
|
|
|
enableInterceptor();
|
|
clickTarget.click();
|
|
|
|
let attempts = 0;
|
|
while (capturedUrl === null && attempts < 30) {
|
|
await wait(100);
|
|
attempts++;
|
|
}
|
|
disableInterceptor();
|
|
|
|
if (capturedUrl) {
|
|
const urlWithHash = capturedUrl + "#" + filename;
|
|
capturedLinks.push({ filename: filename, url: urlWithHash });
|
|
}
|
|
await wait(200);
|
|
}
|
|
|
|
const container = document.querySelector('mat-drawer-content > div') || document.querySelector('.data-table-shell') || document.querySelector('mat-drawer-content');
|
|
|
|
if (!container) {
|
|
alert("Could not find the table container to replace. Check console for links.");
|
|
console.log(capturedLinks);
|
|
return;
|
|
}
|
|
|
|
container.innerHTML = `
|
|
<div style="padding: 20px; font-family: sans-serif; background: #fff; color: #000; height: 100%; overflow: auto;">
|
|
<h2 style="color: #333; margin-top: 0;">Harvest Complete (${capturedLinks.length} files)</h2>
|
|
<p style="background: #e3f2fd; padding: 10px; border-radius: 4px; border-left: 5px solid #2196F3; font-size: 14px;">
|
|
<strong>INSTRUCTIONS:</strong><br>
|
|
Right-click -> <strong>DownThemAll!</strong><br>
|
|
(Use default settings or <code>*text*</code> mask)
|
|
</p>
|
|
<table style="width: 100%; border-collapse: collapse; margin-top: 10px;">
|
|
${capturedLinks.map(item => `
|
|
<tr style="border-bottom: 1px solid #ddd;">
|
|
<td style="padding: 8px;">
|
|
<a href="${item.url}" download="${item.filename}" style="font-size: 14px; color: #0066cc; text-decoration: none; font-family: monospace;">${item.filename}</a>
|
|
</td>
|
|
</tr>
|
|
`).join('')}
|
|
</table>
|
|
</div>
|
|
`;
|
|
})();
|