Last active
February 2, 2023 10:14
-
-
Save rastamhadi/ca4aa2a3ad0b00fd41f7b5d36e0402b0 to your computer and use it in GitHub Desktop.
How much longer do I have to work this month?
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // ==UserScript== | |
| // @name How much longer do I have to work this month? | |
| // @namespace http://tampermonkey.net/ | |
| // @version 0.1 | |
| // @description Calculates the number of hours you need to work for the rest of the month | |
| // @author Rastam Hadi | |
| // @match https://p.secure.freee.co.jp/ | |
| // @icon https://www.google.com/s2/favicons?sz=64&domain=freee.co.jp | |
| // @grant none | |
| // ==/UserScript== | |
| (function() { | |
| 'use strict'; | |
| if (window.location.pathname != '/' || !window.location.hash.startsWith('#work_records')) return; | |
| const Summary = class { | |
| constructor() { | |
| this.container = document.querySelector('.employee-work-record-summary .main-items'); | |
| }; | |
| isNotLoaded() { | |
| return this.container == null; | |
| }; | |
| buildRemainderItem() { | |
| const workedTimeItem = this.getWorkedTimeItem(); | |
| const remainderItemContainer = workedTimeItem.clone(); | |
| const remainderItem = new SummaryItem(remainderItemContainer); | |
| const excessHours = workedTimeItem.getHours() - 8 * this.getWorkedDaysItem().getDays(); | |
| this.container.appendChild(remainderItemContainer); | |
| remainderItem.setLabel('過不足時間'); | |
| remainderItem.setHours(excessHours); | |
| }; | |
| getWorkedDaysItem() { | |
| return new SummaryItem(this.container.firstChild); | |
| }; | |
| getWorkedTimeItem() { | |
| return new SummaryItem(this.container.childNodes[1]); | |
| }; | |
| }; | |
| const SummaryItem = class { | |
| constructor(container) { | |
| this.container = container; | |
| this.body = container.querySelector('.body'); | |
| this.hoursContainer = this.body.querySelector('.hour-min__hour .hour-min__value'); | |
| }; | |
| clone() { | |
| return this.container.cloneNode(true); | |
| }; | |
| setLabel(text) { | |
| this.getLabel().textContent = text; | |
| }; | |
| setHours(hours) { | |
| this.hoursContainer.firstChild.nodeValue = hours; | |
| if (hours < 0) { | |
| this.body.style.color = 'red'; | |
| } else { | |
| this.body.style.color = 'green'; | |
| }; | |
| }; | |
| getLabel() { | |
| return this.container.querySelector('.label'); | |
| }; | |
| getDays() { | |
| return parseInt(this.body.firstChild.nodeValue); | |
| }; | |
| getHours() { | |
| return parseInt(this.hoursContainer.innerText); | |
| }; | |
| }; | |
| function observeBody() { | |
| const observer = new MutationObserver(mutations => { | |
| const summary = new Summary(); | |
| if (summary.isNotLoaded()) return; | |
| summary.buildRemainderItem(); | |
| observer.disconnect(); | |
| document.getElementsByTagName('button').forEach(button => { | |
| button.addEventListener('click', event => { | |
| observeBody(); | |
| }); | |
| }); | |
| }); | |
| observer.observe(document.body, {childList: true, subtree: true}) | |
| }; | |
| observeBody(); | |
| })(); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // ==UserScript== | |
| // @name How much longer do I have to work this month? | |
| // @namespace http://tampermonkey.net/ | |
| // @version 0.1 | |
| // @description Calculates the number of hours you need to work for the rest of the month | |
| // @author Rastam Hadi | |
| // @match https://ssl.jobcan.jp/employee/attendance* | |
| // @grant none | |
| // ==/UserScript== | |
| (function() { | |
| 'use strict'; | |
| const ONE_HOUR = 60; | |
| const EIGHT_HOURS = 8 * ONE_HOUR; | |
| const Duration = class { | |
| constructor(minutes) { | |
| this.minutes = minutes; | |
| }; | |
| static parse(string) { | |
| let hours, minutes; | |
| [hours, minutes] = string.split(':').map(i => parseInt(i)); | |
| return new Duration(minutes + hours * ONE_HOUR); | |
| } | |
| add(duration) { | |
| return new Duration(this.minutes + duration.minutes); | |
| }; | |
| overtime() { | |
| return new Duration(this.minutes - EIGHT_HOURS); | |
| }; | |
| toString() { | |
| const sign = this.minutes < 0 ? '-' : ''; | |
| const formattedHours = `0${this.getHoursSegment()}`.slice(-2); | |
| const formattedMinutes = `0${this.getMinutesSegment()}`.slice(-2); | |
| return `${sign}${formattedHours}:${formattedMinutes}`; | |
| }; | |
| getHoursSegment() { | |
| return Math.abs(Math.trunc(this.minutes / ONE_HOUR)); | |
| }; | |
| getMinutesSegment() { | |
| return Math.abs(this.minutes % ONE_HOUR); | |
| }; | |
| }; | |
| const headerRow = document.querySelector('.jbc-table-header'); | |
| const header = headerRow.lastChild.cloneNode(false); | |
| header.appendChild(document.createTextNode('労働時間')); | |
| header.appendChild(document.createElement('BR')); | |
| header.appendChild(document.createTextNode('過不足')); | |
| headerRow.appendChild(header); | |
| let overtimeTotal = new Duration(0); | |
| const rows = document.querySelector('.table-responsive tbody').children; | |
| for(let i = 0; i < rows.length; i++) { | |
| const row = rows.item(i); | |
| const hoursWorkedCell = row.children.item(4); | |
| const cell = row.lastChild.cloneNode(false); | |
| row.appendChild(cell); | |
| if(hoursWorkedCell.innerText != "") { | |
| const overtime = Duration.parse(hoursWorkedCell.innerText).overtime(); | |
| const cellText = document.createTextNode(overtime.toString()); | |
| cell.appendChild(cellText); | |
| overtimeTotal = overtimeTotal.add(overtime); | |
| } | |
| }; | |
| const footerRow = document.querySelector('.jbc-table-footer'); | |
| const footer = footerRow.lastChild.cloneNode(false); | |
| footer.appendChild(document.createTextNode(overtimeTotal.toString())); | |
| footer.setAttribute('style', `background-color: ${overtimeTotal.minutes < 0 ? '#FEEFED' : '#52CD9A'}`); | |
| footerRow.appendChild(footer); | |
| })(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment