Compare commits

..

No commits in common. "master" and "v8.0.1" have entirely different histories.

16 changed files with 16548 additions and 8245 deletions

File diff suppressed because it is too large Load Diff

View File

@ -9,8 +9,8 @@ module.exports = {
source: pkg.repository.url, source: pkg.repository.url,
downloadURL: 'https://source.cp-austria.at/git/CPATRD/3cx_tapi/raw/branch/master/3CX_TAPI.user.js', downloadURL: 'https://source.cp-austria.at/git/CPATRD/3cx_tapi/raw/branch/master/3CX_TAPI.user.js',
match: [ match: [
'https://192.168.0.154:5001/*', 'https://192.168.0.154:5001/webclient*',
'https://cpsolution.my3cx.at:5001/*' 'https://cpsolution.my3cx.at:5001/webclient*'
], ],
require: [ require: [
'https://cdn.jsdelivr.net/gh/CoeJoder/waitForKeyElements.js@v1.2/waitForKeyElements.js', 'https://cdn.jsdelivr.net/gh/CoeJoder/waitForKeyElements.js@v1.2/waitForKeyElements.js',

View File

@ -15,6 +15,8 @@ const webpackConfig = {
}, },
externals: { externals: {
jquery: '$', jquery: '$',
axios: 'axios',
'axios-userscript-adapter': 'axiosGmxhrAdapter'
}, },
module: { module: {
rules: [ rules: [

View File

@ -1,7 +1,7 @@
const path = require('path') const path = require('path')
const { merge } = require('webpack-merge') const { merge } = require('webpack-merge')
const LiveReloadPlugin = require('webpack-livereload-plugin') const LiveReloadPlugin = require('webpack-livereload-plugin')
const { UserScriptMetaDataPlugin } = require('userscript-metadata-webpack-plugin') const UserScriptMetaDataPlugin = require('userscript-metadata-webpack-plugin')
const metadata = require('./metadata.cjs') const metadata = require('./metadata.cjs')
const webpackConfig = require('./webpack.config.base.cjs') const webpackConfig = require('./webpack.config.base.cjs')

View File

@ -1,5 +1,5 @@
const { merge } = require('webpack-merge') const { merge } = require('webpack-merge')
const { UserScriptMetaDataPlugin } = require('userscript-metadata-webpack-plugin') const UserScriptMetaDataPlugin = require('userscript-metadata-webpack-plugin')
const metadata = require('./metadata.cjs') const metadata = require('./metadata.cjs')
const webpackConfig = require('./webpack.config.base.cjs') const webpackConfig = require('./webpack.config.base.cjs')

12579
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,7 @@
{ {
"name": "3cx-tapi", "name": "3cp-tapi",
"description": "3CX CP Tapi and Projectmanager integration", "description": "Build your UserScript with webpack",
"version": "9.2.2", "version": "8.0.1",
"author": { "author": {
"name": "Daniel Triendl", "name": "Daniel Triendl",
"email": "d.triendl@cp-solutions.at" "email": "d.triendl@cp-solutions.at"
@ -24,32 +24,34 @@
}, },
"private": true, "private": true,
"dependencies": { "dependencies": {
"chrono-node": "^2.7.7", "axios": "0.21.1",
"@trim21/gm-fetch": "^0.1.16" "axios-userscript-adapter": "0.1.4",
"chrono-node": "^2.3.0"
}, },
"devDependencies": { "devDependencies": {
"@types/greasemonkey": "^4.0.7", "@babel/core": "7.14.6",
"@babel/core": "^7.25.8", "@babel/preset-env": "7.14.5",
"@babel/preset-env": "^7.25.8", "@typescript-eslint/eslint-plugin": "4.27.0",
"@typescript-eslint/eslint-plugin": "^8.8.1", "@typescript-eslint/parser": "4.27.0",
"@typescript-eslint/parser": "^8.8.1", "babel-loader": "8.2.2",
"babel-loader": "^9.2.1", "browserslist": "4.16.6",
"browserslist": "^4.21.9", "css-loader": "5.2.6",
"css-loader": "^7.1.2", "eslint": "7.29.0",
"eslint": "^9.12.0", "eslint-config-standard": "16.0.3",
"eslint-plugin-import": "^2.31.0", "eslint-plugin-import": "2.23.4",
"eslint-plugin-node": "11.1.0", "eslint-plugin-node": "11.1.0",
"eslint-plugin-promise": "^7.1.0S", "eslint-plugin-promise": "5.1.0",
"less": "4.2.0", "eslint-plugin-standard": "4.1.0",
"less-loader": "^12.2.0", "less": "4.1.1",
"style-loader": "^4.0.0", "less-loader": "10.0.0",
"ts-loader": "^9.5.1", "style-loader": "2.0.0",
"typescript": "^5.6.3", "ts-loader": "9.2.3",
"userscript-metadata-webpack-plugin": "^0.4.0", "typescript": "4.3.4",
"webpack": "^5.95.0", "userscript-metadata-webpack-plugin": "0.1.0",
"webpack-bundle-analyzer": "^4.10.2", "webpack": "5.39.1",
"webpack-cli": "^5.1.4", "webpack-bundle-analyzer": "4.4.2",
"webpack-livereload-plugin": "3.0.2", "webpack-cli": "4.7.2",
"webpack-merge": "^6.0.1" "webpack-livereload-plugin": "3.0.1",
"webpack-merge": "5.8.0"
} }
} }

View File

@ -1,18 +1,23 @@
import * as chrono from 'chrono-node' import * as chrono from 'chrono-node'
import { TapiContact } from './tapi-contact' import { TapiContact } from './tapi-contact'
import { extractNumber } from './utils' import { axios, extractNumber } from './utils'
import GM_fetch from '@trim21/gm-fetch'
export class CallHistory { export class CallHistory {
private callerIds: { [number: string]: TapiContact } = {} private callerIds: { [number: string]: TapiContact } = {}
private updateCallHistoryEntry (call: HTMLElement, callerId: TapiContact) { private updateCallHistoryEntry (call: HTMLElement, callerId: TapiContact) {
var span = call.querySelector(':scope > span') var span = call.querySelector('span')
this.showTimeManager(call, call.querySelector('.date').textContent, callerId) this.showTimeManager(call, span.nextSibling.textContent.trim(), callerId)
if (callerId && callerId.tD_NAME !== '') { if (callerId && callerId.tD_NAME !== '') {
var text = span.textContent var text = span.textContent
span.textContent = callerId.tD_NAME + ' ' + callerId.tD_NUMBER span.textContent = callerId.tD_NAME
var br = document.createElement('br')
var span2 = document.createElement('span')
span2.style.fontSize = 'small'
span2.textContent = text
span.parentNode.insertBefore(br, span.nextSibling)
span.parentNode.insertBefore(span2, span.nextSibling)
} }
} }
@ -23,10 +28,10 @@ export class CallHistory {
date = dateParts.groups.date date = dateParts.groups.date
duration = dateParts.groups.duration duration = dateParts.groups.duration
} }
var parsedDate = chrono.parseDate(date)
var parsedDateDe = chrono.de.parseDate(date) var parsedDate = chrono.de.parseDate(date)
if (parsedDateDe) { if (!parsedDate) {
parsedDate = parsedDateDe parsedDate = chrono.parseDate(date)
} }
if (!parsedDate) { if (!parsedDate) {
return return
@ -45,7 +50,7 @@ export class CallHistory {
var length = (parsedDuration.getHours() * 60 + parsedDuration.getMinutes()).toString() var length = (parsedDuration.getHours() * 60 + parsedDuration.getMinutes()).toString()
var toolbar = call.querySelector('call-history-options') var toolbar = call.querySelector('.wcToolbarTiles')
var href = 'domizil://PM/Zeitbuchung?' var href = 'domizil://PM/Zeitbuchung?'
if (callerId && callerId.tD_ID) { if (callerId && callerId.tD_ID) {
href += 'KontaktId=' + callerId.tD_ID + '&' href += 'KontaktId=' + callerId.tD_ID + '&'
@ -57,7 +62,7 @@ export class CallHistory {
a.onclick = () => { a.onclick = () => {
window.open(href) window.open(href)
} }
a.innerHTML = '<svg version="1.1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 559.98 559.98">' + a.innerHTML = '<svg version="1.1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 559.98 559.98" width="20" height="20">' +
'<g>' + '<g>' +
' <g>' + ' <g>' +
' <path d="M279.99,0C125.601,0,0,125.601,0,279.99c0,154.39,125.601,279.99,279.99,279.99c154.39,0,279.99-125.601,279.99-279.99' + ' <path d="M279.99,0C125.601,0,0,125.601,0,279.99c0,154.39,125.601,279.99,279.99,279.99c154.39,0,279.99-125.601,279.99-279.99' +
@ -69,14 +74,11 @@ export class CallHistory {
' </g>' + ' </g>' +
'</g>' + '</g>' +
'</svg>' '</svg>'
a.classList.add('btn');
a.classList.add('btn-plain');
toolbar.insertBefore(a, toolbar.firstChild) toolbar.insertBefore(a, toolbar.firstChild)
} }
public async showCallHistory (element: HTMLElement) { public async showCallHistory (element: HTMLElement) {
var span = element.querySelector(':scope > span') var span = element.querySelector('span')
var number = extractNumber(span.textContent) var number = extractNumber(span.textContent)
if (!number) { if (!number) {
this.updateCallHistoryEntry(element, undefined) this.updateCallHistoryEntry(element, undefined)
@ -86,10 +88,10 @@ export class CallHistory {
if (this.callerIds[number] !== undefined) { if (this.callerIds[number] !== undefined) {
this.updateCallHistoryEntry(element, this.callerIds[number]) this.updateCallHistoryEntry(element, this.callerIds[number])
} else { } else {
var response = await GM_fetch('http://cpatapi.cpsrvweb2016.cp-austria.at/callerid/' + encodeURIComponent(number)) var response = await axios.get<TapiContact>('http://cpatapi.cpsrvweb2016.cp-austria.at/callerid/' + encodeURIComponent(number))
var callerId: TapiContact = { tD_NAME: '' } var callerId: TapiContact = { tD_NAME: '' }
if (response.status === 200) { if (response.status === 200) {
callerId = await response.json() as TapiContact callerId = response.data
} }
console.log('TAPI call histroy callerid response', number, response, callerId) console.log('TAPI call histroy callerid response', number, response, callerId)
this.callerIds[number] = callerId this.callerIds[number] = callerId

View File

@ -1,10 +1,9 @@
import GM_fetch from '@trim21/gm-fetch'
import { TapiContact } from './tapi-contact' import { TapiContact } from './tapi-contact'
import { extractNumber } from './utils' import { axios, extractNumber } from './utils'
export class CallNotification { export class CallNotification {
public async showCallNotification (element: HTMLElement) { public async showCallNotification (element: HTMLElement) {
var number = element.querySelector('.callNumber').textContent var number = element.dataset.id
console.log('TAPI call notification', number) console.log('TAPI call notification', number)
number = extractNumber(number) number = extractNumber(number)
@ -14,19 +13,19 @@ export class CallNotification {
} }
console.log('TAPI searching callerid for', number) console.log('TAPI searching callerid for', number)
var response = await GM_fetch('http://cpatapi.cpsrvweb2016.cp-austria.at/callerid/' + encodeURIComponent(number)) var response = await axios.get<TapiContact>('http://cpatapi.cpsrvweb2016.cp-austria.at/callerid/' + encodeURIComponent(number))
console.log('TAPI callerid response', response) console.log('TAPI callerid response', response)
var notification = { var notification = {
text: number text: number
} }
if (response.status === 200) { if (response.status === 200) {
var callerId = await response.json() as TapiContact var callerId = response.data
if (callerId) { if (callerId) {
notification.text = callerId.tD_NAME + '\r\n' + number + ' (' + callerId.tD_MEDIUM + ')' notification.text = callerId.tD_NAME + '\r\n' + number + ' (' + callerId.tD_MEDIUM + ')'
} }
} }
// eslint-disable-next-line no-undef // eslint-disable-next-line no-undef
GM.notification(notification.text, 'TAPI Anruf') GM.notification(notification)
} }
} }

3
src/decs.d.ts vendored Normal file
View File

@ -0,0 +1,3 @@
declare module 'axios-userscript-adapter'
declare const GM: any

View File

@ -9,7 +9,7 @@ console.log('script start')
const search = new Search() const search = new Search()
// eslint-disable-next-line no-undef // eslint-disable-next-line no-undef
waitForKeyElements('ongoing-call-button', (element) => { search.createSearchWindow(element) }, false) waitForKeyElements('div.nav-search', (element) => { search.createSearchWindow(element) }, true)
const callNotification = new CallNotification() const callNotification = new CallNotification()
// eslint-disable-next-line no-undef // eslint-disable-next-line no-undef
@ -21,4 +21,4 @@ waitForKeyElements('.call-history-list call', (element) => { callHistory.showCal
const status = new Status() const status = new Status()
// eslint-disable-next-line no-undef // eslint-disable-next-line no-undef
waitForKeyElements('wc-account-menu', (element) => { status.showStatus(element) }, false) waitForKeyElements('#status-change', (element) => { status.showStatus(element) }, false)

View File

@ -1,42 +0,0 @@
.tapi-search-autocomplete {
/*the container must be positioned relative:*/
position: relative;
display: inline-block;
margin-right: 20px;
}
.tapi-search-autocomplete input {
border: 1px solid transparent;
background-color: #f1f1f1;
/*padding: 10px;*/
/*font-size: 16px;*/
}
.tapi-search-autocomplete input[type=text] {
background-color: #f1f1f1;
width: 100%;
}
.tapi-search-autocomplete-items {
position: absolute;
border: 1px solid #d4d4d4;
border-bottom: none;
border-top: none;
z-index: 99;
/*position the autocomplete items to be the same width as the container:*/
top: 100%;
left: 0;
right: 0;
}
.tapi-search-autocomplete-items div {
padding: 10px;
cursor: pointer;
background-color: #fff;
border-bottom: 1px solid #d4d4d4;
color: #000;
}
.tapi-search-autocomplete-items div p {
margin: 0;
}
.tapi-search-autocomplete-items div:hover, .tapi-search-autocomplete-active {
/*when hovering an item:*/
background-color: #E7E6E6 !important;
}

View File

@ -1,8 +1,6 @@
import './search.css'
import { TapiContact } from './tapi-contact' import { TapiContact } from './tapi-contact'
import { debounce } from './debounce' import { debounce } from './debounce'
import { fireChangeEvents } from './utils' import { axios, fireChangeEvents } from './utils'
import GM_fetch from '@trim21/gm-fetch'
export class Search { export class Search {
private currentSearchText = '' private currentSearchText = ''
@ -11,29 +9,39 @@ export class Search {
console.log('Create TAPI Search') console.log('Create TAPI Search')
var form = document.createElement('form') var form = document.createElement('form')
form.style.width = '200px'
form.style.float = 'right'
form.style.marginRight = '20px'
form.onsubmit = () => { form.onsubmit = () => {
var items = document.getElementsByClassName('tapi-search-autocomplete-active') var items = document.getElementsByClassName('tapi-search-result-selected')
if (items.length === 0) { if (items.length === 0) {
items = document.getElementsByClassName('tapi-search-autocomplete-item') items = document.getElementsByClassName('tapi-search-result')
} }
if (items.length > 0) { if (items.length > 0) {
this.dial((<HTMLElement>items[0]).dataset.tapiNumber) this.dial((<HTMLElement>items[0]).dataset.tapiNumber)
} else {
this.dial((<HTMLInputElement>document.getElementById('tapiSearchInput')).value)
} }
return false return false
} }
var searchBox = document.createElement('div') var searchBox = document.createElement('div')
searchBox.classList.add('tapi-search-autocomplete') searchBox.classList.add('contact-search-box')
searchBox.style.width = '200px'
searchBox.id = 'tapiSearchBox' searchBox.id = 'tapiSearchBox'
form.appendChild(searchBox) form.appendChild(searchBox)
var searchWrapper = document.createElement('div')
searchWrapper.classList.add('search-input-wrapper')
searchWrapper.style.position = 'relative'
searchBox.appendChild(searchWrapper)
var search = document.createElement('input') var search = document.createElement('input')
search.id = 'tapiSearchInput' search.id = 'tapiSearchInput'
search.autocomplete = 'off' search.autocomplete = 'off'
search.classList.add('padder')
search.classList.add('rounded')
search.classList.add('bg-light')
search.classList.add('no-border')
search.classList.add('contact-search-box')
search.placeholder = 'TAPI Suche' search.placeholder = 'TAPI Suche'
search.onfocus = () => { this.doSearch() } search.onfocus = () => { this.doSearch() }
search.onkeydown = (ev) => { this.doSearchKeyDown(ev) } search.onkeydown = (ev) => { this.doSearchKeyDown(ev) }
@ -42,15 +50,22 @@ export class Search {
setTimeout(() => { setTimeout(() => {
console.log('TAPI clear search results') console.log('TAPI clear search results')
this.removeSearchResults() this.removeSearchResults()
}, 250) }, 500)
} }
searchBox.appendChild(search) searchWrapper.appendChild(search)
element.parentElement.insertBefore(form, element) var icon = document.createElement('span')
icon.classList.add('fa')
icon.classList.add('fa-search')
icon.classList.add('form-control-feedback')
icon.style.color = 'grey'
searchWrapper.appendChild(icon)
element.appendChild(form)
} }
private removeSearchResults () { private removeSearchResults () {
var resultList = document.getElementById('tapi-search-autocomplete-list') var resultList = document.getElementById('tapiResults')
if (resultList) { if (resultList) {
resultList.parentNode.removeChild(resultList) resultList.parentNode.removeChild(resultList)
} }
@ -59,12 +74,12 @@ export class Search {
private doSearchKeyDown (ev: KeyboardEvent) { private doSearchKeyDown (ev: KeyboardEvent) {
if (ev.key === 'ArrowUp') { if (ev.key === 'ArrowUp') {
let items = document.getElementsByClassName('tapi-search-autocomplete-active') let items = document.getElementsByClassName('tapi-search-result-selected')
if (items.length > 0) { if (items.length > 0) {
var prev = <Element>items[0].previousSibling var prev = <Element>items[0].previousSibling
} }
if (!prev) { if (!prev) {
items = document.getElementsByClassName('tapi-search-autocomplete-item') items = document.getElementsByClassName('tapi-search-result')
if (items.length > 0) { if (items.length > 0) {
prev = items[items.length - 1] prev = items[items.length - 1]
} }
@ -74,12 +89,12 @@ export class Search {
prev.scrollIntoView(true) prev.scrollIntoView(true)
} }
} else if (ev.key === 'ArrowDown') { } else if (ev.key === 'ArrowDown') {
let items = document.getElementsByClassName('tapi-search-autocomplete-active') let items = document.getElementsByClassName('tapi-search-result-selected')
if (items.length > 0) { if (items.length > 0) {
var next = <Element>items[0].nextSibling var next = <Element>items[0].nextSibling
} }
if (!next) { if (!next) {
items = document.getElementsByClassName('tapi-search-autocomplete-item') items = document.getElementsByClassName('tapi-search-result')
if (items.length > 0) { if (items.length > 0) {
next = items[0] next = items[0]
} }
@ -103,51 +118,64 @@ export class Search {
return return
} }
console.log('Searching TAPI') console.log('Searching TAPI')
var response = await GM_fetch('http://cpatapi.cpsrvweb2016.cp-austria.at/search?query=' + encodeURIComponent(searchText)) var response = await axios.get<TapiContact[]>('http://cpatapi.cpsrvweb2016.cp-austria.at/search?query=' + encodeURIComponent(searchText))
console.log('TAPI Search response', response) console.log('TAPI Search response', response)
var contacts = await response.json() as TapiContact[] var contacts = response.data
console.log('TAPI Contacts', contacts) console.log('TAPI Contacts', contacts)
this.removeSearchResults() this.removeSearchResults()
this.currentSearchText = searchText this.currentSearchText = searchText
var results = document.createElement('div'); var resultList = document.createElement('ul')
results.setAttribute('id', 'tapi-search-autocomplete-list') resultList.id = 'tapiResults'
results.setAttribute('class', 'tapi-search-autocomplete-items') resultList.classList.add('search-nav-absolute')
document.getElementById('tapiSearchBox').appendChild(results) resultList.classList.add('search-nav-ul')
document.getElementById('tapiSearchBox').appendChild(resultList)
resultList.innerHTML = ''
contacts.forEach(contact => { contacts.forEach(contact => {
var item = document.createElement('div'); var li = document.createElement('li')
item.setAttribute('class', 'tapi-search-autocomplete-item') li.classList.add('tapi-search-result')
var p = document.createElement('p') li.classList.add('search-result')
p.innerHTML = contact.tD_NAME + '<br>' + contact.tD_MEDIUM + ': ' + contact.tD_NUMBER_TAPI li.classList.add('pointer')
item.appendChild(p) li.onmouseover = () => { this.selectResult(li) }
item.onclick = () => { this.dial(contact.tD_NUMBER_TAPI) } li.dataset.tapiNumber = contact.tD_NUMBER_TAPI
item.onmouseover = () => { this.selectResult(item) } li.onclick = () => { this.dial(contact.tD_NUMBER_TAPI) }
item.dataset.tapiNumber = contact.tD_NUMBER_TAPI li.style.listStyle = 'outside none none' // display: flex; align-items: center;
results.appendChild(item);
var resultText = document.createElement('div')
resultText.classList.add('search-result-txt')
li.appendChild(resultText)
var line1 = document.createElement('div')
line1.appendChild(document.createTextNode(contact.tD_NAME))
resultText.appendChild(line1)
var line2 = document.createElement('div')
line2.appendChild(document.createTextNode(contact.tD_MEDIUM + ': ' + contact.tD_NUMBER_TAPI))
resultText.appendChild(line2)
resultList.appendChild(li)
}) })
}, 200) }, 200)
private selectResult (item: Element) { private selectResult (resultLi: Element) {
console.log('Select item', item) var items = document.getElementsByClassName('tapi-search-result')
var items = document.getElementsByClassName('tapi-search-autocomplete-active') for (var item of items) {
for (var i of items) { item.classList.remove('bg-light')
i.classList.remove('tapi-search-autocomplete-active') item.classList.remove('tapi-search-result-selected')
} }
item.classList.add('tapi-search-autocomplete-active') resultLi.classList.add('bg-light')
resultLi.classList.add('tapi-search-result-selected')
} }
private dial (number: string) { private dial (number: string) {
console.log('TAPI Search dialing', number); var searchInput = document.getElementsByName('searchByNumberInput')
var searchInput = document.getElementById('dialpad-input'); if (searchInput.length > 0) {
(<HTMLInputElement>searchInput).value = number; (<HTMLInputElement>searchInput[0]).value = number
(<HTMLInputElement>searchInput).focus; searchInput[0].focus()
fireChangeEvents(searchInput);
var toaster = document.querySelector('toaster-container'); fireChangeEvents(searchInput[0])
if (window.getComputedStyle(toaster, null).display == 'none') {
document.getElementById('menuDialer').click();
} }
} }
} }

View File

@ -1,6 +1,6 @@
import './status.css'; import './status.css';
import { axios } from './utils';
import { ZcStatus } from './zc-status'; import { ZcStatus } from './zc-status';
import GM_fetch from "@trim21/gm-fetch";
declare function waitForKeyElements(selectorOrFunction: any, callback: any, waitOnce: boolean): any; declare function waitForKeyElements(selectorOrFunction: any, callback: any, waitOnce: boolean): any;
@ -18,106 +18,54 @@ export class Status {
this._statusOff = await GM.getValue('tapi-zc-off', 'menuAvailable'); this._statusOff = await GM.getValue('tapi-zc-off', 'menuAvailable');
console.log('tapi-zc-user', this._user, 'tapi-zc-enabled', this._enabled, 'tapi-zc-on', this._statusOn, 'tapi-zc-off', this._statusOff); console.log('tapi-zc-user', this._user, 'tapi-zc-enabled', this._enabled, 'tapi-zc-on', this._statusOn, 'tapi-zc-off', this._statusOff);
this.checkStatus(); var div = document.createElement('div');
div.classList.add('tapi-dropdown');
waitForKeyElements("wc-account-menu > div > ul", (element: HTMLElement) => { this.addZcStatusPopup(element) }, true); var button = document.createElement('button');
} button.id = 'tapi-zc-button';
button.classList.add('btn');
private async checkStatus() { button.classList.add('btn-default');
if (this._enabled) { button.innerText = 'ZeitConsens';
try { button.onclick = () => {
var response = await GM_fetch('http://cpatapi.cpsrvweb2016.cp-austria.at/availability/' + encodeURIComponent(this._user)); document.getElementById('tapi-zc-dropdown').classList.toggle('show');
if (response.status == 200) {
var status = await response.json() as ZcStatus;
if (this._currentStatus !== status.loggedIn) {
this._currentStatus = status.loggedIn;
console.log('New status, loggedIn', this._currentStatus);
var accMenu = document.getElementsByTagName("wc-account-menu")[0];
var avatar = accMenu.getElementsByTagName("app-avatar")[0] as HTMLAnchorElement;
avatar.click();
setTimeout(() => {
var statusId = this._currentStatus ? this._statusOn : this._statusOff;
console.log('Clicking status', statusId);
(document.getElementById(statusId) as HTMLSpanElement).click();
}, 1000);
}
}
} catch (error) {
console.log(error);
}
setTimeout(() => this.checkStatus(), 30000);
} }
} div.appendChild(button);
private addZcStatusPopup(element: HTMLElement) {
var divider = document.createElement('li');
divider.classList.add('divider');
divider.classList.add('dropdown-divider');
element.appendChild(divider);
var menu = document.createElement('li');
element.appendChild(menu);
var link = document.createElement('a');
link.id = 'tapi-zc-button';
link.innerText = 'ZeitConsens';
link.classList.add('dropdown-item');
link.classList.add('d-flex');
link.onclick = () => {
document.getElementById('zc-modal').classList.toggle('show');
}
menu.appendChild(link);
var html = var html =
'<div role="document" class="modal-dialog">' + '<div class="form-group">' +
' <div class="modal-content">' + ' <label for="tapi-zc-user">Username</label>' +
' <div class="modal-header">' + ' <input type="text" class="form-control" name="tapi-zc-user" id="tapi-zc-user">' +
' <h4 class="modal-title">ZeitConsens Status</h4><button id="zc-btnClose" type="button" aria-label="Close" class="btn-close" data-qa="modal-cross"></button>' + '</div>' +
' </div>' + '<div class="form-group">' +
' <div class="modal-body">' + ' <label for="tapi-zc-on">Signed in</label>' +
' <div class="form-group">' + ' <select id="tapi-zc-on" class="form-control">' +
' <label for="tapi-zc-user">Username</label>' + ' <option value="menuAvailable">Available</option>' +
' <input type="text" class="form-control" name="tapi-zc-user" id="tapi-zc-user">' + ' <option value="menuOutofoffice">Do Not Disturb</option>' +
' </div>' + ' <option value="menuCustom1">Verfügbar DW</option>' +
' <div class="form-group">' + ' </select>' +
' <label for="tapi-zc-on">Signed in</label>' + '</div>' +
' <select id="tapi-zc-on" class="form-control">' + '<div class="form-group">' +
' <option value="menuAvailable">Available</option>' + ' <label for="tapi-zc-off">Signed out</label>' +
' <option value="menuOutofoffice">Do Not Disturb</option>' + ' <select id="tapi-zc-off" class="form-control">' +
' <option value="menuCustom1">Verfügbar DW</option>' + ' <option value="menuAway">Away</option>' +
' </select>' + ' <option value="menuOutofoffice">Do Not Disturb</option>' +
' </div>' + ' </select>' +
' <div class="form-group">' + '</div>' +
' <label for="tapi-zc-off">Signed out</label>' + '<div class="checkbox">' +
' <select id="tapi-zc-off" class="form-control">' + ' <label class="i-checks" for="tapi-zc-enabled">' +
' <option value="menuAway">Away</option>' + ' <input type="checkbox" id="tapi-zc-enabled">' +
' <option value="menuOutofoffice">Do Not Disturb</option>' + ' <i></i><span>Enabled</span>' +
' </select>' + '</label>'
' </div>' +
' <div class="checkbox">' +
' <label class="i-checks" for="tapi-zc-enabled">' +
' <input type="checkbox" id="tapi-zc-enabled">' +
' <i></i><span>Enabled</span>' +
' </label>' +
' </div>' +
' </div>' +
//' <div class="modal-footer">' +
//' <button id="zc-btnOk" type="button" class="btn btn-primary" data-qa="modal-ok">OK </button>' +
//' <button id="zc-btnCancel" type="button" class="btn btn-border" data-qa="modal-close">Cancel </button>' +
//' </div>' +
' </div>' +
'</div>'; '</div>';
var modal = document.createElement('modal-container');
modal.id = 'zc-modal';
modal.classList.add('modal');
modal.classList.add('fade');
modal.innerHTML = html;
document.getElementsByTagName('body')[0].appendChild(modal);
var btnClose = document.getElementById('zc-btnClose'); var dropdown = document.createElement('div');
btnClose.onclick = () => { dropdown.classList.add('tapi-dropdown-content');
document.getElementById('zc-modal').classList.toggle('show'); dropdown.classList.add('panel-body');
} dropdown.id = 'tapi-zc-dropdown';
dropdown.innerHTML = html;
div.appendChild(dropdown);
element.insertBefore(div, element.firstChild);
var zcUser = document.getElementById('tapi-zc-user') as HTMLInputElement; var zcUser = document.getElementById('tapi-zc-user') as HTMLInputElement;
zcUser.value = this._user; zcUser.value = this._user;
@ -155,5 +103,31 @@ export class Status {
console.log('tapi-zc-off', this._statusOff); console.log('tapi-zc-off', this._statusOff);
this._currentStatus = undefined; this._currentStatus = undefined;
} }
this.checkStatus();
}
private async checkStatus() {
if (this._enabled) {
try {
var response = await axios.get<ZcStatus>('http://cpatapi.cpsrvweb2016.cp-austria.at/availability/' + encodeURIComponent(this._user));
if (response.status == 200) {
var status = response.data;
if (this._currentStatus !== status.loggedIn) {
this._currentStatus = status.loggedIn;
console.log('New status, loggedIn', this._currentStatus);
(document.getElementsByClassName("current-status")[0] as HTMLAnchorElement).click();
setTimeout(() => {
var statusId = this._currentStatus ? this._statusOn : this._statusOff;
(document.getElementById(statusId) as HTMLAnchorElement).click();
}, 1000);
}
}
} catch (error) {
console.log(error);
}
setTimeout(() => this.checkStatus(), 30000);
}
} }
} }

View File

@ -1,3 +1,23 @@
/**
* @typedef {Object} AxiosResponse
* @property {Object} data
* @property {Object} headers
* @property {Object} config
* @property {Object} request
* @property {number} code
* @property {string} statusText
*/
/**
* @typedef {Object} AxiosError
* @property {AxiosResponse} response
*/
import axios from 'axios'
import adapter from 'axios-userscript-adapter'
axios.defaults.adapter = adapter
export { axios }
export function extractNumber (s: string) { export function extractNumber (s: string) {
var match = /(\+?[0-9]{4,})/.exec(s) var match = /(\+?[0-9]{4,})/.exec(s)
if (!match) { if (!match) {

View File

@ -2,8 +2,8 @@
"compilerOptions": { "compilerOptions": {
"outDir": "./dist/", "outDir": "./dist/",
"noImplicitAny": true, "noImplicitAny": true,
"module": "ESNext", "module": "es6",
"target": "ES2022", "target": "es6",
"allowJs": true, "allowJs": true,
"moduleResolution": "node" "moduleResolution": "node"
} }