-
Notifications
You must be signed in to change notification settings - Fork 0
/
com.dynatrace.timetracking.bookmarklet.js.map
1 lines (1 loc) · 37.2 KB
/
com.dynatrace.timetracking.bookmarklet.js.map
1
{"version":3,"sources":["webpack:///webpack/bootstrap","webpack:///./bookmarklet/bookmarklet.ts"],"names":["installedModules","__webpack_require__","moduleId","exports","module","i","l","modules","call","m","c","d","name","getter","o","Object","defineProperty","enumerable","get","r","Symbol","toStringTag","value","t","mode","__esModule","ns","create","key","bind","n","object","property","prototype","hasOwnProperty","p","s","idCss","idHtml","idInput","idSelectType","idButtonBook","idButtonClear","idButtonClose","idLoader","cacheTaskIdAndProjectId","Map","cacheUserDetailUuid","isInvalidDigit","stringTime","isNaN","charAt","isInvalidHour","integerHour","isInvalidMinute","integerMinute","computeTimecockpitEntryProperties","line","length","stringDate","substr","stringTimeBegin","stringTimeEnd","indexOfPipe","indexOf","stringJiraKey","substring","stringComment","integerYearCurrent","Date","getFullYear","integerYear","parseInt","integerMonth","integerDay","year","month","day","date","setFullYear","getMonth","getDate","isValidDate","integerHourBegin","integerHourEnd","integerMinuteBegin","integerMinuteEnd","jiraKey","APP_BeginTime","APP_EndTime","APP_Description","setEnabled","input","enable","forEach","id","document","getElementById","disabled","contentEditable","focus","style","visibility","clear","querySelectorAll","element","parentNode","removeChild","bookEntry","span","string","innerText","trim","selectType","timesheetTypeUuid","options","selectedIndex","linePrevious","innerHTML","lineArray","split","setTimeout","synchronizedLineProcessor","statusOfPreviousLine","scrollTop","scrollHeight","shift","normalizedLine","callback","properties","undefined","USR_TimesheetTypeUuid","nextStep","APP_UserDetailUuid","filter","response","xhrGet","json","JSON","parse","console","log","cache","APP_TaskUuid","APP_ProjectUuid","stringify","url","xhr","xhrPost","error","status","createEntity","has","set","queryTaskIdAndProjectIdForJiraKey","checkIfEntityWithEqualBeginOrEndTimeAlreadyExists","useruuid","queryUserId","checkLineAndParseProperties","refreshButton","Array","find","button","title","includes","click","createContent","Promise","resolve","link","createElement","rel","type","href","now","media","onload","head","appendChild","loadCss","dummy","body","querySelector","addEventListener","e","preventDefault","execCommand","clipboardData","getData","onclick","onkeydown","event","code","_","window","method","request","XMLHttpRequest","reject","onreadystatechange","readyState","responseText","statusText","open","setRequestHeader","send","location","origin"],"mappings":"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","file":"com.dynatrace.timetracking.bookmarklet.js","sourcesContent":[" \t// The module cache\n \tvar installedModules = {};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId]) {\n \t\t\treturn installedModules[moduleId].exports;\n \t\t}\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, { enumerable: true, get: getter });\n \t\t}\n \t};\n\n \t// define __esModule on exports\n \t__webpack_require__.r = function(exports) {\n \t\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n \t\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n \t\t}\n \t\tObject.defineProperty(exports, '__esModule', { value: true });\n \t};\n\n \t// create a fake namespace object\n \t// mode & 1: value is a module id, require it\n \t// mode & 2: merge all properties of value into the ns\n \t// mode & 4: return value when already ns object\n \t// mode & 8|1: behave like require\n \t__webpack_require__.t = function(value, mode) {\n \t\tif(mode & 1) value = __webpack_require__(value);\n \t\tif(mode & 8) return value;\n \t\tif((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;\n \t\tvar ns = Object.create(null);\n \t\t__webpack_require__.r(ns);\n \t\tObject.defineProperty(ns, 'default', { enumerable: true, value: value });\n \t\tif(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));\n \t\treturn ns;\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"\";\n\n\n \t// Load entry module and return exports\n \treturn __webpack_require__(__webpack_require__.s = 0);\n","import './bookmarklet.css';\n\ninterface TimecockpitEntryProperties {\n jiraKey: string;\n\n APP_BeginTime: string;\n APP_EndTime: string;\n APP_Description: string;\n APP_TaskUuid?: string;\n APP_ProjectUuid?: string;\n APP_UserDetailUuid?: string;\n USR_TimesheetTypeUuid?: string;\n\n APP_IsDurationTimesheet?: boolean;\n APP_NoBilling?: boolean;\n USR_MedicalConfirmationReceived?: boolean;\n}\n\nconst timecockpitUrl = 'https://dynatrace.timecockpit.com';\n\n// https://stackoverflow.com/questions/6028211/what-is-the-standard-naming-convention-for-html-css-ids-and-classes/37797488#37797488\nconst idCss = 'com_kamilsarelo_dynatrace_timetracking_css';\nconst idHtml = 'com_kamilsarelo_dynatrace_timetracking_html';\nconst idContent = 'com_kamilsarelo_dynatrace_timetracking_content';\nconst idHeader = 'com_kamilsarelo_dynatrace_timetracking_header';\nconst idMain = 'com_kamilsarelo_dynatrace_timetracking_main';\nconst idInput = 'com_kamilsarelo_dynatrace_timetracking_input';\nconst idFooter = 'com_kamilsarelo_dynatrace_timetracking_footer';\nconst idFooterLeft = 'com_kamilsarelo_dynatrace_timetracking_footer_left';\nconst idFooterRight = 'com_kamilsarelo_dynatrace_timetracking_footer_right';\nconst idSelectType = 'com_kamilsarelo_dynatrace_timetracking_select_type';\nconst idButtonBook = 'com_kamilsarelo_dynatrace_timetracking_action_book';\nconst idButtonClear = 'com_kamilsarelo_dynatrace_timetracking_action_clear';\nconst idButtonClose = 'com_kamilsarelo_dynatrace_timetracking_action_close';\nconst idLoader = 'com_kamilsarelo_dynatrace_timetracking_loader';\n\n// caches\nconst cacheTaskIdAndProjectId = new Map();\nconst statusOfPreviousLineDone = 'done';\n\nlet cacheUserDetailUuid;\n\n// time sanity checks\nfunction isInvalidDigit(stringTime: string): boolean {\n return (\n isNaN(+stringTime.charAt(0)) ||\n isNaN(+stringTime.charAt(1)) ||\n isNaN(+stringTime.charAt(3)) ||\n isNaN(+stringTime.charAt(4))\n );\n}\n\nfunction isInvalidHour(integerHour: number): boolean {\n return isNaN(integerHour) || integerHour < 0 || integerHour > 23;\n}\n\nfunction isInvalidMinute(integerMinute: number): boolean {\n return isNaN(integerMinute) || integerMinute < 0 || integerMinute > 59;\n}\n\n// https://ctrlq.org/code/20109-javascript-date-valid\nfunction isValidDate(year: number, month: number, day: number): boolean {\n const date = new Date();\n\n date.setFullYear(year, month - 1, day);\n\n return (\n date.getFullYear() === year &&\n date.getMonth() === month - 1 &&\n date.getDate() === day\n );\n}\n\nfunction computeTimecockpitEntryProperties(\n line: string,\n): TimecockpitEntryProperties | undefined {\n // basic sanity checks:\n // 2019-03-11|12:00|16:00|...|...\n // 0123456789 123456789 123456789\n if (\n line.length <= 23 || // first 23 characters are fixed width: date, time, time\n isNaN(+line.charAt(0)) || // first character must be a number: https://stackoverflow.com/questions/8935632/check-if-character-is-number\n '|' !== line.charAt(10) ||\n '|' !== line.charAt(16) ||\n '|' !== line.charAt(22)\n ) {\n return;\n }\n\n // date and times\n const stringDate = line.substr(0, 10); // https://www.w3schools.com/jsref/jsref_obj_string.asp\n const stringTimeBegin = line.substr(11, 5);\n const stringTimeEnd = line.substr(17, 5);\n // Jira key\n const indexOfPipe = line.indexOf('|', 23);\n if (indexOfPipe === -1) {\n // no delimiter after Jira key\n return;\n }\n const stringJiraKey = line.substring(23, indexOfPipe); // https://stackoverflow.com/questions/2243824/what-is-the-difference-between-string-slice-and-string-substring\n if (stringJiraKey === '') {\n return;\n }\n // comment\n const stringComment = line.substr(indexOfPipe + 1);\n if (stringComment === '') {\n // empty comment\n return;\n }\n\n // ---\n\n // date sanity checks\n // valid delimiters\n if ('-' !== stringDate.charAt(4) || '-' !== stringDate.charAt(7)) {\n return;\n }\n // valid digits: https://stackoverflow.com/questions/175739/built-in-way-in-javascript-to-check-if-a-string-is-a-valid-number\n if (\n isNaN(+stringDate.charAt(0)) ||\n isNaN(+stringDate.charAt(1)) ||\n isNaN(+stringDate.charAt(2)) ||\n isNaN(+stringDate.charAt(3)) ||\n isNaN(+stringDate.charAt(5)) ||\n isNaN(+stringDate.charAt(6)) ||\n isNaN(+stringDate.charAt(8)) ||\n isNaN(+stringDate.charAt(9))\n ) {\n return;\n }\n // valid year\n const integerYearCurrent = new Date().getFullYear();\n const integerYear = parseInt(stringDate.substr(0, 4), 10);\n // if (isNaN(integerYear) || integerYear < 2019 || integerYear > 2046) {\n if (\n isNaN(integerYear) ||\n integerYear < integerYearCurrent ||\n integerYear > integerYearCurrent\n ) {\n return;\n }\n // valid month\n const integerMonth = parseInt(stringDate.substr(5, 2), 10);\n if (isNaN(integerYear) || integerMonth < 1 || integerMonth > 12) {\n return;\n }\n // valid day\n const integerDay = parseInt(stringDate.substr(8, 2), 10);\n if (isNaN(integerYear) || integerDay < 1 || integerDay > 31) {\n return;\n }\n\n if (!isValidDate(integerYear, integerMonth, integerDay)) {\n return;\n }\n\n // ---\n\n // valid delimiters\n if (':' !== stringTimeBegin.charAt(2) || ':' !== stringTimeEnd.charAt(2)) {\n return;\n }\n // valid digits\n if (isInvalidDigit(stringTimeBegin) || isInvalidDigit(stringTimeEnd)) {\n return;\n }\n // valid hours\n const integerHourBegin = parseInt(stringTimeBegin.substr(0, 2), 10);\n const integerHourEnd = parseInt(stringTimeEnd.substr(0, 2), 10);\n if (isInvalidHour(integerHourBegin) || isInvalidHour(integerHourEnd)) {\n return;\n }\n // valid minutes\n const integerMinuteBegin = parseInt(stringTimeBegin.substr(3, 2), 10);\n const integerMinuteEnd = parseInt(stringTimeEnd.substr(3, 2), 10);\n if (\n isInvalidMinute(integerMinuteBegin) ||\n isInvalidMinute(integerMinuteEnd)\n ) {\n return;\n }\n // begin actually before end\n if (\n integerHourBegin > integerHourEnd ||\n (integerHourBegin === integerHourEnd &&\n integerMinuteBegin >= integerMinuteEnd)\n ) {\n return;\n }\n\n // ---\n\n // const APP_Description = encodeURIComponent(stringComment); // encoding not necessary, https://stackoverflow.com/questions/332872/encode-url-in-javascript/6171234#6171234\n\n return {\n jiraKey: stringJiraKey,\n APP_BeginTime: stringDate + 'T' + stringTimeBegin + ':00',\n APP_EndTime: stringDate + 'T' + stringTimeEnd + ':00',\n APP_Description: stringComment,\n };\n}\n\nfunction setEnabled(input: HTMLDivElement, enable: boolean): void {\n [idButtonBook, idButtonClear, idButtonClose].forEach((id) => {\n const button = document.getElementById(id) as HTMLButtonElement;\n button.disabled = !enable;\n });\n\n input.contentEditable = 'true'; // TODO ChMa: shouldn't this be set according to param 'enable'?\n input.focus();\n\n document.getElementById(idLoader)!.style.visibility = enable\n ? 'hidden'\n : 'visible';\n}\n\n// clear previous instances\nfunction clear(): void {\n // or: const clear = function() {\n [idHtml, idCss].forEach((id) => {\n document.querySelectorAll('#' + id).forEach((element) => {\n element.parentNode!.removeChild(element); //https://stackoverflow.com/questions/8830839/javascript-dom-remove-element/8830882\n });\n });\n}\n\n// https://stackoverflow.com/questions/574944/how-to-load-up-css-files-using-javascript/51183077#51183077\nasync function loadCss(): Promise<void> {\n return new Promise((resolve) => {\n // CSS\n const link = document.createElement('link');\n\n link.id = idCss;\n link.rel = 'stylesheet';\n link.type = 'text/css';\n // link.href = 'https://localhost/bookmarklet.css';\n // link.href = 'https://cdn.jsdelivr.net/gh/kamilsarelo/timetracking/bookmarklet/bookmarklet.css';\n link.href = `https://christian-fischer.github.io/com.dynatrace.timetracking.bookmarklet.css?q=${Date.now()}`;\n link.media = 'all';\n // https://developer.mozilla.org/en-US/docs/Web/API/GlobalEventHandlers/onload and https://stackoverflow.com/questions/6348494/addeventlistener-vs-onclick/6348533#6348533\n link.onload = () => {\n resolve();\n };\n document.head.appendChild(link); // https://developer.mozilla.org/de/docs/Web/API/Document/head\n });\n}\n\nasync function bookEntry(): Promise<void> {\n const input = document.getElementById(idInput) as HTMLDivElement;\n\n // remove all html except line breaks\n input.querySelectorAll('span').forEach((span) => {\n // also: ... .forEach(span => { ...\n input.removeChild(span);\n });\n\n const string = input.innerText; // or https://developer.mozilla.org/de/docs/Web/API/Node/textContent but textContent ignores line breaks\n if (string.trim().length === 0) {\n return;\n }\n\n setEnabled(input, false);\n\n const selectType = document.getElementById(idSelectType) as HTMLSelectElement;\n const timesheetTypeUuid = selectType.options[selectType.selectedIndex].value;\n\n input.innerHTML = '';\n let linePrevious;\n\n const lineArray = string.split(/\\r\\n|\\r|\\n/g); // also string.split(/\\r?\\n/g); but mind: https://stackoverflow.com/questions/21711768/split-string-in-javascript-and-detect-line-break/21712066#21712066\n // lineArray.forEach((line) => { ...\n // the whole booking process has to be done sequential via synchronous xhr (xhr is parallel/async by default),\n // so caches can work, AND most importantly no duplicate entities are created\n // but synchronous xhr should be used in workers exclusively: https://xhr.spec.whatwg.org/#synchronous-flag\n // ...thus forEach cannot be used\n //\n // \"Synchronous XMLHttpRequest outside of workers is in the process of being removed from the web platform\n // as it has detrimental effects to the end user’s experience. (This is a long process that takes many years.)\n // Developers must not pass false for the async argument when current global object is a Window object.\n // User agents are strongly encouraged to warn about such usage in developer tools\n // and may experiment with throwing an \"InvalidAccessError\" DOMException when it occurs.\"\n //\n // ...thus let's simulate synchronours xhr with a mutex callback... https://www.mkyong.com/java/java-thread-mutex-and-semaphore-example/\n async function synchronizedLineProcessor(\n statusOfPreviousLine?: string,\n ): Promise<void> {\n if (linePrevious) {\n input.innerHTML =\n (input.innerHTML ? input.innerHTML + '<br/>' : '') +\n (statusOfPreviousLine\n ? `<span class=\"pill\" style=\"background-color:${\n statusOfPreviousLine === statusOfPreviousLineDone\n ? 'green'\n : 'red'\n };\">${statusOfPreviousLine}</span>`\n : '') +\n linePrevious;\n input.scrollTop = input.scrollHeight; // https://stackoverflow.com/questions/40495860/how-to-scroll-to-automatically-scroll-to-the-bottom-of-an-editable-div-onload/40506676#40506676\n }\n if (lineArray.length > 0) {\n linePrevious = lineArray.shift(); // https://love2dev.com/blog/javascript-remove-from-array/\n\n await checkLineAndParseProperties(\n linePrevious,\n timesheetTypeUuid,\n synchronizedLineProcessor,\n ); // first step, forwards to consecutive steps\n } else {\n setEnabled(input, true);\n\n const refreshButton = Array.prototype.find.call(\n document.querySelectorAll('button'),\n (button) =>\n button.title.includes('Refresh data') ||\n button.title.includes('Daten aktualisieren'),\n ) as HTMLButtonElement;\n\n if (refreshButton) {\n refreshButton.click();\n }\n }\n }\n\n // TODO ChMa: check if this is still required despite using promises!\n setTimeout(synchronizedLineProcessor, 0); // must be deferred\n}\n\nasync function createContent(): Promise<void> {\n clear();\n await loadCss();\n\n // HTML\n const dummy = document.createElement('dummy');\n dummy.innerHTML = `\n\t\t\t\t\t<div id=\"${idHtml}\">\n\t\t\t\t\t\t<div id=\"${idContent}\">\n\t\t\t\t\t\t\t<div id=\"${idHeader}\">\n\t\t\t\t\t\t\t\t<select id=\"${idSelectType}\" class=\"filament-select-css\">\n\t\t\t\t\t\t\t\t\t<option value=\"cd4f750b-85f8-41f8-b193-9c82e23f82eb\" selected=\"selected\">Office</option>\n\t\t\t\t\t\t\t\t\t<option value=\"0ad94cf7-955c-45dc-b49e-20be0f449b75\">Home Office</option>\n <option value=\"43007851-87f0-468d-b9d2-376ede4a8fd2\">Field Service</option>\n\t\t\t\t\t\t\t\t</select>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t<div id=\"${idMain}\">\n\t\t\t\t\t\t\t\t<div id=\"${idInput}\" contenteditable=\"true\">\n\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div id=\"${idLoader}\">\n\t\t\t\t\t\t\t\t\t<div class=\"spin-wrapper\">\n\t\t\t\t\t\t\t\t\t\t<div class=\"spinner\">\n\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t<div id=\"${idFooter}\">\n\t\t\t\t\t\t\t\t<button id=\"${idButtonBook}\" class=\"pure-material-button-contained\">Book</button>\n\t\t\t\t\t\t\t\t<button id=\"${idButtonClear}\" class=\"pure-material-button-outlined\">Clear</button>\n\t\t\t\t\t\t\t\t<button id=\"${idButtonClose}\" class=\"pure-material-button-outlined\">Close</button>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</div>`;\n document.body.appendChild(dummy.querySelector('div')!);\n\n setTimeout(() => {\n // must be deferred, https://stackoverflow.com/questions/18509507/why-use-settimeout-in-deferred\n document.getElementById(idInput)!.focus();\n }, 0);\n\n // document.getElementById(idInput).addEventListener('paste', (e) => { // https://stackoverflow.com/questions/21257688/paste-rich-text-into-content-editable-div-and-only-keep-bold-and-italics-formatt\n // \te.preventDefault();\n // \tconst clipboardData = e.clipboardData;\n // \tconst dataText = clipboardData.getData('text/plain');\n // \tif (dataText && dataText.trim().length != 0) {\n // \t\tdocument.getElementById(idInput).innerText = dataText;\n // \t\treturn false; // prevent returning text in clipboard\n // \t}\n // }, false);\n //\n // ...this is good, but the following is better...\n //\n document\n .getElementById(idInput)!\n .addEventListener('paste', (e: ClipboardEvent) => {\n // https://stackoverflow.com/questions/12027137/javascript-trick-for-paste-as-plain-text-in-execcommand/19327995#19327995\n e.preventDefault();\n document.execCommand(\n 'insertText',\n false,\n e.clipboardData?.getData('text/plain'),\n );\n });\n\n document.getElementById(idButtonBook)!.onclick = () => {\n bookEntry();\n };\n\n document.getElementById(idButtonClear)!.onclick = () => {\n // https://stackoverflow.com/questions/6348494/addeventlistener-vs-onclick\n const input = document.getElementById(idInput)!;\n\n input.innerHTML = ''; // https://stackoverflow.com/questions/3450593/how-do-i-clear-the-content-of-a-div-using-javascript\n input.focus();\n };\n\n document.getElementById(idButtonClose)!.onclick = () => {\n clear();\n };\n\n document.onkeydown = (event: KeyboardEvent) => {\n if (event.code === 'Escape') {\n clear();\n document.onkeydown = (_: KeyboardEvent) => {}; // deregister\n }\n };\n\n window['COM_KAMILSARELO_DYNATRACE_TIMETRACKING_FORK_RUNNING'] = false;\n}\n\nasync function checkLineAndParseProperties(\n normalizedLine: string,\n timesheetTypeUuid: string,\n callback: (statusOfPreviousLine?: string) => void,\n): Promise<void> {\n normalizedLine = normalizedLine.trim();\n\n if (!normalizedLine) {\n callback(); // no error on empty line\n } else {\n const properties = computeTimecockpitEntryProperties(normalizedLine);\n\n if (properties !== undefined) {\n properties.USR_TimesheetTypeUuid = timesheetTypeUuid;\n await queryUserId(properties, callback);\n } else {\n callback('invalid');\n }\n }\n}\n\nasync function queryUserId(\n properties: TimecockpitEntryProperties,\n callback: (statusOfPreviousLine?: string) => void,\n): Promise<void> {\n async function nextStep() {\n properties.APP_UserDetailUuid = cacheUserDetailUuid;\n await checkIfEntityWithEqualBeginOrEndTimeAlreadyExists(\n properties,\n callback,\n );\n }\n\n if (cacheUserDetailUuid) {\n await nextStep(); // not deferred, because async xhr starts immediately in next step\n return; // avoid running callback too early\n }\n\n try {\n const json = JSON.parse(await xhrGet('/shell/user'));\n\n if (json) {\n if (json.useruuid) {\n cacheUserDetailUuid = json.useruuid;\n await nextStep();\n return; // avoid running callback too early\n } else {\n console.log('ERROR: no useruuid available');\n }\n } else {\n console.log('ERROR: on JSON.parse() in queryUserId()');\n }\n callback('error');\n } catch (error) {\n console.log('ERROR: in queryUserId()', error);\n callback(error.status || 'error');\n }\n}\n\nasync function checkIfEntityWithEqualBeginOrEndTimeAlreadyExists(\n properties: TimecockpitEntryProperties,\n callback: (statusOfPreviousLine?: string) => void,\n): Promise<void> {\n try {\n const filter = `(APP_BeginTime eq datetime'${properties.APP_BeginTime}' or APP_EndTime eq datetime'${properties.APP_EndTime}') and APP_UserDetailUuid eq guid'${properties.APP_UserDetailUuid}'`;\n const response = await xhrGet(`/odata/APP_Timesheet?$filter=${filter}`);\n const json = JSON.parse(response);\n\n if (json?.value) {\n if (json.value.length > 0) {\n console.log(\n 'ERROR: APP_Timesheet entity with equal start- (' +\n properties.APP_BeginTime +\n ') and/or end-time (' +\n properties.APP_EndTime +\n ') exists',\n );\n callback('exists');\n return;\n } else {\n await queryTaskIdAndProjectIdForJiraKey(properties, callback);\n return; // avoid running callback too early\n }\n } else {\n console.log(\n 'ERROR: on JSON.parse() in checkIfEntityWithEqualBeginOrEndTimeAlreadyExists()',\n );\n }\n callback('error');\n } catch (error) {\n console.log(\n 'ERROR: in checkIfEntityWithEqualBeginOrEndTimeAlreadyExists()',\n error,\n );\n callback(error.status || 'error');\n }\n}\n\nasync function queryTaskIdAndProjectIdForJiraKey(\n properties: TimecockpitEntryProperties,\n callback: (statusOfPreviousLine?: string) => void,\n): Promise<void> {\n async function nextStep() {\n const cache = cacheTaskIdAndProjectId.get(properties.jiraKey);\n\n properties.APP_TaskUuid = cache.APP_TaskUuid;\n properties.APP_ProjectUuid = cache.APP_ProjectUuid;\n\n await createEntity(properties, callback);\n }\n\n if (cacheTaskIdAndProjectId.has(properties.jiraKey)) {\n await nextStep(); // not deferred, because async xhr starts immediately in next step\n return; // avoid running callback too early\n }\n\n try {\n const json = JSON.parse(\n await xhrGet(\n `/odata/APP_Task?$filter=APP_Code eq '${properties.jiraKey}'&$select=APP_TaskUuid,APP_ProjectUuid`,\n ),\n ); // https://stackoverflow.com/questions/33169315/json-parse-selecting-from-a-select-container\n\n if (json && json.value) {\n if (json.value.length > 0) {\n cacheTaskIdAndProjectId.set(properties.jiraKey, {\n APP_TaskUuid: json.value[0].APP_TaskUuid,\n APP_ProjectUuid: json.value[0].APP_ProjectUuid,\n });\n await nextStep();\n return; // avoid running callback too early\n } else {\n console.log(\n 'ERROR: no APP_Task entity for specified Jira key (' +\n properties.jiraKey +\n ') available',\n );\n }\n } else {\n console.log(\n 'ERROR: on JSON.parse() in queryTaskIdAndProjectIdForJiraKey()',\n );\n }\n callback('error');\n } catch (error) {\n console.error('ERROR: in queryTaskIdAndProjectIdForJiraKey()', error);\n callback(error.status || 'error');\n }\n}\n\nasync function createEntity(\n properties: TimecockpitEntryProperties,\n callback: (statusOfPreviousLine?: string) => void,\n): Promise<void> {\n const json = JSON.stringify({\n // 'APP_TimesheetUuid': https://stackoverflow.com/questions/105034/create-guid-uuid-in-javascript/2117523#2117523\n APP_BeginTime: properties.APP_BeginTime,\n APP_EndTime: properties.APP_EndTime,\n APP_Description: properties.APP_Description,\n APP_TaskUuid: properties.APP_TaskUuid,\n APP_ProjectUuid: properties.APP_ProjectUuid,\n APP_UserDetailUuid: properties.APP_UserDetailUuid,\n USR_TimesheetTypeUuid: properties.USR_TimesheetTypeUuid,\n // 'APP_IsDurationTimesheet': false,\n // 'APP_NoBilling': false,\n // 'USR_MedicalConfirmationReceived': false\n });\n\n try {\n await xhrPost('/odata/APP_Timesheet', json);\n callback(statusOfPreviousLineDone);\n } catch (error) {\n console.error('ERROR: in createEntity()', error);\n callback(error.status || 'error');\n }\n}\n\nasync function deleteEntity(APP_TimesheetUuid): Promise<void> {\n try {\n await xhrDelete(`/odata/APP_Timesheet(guid'${APP_TimesheetUuid}')`);\n console.log('deleted APP_Timesheet entity with UUID: ' + APP_TimesheetUuid);\n } catch (error) {\n console.error('ERROR: in deleteEntity()', error);\n }\n}\n\nasync function xhrGet(url: string): Promise<string> {\n return xhr(url);\n}\n\nasync function xhrPost(url: string, json?: any): Promise<string> {\n return xhr(url, 'POST', json);\n}\n\nasync function xhrDelete(url: string): Promise<string> {\n return xhr(url, 'DELETE');\n}\n\nasync function xhr(\n url: string,\n method?: 'GET' | 'POST' | 'PUT' | 'DELETE',\n json?: any,\n): Promise<string> {\n const request = new XMLHttpRequest();\n\n return new Promise((resolve, reject) => {\n request.onreadystatechange = () => {\n if (request.readyState !== 4) return; // 4 is DONE, https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/readyState\n if (request.status >= 200 && request.status < 300) {\n resolve(request.responseText);\n } else {\n reject({\n status: request.status,\n statusText: request.statusText,\n });\n }\n };\n\n request.open(method || 'GET', url, true);\n request.setRequestHeader('cache-control', 'no-cache'); // https://stackoverflow.com/a/48969579\n request.setRequestHeader('cache-control', 'max-age=0');\n request.setRequestHeader('pragma', 'no-cache');\n\n if (method === 'POST') {\n request.setRequestHeader(\n 'Content-Type',\n 'application/json; charset=utf-8',\n );\n request.send(json);\n } else {\n request.send();\n }\n });\n}\n\n// RUN BOOKMARKLET\n(async () => {\n // console.clear();\n\n if (window['COM_KAMILSARELO_DYNATRACE_TIMETRACKING_FORK_RUNNING']) {\n console.log('ERROR: bookmarklet is already running');\n return; // https://stackoverflow.com/questions/550574/how-to-terminate-the-script-in-javascript\n }\n window['COM_KAMILSARELO_DYNATRACE_TIMETRACKING_FORK_RUNNING'] = true; // global scope var, https://stackoverflow.com/questions/9521298/verify-external-script-is-loaded\n\n console.log('bookmarklet called');\n\n if (window.location.origin !== timecockpitUrl) {\n const dummy = document.createElement('dummy');\n dummy.innerHTML = `\n\t\t\t<div style=\"position: fixed; top: 0; bottom: 0; left: 0; right: 0; z-index: 999; background-color: rgba(0, 0, 0, 0.66); display: grid;\">\n\t\t\t\t<div style=\"margin: auto; padding: 24px; box-sizing: border-box; font-size: 24px; background-color: yellow; border-radius: 4px; font-family: Roboto, 'Segoe UI', BlinkMacSystemFont, system-ui, -apple-system, Arial, Helvetica, sans-serif;\">\n\t\t\t\t\t...redirecting to ' + url + '. Run the bookmarklet again after the site loaded.\n\t\t\t\t</div>\n\t\t\t</div>`;\n document.body.appendChild(dummy.querySelector('div')!); // https://developer.mozilla.org/de/docs/Web/API/Document/body and https://stackoverflow.com/questions/9614932/best-way-to-create-large-static-dom-elements-in-javascript\n\n window.setTimeout(() => {\n // https://stackoverflow.com/questions/18048338/how-can-i-execute-a-script-after-calling-window-location-href\n // window.onload = () => { ... cannot be performed after the redirect\n window.location.href = timecockpitUrl;\n }, 1000);\n } else if (document.readyState && document.readyState === 'complete') {\n await createContent();\n } else {\n window['COM_KAMILSARELO_DYNATRACE_TIMETRACKING_FORK_RUNNING'] = false;\n }\n})();\n"],"sourceRoot":""}