您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Adding Ability to see reviewed transactions on the reconciliation page
// ==UserScript== // @name Wave Reconciliation-Reviewed // @description Adding Ability to see reviewed transactions on the reconciliation page // @author Seth Parrish // @namespace https://sethp.cc // @version 0.5 // @icon https://raw.githubusercontent.com/xthexder/wide-github/master/icon.png // @homepageURL https://greasyfork.org/en/scripts/394287-wave-reconciliation-reviewed // @supportURL https://greasyfork.org/en/scripts/394287-wave-reconciliation-reviewed // @match https://next.waveapps.com/* // @grant GM_registerMenuCommand // @grant GM_getValue // @grant GM_setValue // @grant GM_deleteValue // @grant GM_addStyle // @license GPL-3.0-only // ==/UserScript== "use strict"; // Global Vars & Storage Object // var d = document // var b = d.body var DBNAME = "reviewed_db"; var db = GM_getValue(DBNAME) || []; console.log("DB:", db); // Add GM DB deletion option GM_registerMenuCommand("Clear Stored Data", () => { var shouldClear = confirm( 'Do you want to clear the "seen" reviewed transactions? (this will not effect data in wave)' ); if (shouldClear) { db = []; GM_setValue(DBNAME, db); GM_deleteValue(DBNAME); console.log("DB:", db); } }); // Add 'unmatch all' button GM_registerMenuCommand("Unmatch All Transactions on screen", () => { var shouldGo = confirm( "Do you want to unmatch all the transactions currently on the page?" ); if (shouldGo) { var className = "account-recv2__reconciliation__table__matched-icon--true"; var icons = Array.from(document.getElementsByClassName(className)); icons.forEach(function (x) { x.click(); }); console.log("Finished Unmatching Transactions"); } }); // Find transaction from reconciliaton var lastPicked = ""; function findTransaction() { if (lastPicked != "") { var url = window.location.href.split("account-")[0]; window.open(url + "transactions/" + lastPicked); } else { alert("You haven't picked a transaction yet"); } console.log("Looking for transaction"); } GM_registerMenuCommand("Find Transaction", () => { findTransaction(); }); // Adding Custom CSS GM_addStyle( ".account-recv2__reconciliation__table__reviewed--true {background: #dec9ff !important;color: #849194 !important;}" ); // Check for Reviewed Status and add to the DB function processLatestTransactions(res) { var isReviewed = (x) => Boolean(x.transaction_status.value); var isInDB = (x) => db.some((e) => e.transaction_guid === x.transaction_guid); res.latest_transactions.forEach((x) => { if (isReviewed(x) && !isInDB(x)) { db.push(x); } }); GM_setValue(DBNAME, db); console.log("DB: ", db); } // Handle changing the status of a single transaction function processTransactionStatusChange(res) { // Do not run if we are marking as reviewed (other case handles) if (res.transaction_status.value) { return; } for (var i = 0; i < db.length; i++) { if (db[i].transaction_guid === res.guid) { db.splice(i, 1); } } GM_setValue("reviewed_db", db); console.log("DB: ", db); } // Utility function to apply custom css to a row with matching data function turnGreen(date, desc, price_formatted) { var datedRows = Array.apply( null, document.querySelectorAll(`time[datetime="${date}"]`) ).map(function (x) { return x.parentNode.parentElement.parentElement.parentElement.parentElement; }); if (datedRows.length === 0) { return; } var el = datedRows.find(function (x) { var txt = x.textContent; // Eg. "Nov 29, 2019Steam Games$13.90$1,568.22" return ( txt.includes(date.split("-")[0]) && txt.includes(desc) && txt.includes(price_formatted) ); }); el.className += " account-recv2__reconciliation__table__reviewed--true "; } // Iterate DB and apply styles function processReconciliationPage(res) { // Deal with this page's transaction data // var matched = res.transactions.filter(x => Boolean(x.is_matched)) db.forEach(function (x) { turnGreen( x.transaction_date, x.transaction_description, x.transaction_total.transaction.formatted_string ); }); } // HTTP Listener (function (open) { XMLHttpRequest.prototype.open = function () { this.addEventListener( "readystatechange", function () { var json = this.responseText ? JSON.parse(this.responseText) : {}; var doneAndIncludes = (x) => this.readyState === 4 && this.responseURL.includes(x); if (doneAndIncludes("/transactions/latest/")) { // Check for a finished request dealing with latest transactions processLatestTransactions(json); } else if (doneAndIncludes("/transactions/status/")) { // Check for a finished request, marking a transaction as "un-reviewed" processTransactionStatusChange(json); } else if ( doneAndIncludes("/account_reconciliation/reconciliation_by_period/") ) { // Check for a finished request dealing with reconciliation transactions processReconciliationPage(json); } else if ( doneAndIncludes("transactions/") && this.responseURL.split("/").length == 8 ) { // Grab last (selected) transaction and save to variable lastPicked = this.responseURL.split("/")[6]; console.log("Last Picked Updated: ", lastPicked); } }, false ); open.apply(this, arguments); }; })(XMLHttpRequest.prototype.open); // Keyboard Listener function keyPress(e) { // this would test for whichever key is alt and the ctrl key at the same time if (e.ctrlKey && e.keyCode == 18) { findTransaction(); } } // register the handler document.addEventListener("keydown", keyPress); // The End :)