Compare commits
15 Commits
Author | SHA1 | Date | |
---|---|---|---|
ba5a5c627b | |||
3bf1baeca8 | |||
6186b14b16 | |||
f578bd2fe1 | |||
933b445ed6 | |||
bbe20d6351 | |||
9e5d93bad2 | |||
b83cef625a | |||
ad5c8ece12 | |||
0455cb1926 | |||
3e33155276 | |||
de34a6c66e | |||
a4a346b48d | |||
cd303869c8 | |||
4283ee6b5c |
9
.babelrc.js
Normal file
9
.babelrc.js
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
module.exports = function (api) {
|
||||||
|
api.cache(true)
|
||||||
|
|
||||||
|
const presets = ['@babel/preset-env']
|
||||||
|
|
||||||
|
return {
|
||||||
|
presets,
|
||||||
|
}
|
||||||
|
}
|
3
.browserslistrc
Normal file
3
.browserslistrc
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
> 1%
|
||||||
|
not IE 11
|
||||||
|
not dead
|
13345
3CX_TAPI.user.js
13345
3CX_TAPI.user.js
File diff suppressed because one or more lines are too long
@ -5,9 +5,9 @@ module.exports = {
|
|||||||
namespace: 'http://cp-solutions.at',
|
namespace: 'http://cp-solutions.at',
|
||||||
version: pkg.version,
|
version: pkg.version,
|
||||||
author: pkg.author,
|
author: pkg.author,
|
||||||
copyright: 'Copyright 2020 CP Solutions GmbH',
|
copyright: 'Copyright 2021 CP Solutions GmbH',
|
||||||
source: pkg.repository.url,
|
source: pkg.repository.url,
|
||||||
downloadURL: 'http://scootaloo.cp-austria.at/gitlist/3cx_tapi.git/raw/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/webclient*',
|
'https://192.168.0.154:5001/webclient*',
|
||||||
'https://cpsolution.my3cx.at:5001/webclient*'
|
'https://cpsolution.my3cx.at:5001/webclient*'
|
||||||
@ -18,8 +18,10 @@ module.exports = {
|
|||||||
`https://cdn.jsdelivr.net/npm/axios-userscript-adapter@${pkg.dependencies['axios-userscript-adapter']}/dist/axiosGmxhrAdapter.min.js`
|
`https://cdn.jsdelivr.net/npm/axios-userscript-adapter@${pkg.dependencies['axios-userscript-adapter']}/dist/axiosGmxhrAdapter.min.js`
|
||||||
],
|
],
|
||||||
grant: [
|
grant: [
|
||||||
'GM_xmlhttpRequest',
|
'GM.xmlHttpRequest',
|
||||||
'GM.notification'
|
'GM.notification',
|
||||||
|
'GM.getValue',
|
||||||
|
'GM.setValue'
|
||||||
],
|
],
|
||||||
connect: [
|
connect: [
|
||||||
'cpatapi.cpsrvweb2016.cp-austria.at'
|
'cpatapi.cpsrvweb2016.cp-austria.at'
|
@ -1,42 +1,38 @@
|
|||||||
const path = require('path')
|
const path = require('path')
|
||||||
const webpack = require('webpack')
|
const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer')
|
||||||
|
|
||||||
const webpackConfig = {
|
const webpackConfig = {
|
||||||
node: {
|
|
||||||
Buffer: false
|
|
||||||
},
|
|
||||||
resolve: {
|
resolve: {
|
||||||
extensions: ['.js', '.ts']
|
extensions: ['.js', '.ts']
|
||||||
},
|
},
|
||||||
// performance: {
|
|
||||||
// hints: false
|
|
||||||
// },
|
|
||||||
optimization: {
|
optimization: {
|
||||||
minimize: false
|
minimize: false,
|
||||||
|
moduleIds: 'named',
|
||||||
},
|
},
|
||||||
entry: './src/js/index.js',
|
entry: './src/index.js',
|
||||||
output: {
|
output: {
|
||||||
path: path.resolve(__dirname, '../dist')
|
path: path.resolve(__dirname, '../dist')
|
||||||
},
|
},
|
||||||
externals: {
|
externals: {
|
||||||
|
jquery: '$',
|
||||||
axios: 'axios',
|
axios: 'axios',
|
||||||
'axios-userscript-adapter': 'axiosGmxhrAdapter'
|
'axios-userscript-adapter': 'axiosGmxhrAdapter'
|
||||||
},
|
},
|
||||||
module: {
|
module: {
|
||||||
rules: [
|
rules: [
|
||||||
{
|
{
|
||||||
|
use: {
|
||||||
|
loader: 'babel-loader',
|
||||||
|
},
|
||||||
test: /\.js$/,
|
test: /\.js$/,
|
||||||
exclude: /node_modules/,
|
|
||||||
loader: 'eslint-loader'
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
test: /\.ts$/,
|
test: /\.ts$/,
|
||||||
exclude: /node_modules/,
|
|
||||||
loader: 'ts-loader'
|
loader: 'ts-loader'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
test: /\.less$/,
|
test: /\.less$/,
|
||||||
loader: [
|
use: [
|
||||||
'style-loader',
|
'style-loader',
|
||||||
'css-loader',
|
'css-loader',
|
||||||
'less-loader', // 将 Less 编译为 CSS
|
'less-loader', // 将 Less 编译为 CSS
|
||||||
@ -44,16 +40,14 @@ const webpackConfig = {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
test: /\.css$/,
|
test: /\.css$/,
|
||||||
loader: [
|
use: [
|
||||||
'style-loader',
|
'style-loader',
|
||||||
'css-loader',
|
'css-loader',
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
plugins: [
|
plugins: process.env.npm_config_report ? [new BundleAnalyzerPlugin()] : [],
|
||||||
new webpack.HashedModuleIdsPlugin()
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = webpackConfig
|
module.exports = webpackConfig
|
37
config/webpack.config.dev.cjs
Normal file
37
config/webpack.config.dev.cjs
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
const path = require('path')
|
||||||
|
const { merge } = require('webpack-merge')
|
||||||
|
const LiveReloadPlugin = require('webpack-livereload-plugin')
|
||||||
|
const UserScriptMetaDataPlugin = require('userscript-metadata-webpack-plugin')
|
||||||
|
|
||||||
|
const metadata = require('./metadata.cjs')
|
||||||
|
const webpackConfig = require('./webpack.config.base.cjs')
|
||||||
|
|
||||||
|
metadata.require.push(
|
||||||
|
'file://' + path.resolve(__dirname, '../dist/index.prod.user.js')
|
||||||
|
)
|
||||||
|
|
||||||
|
const cfg = merge(webpackConfig, {
|
||||||
|
entry: {
|
||||||
|
prod: webpackConfig.entry,
|
||||||
|
dev: path.resolve(__dirname, './empty.cjs'),
|
||||||
|
},
|
||||||
|
output: {
|
||||||
|
filename: 'index.[name].user.js',
|
||||||
|
path: path.resolve(__dirname, '../dist'),
|
||||||
|
},
|
||||||
|
devtool: 'inline-source-map',
|
||||||
|
watch: true,
|
||||||
|
watchOptions: {
|
||||||
|
ignored: /node_modules/,
|
||||||
|
},
|
||||||
|
plugins: [
|
||||||
|
new LiveReloadPlugin({
|
||||||
|
delay: 500,
|
||||||
|
}),
|
||||||
|
new UserScriptMetaDataPlugin({
|
||||||
|
metadata,
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
})
|
||||||
|
|
||||||
|
module.exports = cfg
|
@ -1,43 +0,0 @@
|
|||||||
const path = require("path");
|
|
||||||
const { merge } = require("webpack-merge");
|
|
||||||
const BundleAnalyzerPlugin = require("webpack-bundle-analyzer")
|
|
||||||
.BundleAnalyzerPlugin;
|
|
||||||
const LiveReloadPlugin = require("webpack-livereload-plugin");
|
|
||||||
const UserScriptMetaDataPlugin = require("userscript-metadata-webpack-plugin");
|
|
||||||
const metadata = require("./metadata");
|
|
||||||
|
|
||||||
const webpackConfig = require("./webpack.config.base");
|
|
||||||
|
|
||||||
metadata.require.push(
|
|
||||||
"file://" + path.resolve(__dirname, "../dist/index.prod.user.js")
|
|
||||||
);
|
|
||||||
|
|
||||||
const cfg = merge(webpackConfig, {
|
|
||||||
entry: {
|
|
||||||
prod: webpackConfig.entry,
|
|
||||||
dev: path.resolve(__dirname, "./empty.js"),
|
|
||||||
},
|
|
||||||
output: {
|
|
||||||
filename: "index.[name].user.js",
|
|
||||||
path: path.resolve(__dirname, "../dist"),
|
|
||||||
},
|
|
||||||
devtool: "inline-source-map",
|
|
||||||
watch: true,
|
|
||||||
watchOptions: {
|
|
||||||
ignored: /node_modules/,
|
|
||||||
},
|
|
||||||
plugins: [
|
|
||||||
new LiveReloadPlugin({
|
|
||||||
delay: 500,
|
|
||||||
}),
|
|
||||||
new UserScriptMetaDataPlugin({
|
|
||||||
metadata,
|
|
||||||
}),
|
|
||||||
],
|
|
||||||
});
|
|
||||||
|
|
||||||
if (process.env.npm_config_report) {
|
|
||||||
cfg.plugins.push(new BundleAnalyzerPlugin());
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = cfg;
|
|
19
config/webpack.config.production.cjs
Normal file
19
config/webpack.config.production.cjs
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
const { merge } = require('webpack-merge')
|
||||||
|
const UserScriptMetaDataPlugin = require('userscript-metadata-webpack-plugin')
|
||||||
|
|
||||||
|
const metadata = require('./metadata.cjs')
|
||||||
|
const webpackConfig = require('./webpack.config.base.cjs')
|
||||||
|
|
||||||
|
const cfg = merge(webpackConfig, {
|
||||||
|
mode: 'production',
|
||||||
|
output: {
|
||||||
|
filename: metadata.name + '.prod.user.js',
|
||||||
|
},
|
||||||
|
plugins: [
|
||||||
|
new UserScriptMetaDataPlugin({
|
||||||
|
metadata,
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
})
|
||||||
|
|
||||||
|
module.exports = cfg
|
@ -1,23 +0,0 @@
|
|||||||
const { merge } = require("webpack-merge");
|
|
||||||
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin
|
|
||||||
|
|
||||||
const UserScriptMetaDataPlugin = require('userscript-metadata-webpack-plugin')
|
|
||||||
const metadata = require('./metadata')
|
|
||||||
|
|
||||||
const webpackConfig = require('./webpack.config.base')
|
|
||||||
const cfg = merge({}, webpackConfig, {
|
|
||||||
output: {
|
|
||||||
filename: 'index.prod.user.js'
|
|
||||||
},
|
|
||||||
plugins: [
|
|
||||||
new UserScriptMetaDataPlugin({
|
|
||||||
metadata
|
|
||||||
})
|
|
||||||
]
|
|
||||||
})
|
|
||||||
|
|
||||||
if (process.env.npm_config_report) {
|
|
||||||
cfg.plugins.push(new BundleAnalyzerPlugin())
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = cfg
|
|
15443
package-lock.json
generated
15443
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
71
package.json
71
package.json
@ -1,58 +1,57 @@
|
|||||||
{
|
{
|
||||||
"name": "3cp-tapi",
|
"name": "3cx-tapi",
|
||||||
"description": "Build your UserScript with webpack",
|
"description": "3CX CP Tapi and Projectmanager integration",
|
||||||
"version": "7.0.3",
|
"version": "9.0.2",
|
||||||
"author": {
|
"author": {
|
||||||
"name": "Daniel Triendl",
|
"name": "Daniel Triendl",
|
||||||
"email": "d.triendl@cp-solutions.at"
|
"email": "d.triendl@cp-solutions.at"
|
||||||
},
|
},
|
||||||
"browserslist": [
|
|
||||||
"last 2 version",
|
|
||||||
"> 1%"
|
|
||||||
],
|
|
||||||
"eslintIgnore": [
|
"eslintIgnore": [
|
||||||
"dist/*.js"
|
"dist/*.js",
|
||||||
|
"node_modules"
|
||||||
],
|
],
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"lint": "eslint src",
|
"lint": "eslint --ext .ts,.js src",
|
||||||
"preversion": "npm run lint",
|
"preversion": "npm run lint",
|
||||||
"postversion": "git push --follow-tags",
|
"postversion": "git push --follow-tags",
|
||||||
"anylize": "npm_config_report=true npm run build",
|
"anylize": "npm_config_report=true npm run build",
|
||||||
"build": "webpack --mode production --config config/webpack.config.production.js",
|
"build": "webpack --mode production --config config/webpack.config.production.cjs",
|
||||||
"dev": "webpack --mode development --config config/webpack.config.dev.js"
|
"dev": "webpack --mode development --config config/webpack.config.dev.cjs"
|
||||||
},
|
},
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "http://scootaloo.cp-austria.at/gitlist/3cx_tapi.git"
|
"url": "https://source.cp-austria.at/git/CPATRD/3cx_tapi.git"
|
||||||
},
|
},
|
||||||
"private": true,
|
"private": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"axios": "0.20.0",
|
"axios": "0.21.1",
|
||||||
"axios-userscript-adapter": "0.0.7",
|
"axios-userscript-adapter": "0.1.4",
|
||||||
"chrono-node": "2.1.9"
|
"chrono-node": "^2.3.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@typescript-eslint/eslint-plugin": "4.3.0",
|
"@babel/core": "7.14.6",
|
||||||
"@typescript-eslint/parser": "4.3.0",
|
"@babel/preset-env": "7.14.5",
|
||||||
"css-loader": "4.3.0",
|
"@typescript-eslint/eslint-plugin": "4.27.0",
|
||||||
"eslint": "7.10.0",
|
"@typescript-eslint/parser": "4.27.0",
|
||||||
"eslint-config-standard": "14.1.1",
|
"babel-loader": "8.2.2",
|
||||||
"eslint-loader": "4.0.2",
|
"browserslist": "4.16.6",
|
||||||
"eslint-plugin-import": "2.22.1",
|
"css-loader": "5.2.6",
|
||||||
|
"eslint": "7.29.0",
|
||||||
|
"eslint-config-standard": "16.0.3",
|
||||||
|
"eslint-plugin-import": "2.23.4",
|
||||||
"eslint-plugin-node": "11.1.0",
|
"eslint-plugin-node": "11.1.0",
|
||||||
"eslint-plugin-promise": "4.2.1",
|
"eslint-plugin-promise": "5.1.0",
|
||||||
"eslint-plugin-standard": "4.0.1",
|
"eslint-plugin-standard": "4.1.0",
|
||||||
"less": "3.12.2",
|
"less": "4.1.1",
|
||||||
"less-loader": "7.0.1",
|
"less-loader": "10.0.0",
|
||||||
"style-loader": "1.2.1",
|
"style-loader": "2.0.0",
|
||||||
"ts-loader": "8.0.4",
|
"ts-loader": "9.2.3",
|
||||||
"typescript": "4.0.3",
|
"typescript": "4.3.4",
|
||||||
"userscript-metadata-webpack-plugin": "0.0.6",
|
"userscript-metadata-webpack-plugin": "0.1.0",
|
||||||
"webpack": "4.44.2",
|
"webpack": "5.39.1",
|
||||||
"webpack-bundle-analyzer": "3.9.0",
|
"webpack-bundle-analyzer": "4.4.2",
|
||||||
"webpack-cli": "3.3.12",
|
"webpack-cli": "4.7.2",
|
||||||
"webpack-dev-server": "^3.11.0",
|
"webpack-livereload-plugin": "3.0.1",
|
||||||
"webpack-livereload-plugin": "2.3.0",
|
"webpack-merge": "5.8.0"
|
||||||
"webpack-merge": "5.1.4"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -43,7 +43,7 @@ npm run build
|
|||||||
## distribution
|
## distribution
|
||||||
|
|
||||||
```
|
```
|
||||||
cp dist/index.prod.user.js 3CX_TAPI.user.js
|
cp "dist/3CX TAPI.prod.user.js" 3CX_TAPI.user.js
|
||||||
```
|
```
|
||||||
|
|
||||||
And commit 3CX_TAPI.user.js
|
And commit 3CX_TAPI.user.js
|
||||||
|
@ -6,18 +6,12 @@ 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('span')
|
var span = call.querySelector(':scope > span')
|
||||||
this.showTimeManager(call, span.nextSibling.textContent.trim(), callerId)
|
this.showTimeManager(call, call.querySelector('.date').textContent, callerId)
|
||||||
|
|
||||||
if (callerId && callerId.tD_NAME !== '') {
|
if (callerId && callerId.tD_NAME !== '') {
|
||||||
var text = span.textContent
|
var text = span.textContent
|
||||||
span.textContent = callerId.tD_NAME
|
span.textContent = callerId.tD_NAME + ' ' + callerId.tD_NUMBER
|
||||||
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)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -28,7 +22,6 @@ export class CallHistory {
|
|||||||
date = dateParts.groups.date
|
date = dateParts.groups.date
|
||||||
duration = dateParts.groups.duration
|
duration = dateParts.groups.duration
|
||||||
}
|
}
|
||||||
|
|
||||||
var parsedDate = chrono.de.parseDate(date)
|
var parsedDate = chrono.de.parseDate(date)
|
||||||
if (!parsedDate) {
|
if (!parsedDate) {
|
||||||
parsedDate = chrono.parseDate(date)
|
parsedDate = chrono.parseDate(date)
|
||||||
@ -50,7 +43,7 @@ export class CallHistory {
|
|||||||
|
|
||||||
var length = (parsedDuration.getHours() * 60 + parsedDuration.getMinutes()).toString()
|
var length = (parsedDuration.getHours() * 60 + parsedDuration.getMinutes()).toString()
|
||||||
|
|
||||||
var toolbar = call.querySelector('.wcToolbarTiles')
|
var toolbar = call.querySelector('call-history-options')
|
||||||
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 + '&'
|
||||||
@ -62,7 +55,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" width="20" height="20">' +
|
a.innerHTML = '<svg version="1.1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 559.98 559.98">' +
|
||||||
'<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' +
|
||||||
@ -74,11 +67,14 @@ 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('span')
|
var span = element.querySelector(':scope > span')
|
||||||
var number = extractNumber(span.textContent)
|
var number = extractNumber(span.textContent)
|
||||||
if (!number) {
|
if (!number) {
|
||||||
this.updateCallHistoryEntry(element, undefined)
|
this.updateCallHistoryEntry(element, undefined)
|
@ -3,7 +3,7 @@ import { axios, extractNumber } from './utils'
|
|||||||
|
|
||||||
export class CallNotification {
|
export class CallNotification {
|
||||||
public async showCallNotification (element: HTMLElement) {
|
public async showCallNotification (element: HTMLElement) {
|
||||||
var number = element.dataset.id
|
var number = element.querySelector('.callNumber').textContent
|
||||||
console.log('TAPI call notification', number)
|
console.log('TAPI call notification', number)
|
||||||
|
|
||||||
number = extractNumber(number)
|
number = extractNumber(number)
|
0
src/js/decs.d.ts → src/decs.d.ts
vendored
0
src/js/decs.d.ts → src/decs.d.ts
vendored
@ -3,12 +3,13 @@ import * as chrono from 'chrono-node'
|
|||||||
import { CallHistory } from './call-history'
|
import { CallHistory } from './call-history'
|
||||||
import { CallNotification } from './call-notification'
|
import { CallNotification } from './call-notification'
|
||||||
import { Search } from './search'
|
import { Search } from './search'
|
||||||
|
import { Status } from './status'
|
||||||
|
|
||||||
console.log('script start')
|
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('div.nav-search', (element) => { search.createSearchWindow(element) }, true)
|
waitForKeyElements('ongoing-call-button', (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
|
||||||
@ -17,3 +18,7 @@ waitForKeyElements('call-view', (element) => { callNotification.showCallNotifica
|
|||||||
const callHistory = new CallHistory()
|
const callHistory = new CallHistory()
|
||||||
// eslint-disable-next-line no-undef
|
// eslint-disable-next-line no-undef
|
||||||
waitForKeyElements('.call-history-list call', (element) => { callHistory.showCallHistory(element) }, false)
|
waitForKeyElements('.call-history-list call', (element) => { callHistory.showCallHistory(element) }, false)
|
||||||
|
|
||||||
|
const status = new Status()
|
||||||
|
// eslint-disable-next-line no-undef
|
||||||
|
waitForKeyElements('wc-account-menu', (element) => { status.showStatus(element) }, false)
|
@ -1,33 +0,0 @@
|
|||||||
/**
|
|
||||||
* @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) {
|
|
||||||
var match = /(\+?[0-9]{4,})/.exec(s)
|
|
||||||
if (!match) {
|
|
||||||
return undefined
|
|
||||||
}
|
|
||||||
|
|
||||||
var number = match[1]
|
|
||||||
if (number.startsWith('+')) {
|
|
||||||
number = number.replace('+', '00')
|
|
||||||
}
|
|
||||||
|
|
||||||
return number
|
|
||||||
}
|
|
9
src/search.css
Normal file
9
src/search.css
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
.tapi-search-result {
|
||||||
|
color: #000;
|
||||||
|
padding: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tapi-search-result:hover, .tapi-search-result-selected {
|
||||||
|
background-color: #E7E6E6;
|
||||||
|
}
|
||||||
|
|
@ -1,6 +1,7 @@
|
|||||||
|
import './search.css'
|
||||||
import { TapiContact } from './tapi-contact'
|
import { TapiContact } from './tapi-contact'
|
||||||
import { debounce } from './debounce'
|
import { debounce } from './debounce'
|
||||||
import { axios } from './utils'
|
import { axios, fireChangeEvents } from './utils'
|
||||||
|
|
||||||
export class Search {
|
export class Search {
|
||||||
private currentSearchText = ''
|
private currentSearchText = ''
|
||||||
@ -19,6 +20,8 @@ export class Search {
|
|||||||
}
|
}
|
||||||
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
|
||||||
@ -61,7 +64,7 @@ export class Search {
|
|||||||
icon.style.color = 'grey'
|
icon.style.color = 'grey'
|
||||||
searchWrapper.appendChild(icon)
|
searchWrapper.appendChild(icon)
|
||||||
|
|
||||||
element.appendChild(form)
|
element.parentElement.insertBefore(form, element)
|
||||||
}
|
}
|
||||||
|
|
||||||
private removeSearchResults () {
|
private removeSearchResults () {
|
||||||
@ -135,7 +138,6 @@ export class Search {
|
|||||||
contacts.forEach(contact => {
|
contacts.forEach(contact => {
|
||||||
var li = document.createElement('li')
|
var li = document.createElement('li')
|
||||||
li.classList.add('tapi-search-result')
|
li.classList.add('tapi-search-result')
|
||||||
li.classList.add('search-result')
|
|
||||||
li.classList.add('pointer')
|
li.classList.add('pointer')
|
||||||
li.onmouseover = () => { this.selectResult(li) }
|
li.onmouseover = () => { this.selectResult(li) }
|
||||||
li.dataset.tapiNumber = contact.tD_NUMBER_TAPI
|
li.dataset.tapiNumber = contact.tD_NUMBER_TAPI
|
||||||
@ -161,37 +163,22 @@ export class Search {
|
|||||||
private selectResult (resultLi: Element) {
|
private selectResult (resultLi: Element) {
|
||||||
var items = document.getElementsByClassName('tapi-search-result')
|
var items = document.getElementsByClassName('tapi-search-result')
|
||||||
for (var item of items) {
|
for (var item of items) {
|
||||||
item.classList.remove('bg-light')
|
|
||||||
item.classList.remove('tapi-search-result-selected')
|
item.classList.remove('tapi-search-result-selected')
|
||||||
}
|
}
|
||||||
|
|
||||||
resultLi.classList.add('bg-light')
|
|
||||||
resultLi.classList.add('tapi-search-result-selected')
|
resultLi.classList.add('tapi-search-result-selected')
|
||||||
}
|
}
|
||||||
|
|
||||||
private dial (number: string) {
|
private dial (number: string) {
|
||||||
var searchInput = document.getElementsByName('searchByNumberInput')
|
console.log('TAPI Search dialing', number);
|
||||||
if (searchInput.length > 0) {
|
var searchInput = document.getElementById('dialpad-input');
|
||||||
(<HTMLInputElement>searchInput[0]).value = number
|
(<HTMLInputElement>searchInput).value = number;
|
||||||
searchInput[0].focus()
|
(<HTMLInputElement>searchInput).focus;
|
||||||
|
fireChangeEvents(searchInput);
|
||||||
|
|
||||||
this.fireChangeEvents(searchInput[0])
|
var toaster = document.querySelector('toaster-container');
|
||||||
|
if (window.getComputedStyle(toaster, null).display == 'none') {
|
||||||
|
document.getElementById('menuDialer').click();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fireChangeEvents (element: Element) {
|
|
||||||
var changeEvent = null
|
|
||||||
changeEvent = document.createEvent('HTMLEvents')
|
|
||||||
changeEvent.initEvent('input', true, true)
|
|
||||||
element.dispatchEvent(changeEvent)
|
|
||||||
console.debug('input event dispatched for element: ' + element.id)
|
|
||||||
changeEvent = document.createEvent('HTMLEvents')
|
|
||||||
changeEvent.initEvent('keyup', true, true)
|
|
||||||
element.dispatchEvent(changeEvent)
|
|
||||||
console.debug('keyup event dispatched for element: ' + element.id)
|
|
||||||
changeEvent = document.createEvent('HTMLEvents')
|
|
||||||
changeEvent.initEvent('change', true, true)
|
|
||||||
element.dispatchEvent(changeEvent)
|
|
||||||
console.debug('change event dispatched for element: ' + element.id)
|
|
||||||
}
|
|
||||||
}
|
}
|
19
src/status.css
Normal file
19
src/status.css
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
.tapi-dropdown {
|
||||||
|
position: relative;
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tapi-dropdown-content {
|
||||||
|
display: none;
|
||||||
|
position: absolute;
|
||||||
|
min-width: 200px;
|
||||||
|
overflow: auto;
|
||||||
|
box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2);
|
||||||
|
z-index: 1;
|
||||||
|
color: #000;
|
||||||
|
background-color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.show {
|
||||||
|
display: block;
|
||||||
|
}
|
157
src/status.ts
Normal file
157
src/status.ts
Normal file
@ -0,0 +1,157 @@
|
|||||||
|
import './status.css';
|
||||||
|
import { axios } from './utils';
|
||||||
|
import { ZcStatus } from './zc-status';
|
||||||
|
|
||||||
|
declare function waitForKeyElements(selectorOrFunction: any, callback: any, waitOnce: boolean): any;
|
||||||
|
|
||||||
|
export class Status {
|
||||||
|
private _user: string;
|
||||||
|
private _enabled = false;
|
||||||
|
private _statusOn = 'menuAvailable';
|
||||||
|
private _statusOff = 'menuAway';
|
||||||
|
private _currentStatus: boolean = undefined;
|
||||||
|
|
||||||
|
public async showStatus(element: HTMLElement) {
|
||||||
|
this._user = await GM.getValue('tapi-zc-user', '');
|
||||||
|
this._enabled = await GM.getValue('tapi-zc-enabled', false);
|
||||||
|
this._statusOn = await GM.getValue('tapi-zc-on', '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);
|
||||||
|
|
||||||
|
this.checkStatus();
|
||||||
|
|
||||||
|
waitForKeyElements("wc-account-menu > div > ul", (element: HTMLElement) => { this.addZcStatusPopup(element) }, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
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.getElementsByTagName("wcavatar")[0] as HTMLAnchorElement).click();
|
||||||
|
setTimeout(() => {
|
||||||
|
var statusId = this._currentStatus ? this._statusOn : this._statusOff;
|
||||||
|
(document.getElementById(statusId) as HTMLSpanElement).click();
|
||||||
|
}, 1000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error);
|
||||||
|
}
|
||||||
|
setTimeout(() => this.checkStatus(), 30000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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 =
|
||||||
|
'<div role="document" class="modal-dialog">' +
|
||||||
|
' <div class="modal-content">' +
|
||||||
|
' <div class="modal-header">' +
|
||||||
|
' <h4 class="modal-title float-left">ZeitConsens Status</h4><button id="zc-btnClose" type="button" aria-label="Close" class="close float-right"><span aria-hidden="true">×</span></button>' +
|
||||||
|
' </div>' +
|
||||||
|
' <div class="modal-body">' +
|
||||||
|
' <div class="form-group">' +
|
||||||
|
' <label for="tapi-zc-user">Username</label>' +
|
||||||
|
' <input type="text" class="form-control" name="tapi-zc-user" id="tapi-zc-user">' +
|
||||||
|
' </div>' +
|
||||||
|
' <div class="form-group">' +
|
||||||
|
' <label for="tapi-zc-on">Signed in</label>' +
|
||||||
|
' <select id="tapi-zc-on" class="form-control">' +
|
||||||
|
' <option value="menuAvailable">Available</option>' +
|
||||||
|
' <option value="menuOutofoffice">Do Not Disturb</option>' +
|
||||||
|
' <option value="menuCustom1">Verfügbar DW</option>' +
|
||||||
|
' </select>' +
|
||||||
|
' </div>' +
|
||||||
|
' <div class="form-group">' +
|
||||||
|
' <label for="tapi-zc-off">Signed out</label>' +
|
||||||
|
' <select id="tapi-zc-off" class="form-control">' +
|
||||||
|
' <option value="menuAway">Away</option>' +
|
||||||
|
' <option value="menuOutofoffice">Do Not Disturb</option>' +
|
||||||
|
' </select>' +
|
||||||
|
' </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">OK </button>' +
|
||||||
|
' <button id="zc-btnCancel" type="button" class="btn btn-light">Cancel </button>' +
|
||||||
|
' </div>' +
|
||||||
|
' </div>' +
|
||||||
|
'</div>';
|
||||||
|
var modal = document.createElement('modal-container');
|
||||||
|
modal.id = 'zc-modal';
|
||||||
|
modal.classList.add('modal');
|
||||||
|
modal.classList.add('fade');
|
||||||
|
modal.innerHTML = html;
|
||||||
|
var body = document.getElementsByTagName('body')[0].appendChild(modal);
|
||||||
|
|
||||||
|
var btnClose = document.getElementById('zc-btnClose');
|
||||||
|
btnClose.onclick = () => {
|
||||||
|
document.getElementById('zc-modal').classList.toggle('show');
|
||||||
|
}
|
||||||
|
|
||||||
|
var zcUser = document.getElementById('tapi-zc-user') as HTMLInputElement;
|
||||||
|
zcUser.value = this._user;
|
||||||
|
zcUser.onchange = () => {
|
||||||
|
this._user = zcUser.value;
|
||||||
|
GM.setValue('tapi-zc-user', this._user);
|
||||||
|
console.log('tapi-zc-user', this._user);
|
||||||
|
this._currentStatus = undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
var zcEnabled = document.getElementById('tapi-zc-enabled') as HTMLInputElement;
|
||||||
|
zcEnabled.checked = this._enabled;
|
||||||
|
zcEnabled.onchange = () => {
|
||||||
|
this._enabled = zcEnabled.checked;
|
||||||
|
GM.setValue('tapi-zc-enabled', this._enabled);
|
||||||
|
console.log('tapi-zc-enabled', this._enabled);
|
||||||
|
this._currentStatus = undefined;
|
||||||
|
this.checkStatus();
|
||||||
|
}
|
||||||
|
|
||||||
|
var zcOn = document.getElementById('tapi-zc-on') as HTMLSelectElement;
|
||||||
|
zcOn.value = this._statusOn;
|
||||||
|
zcOn.onchange = () => {
|
||||||
|
this._statusOn = zcOn.value;
|
||||||
|
GM.setValue('tapi-zc-on', this._statusOn);
|
||||||
|
console.log('tapi-zc-on', this._statusOn);
|
||||||
|
this._currentStatus = undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
var zcOff = document.getElementById('tapi-zc-off') as HTMLSelectElement;
|
||||||
|
zcOff.value = this._statusOff;
|
||||||
|
zcOff.onchange = () => {
|
||||||
|
this._statusOff = zcOff.value;
|
||||||
|
GM.setValue('tapi-zc-off', this._statusOff);
|
||||||
|
console.log('tapi-zc-off', this._statusOff);
|
||||||
|
this._currentStatus = undefined;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
49
src/utils.ts
Normal file
49
src/utils.ts
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
/**
|
||||||
|
* @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) {
|
||||||
|
var match = /(\+?[0-9]{4,})/.exec(s)
|
||||||
|
if (!match) {
|
||||||
|
return undefined
|
||||||
|
}
|
||||||
|
|
||||||
|
var number = match[1]
|
||||||
|
if (number.startsWith('+')) {
|
||||||
|
number = number.replace('+', '00')
|
||||||
|
}
|
||||||
|
|
||||||
|
return number
|
||||||
|
}
|
||||||
|
|
||||||
|
export function fireChangeEvents (element: Element) {
|
||||||
|
var changeEvent = null
|
||||||
|
changeEvent = document.createEvent('HTMLEvents')
|
||||||
|
changeEvent.initEvent('input', true, true)
|
||||||
|
element.dispatchEvent(changeEvent)
|
||||||
|
console.debug('input event dispatched for element: ' + element.id)
|
||||||
|
changeEvent = document.createEvent('HTMLEvents')
|
||||||
|
changeEvent.initEvent('keyup', true, true)
|
||||||
|
element.dispatchEvent(changeEvent)
|
||||||
|
console.debug('keyup event dispatched for element: ' + element.id)
|
||||||
|
changeEvent = document.createEvent('HTMLEvents')
|
||||||
|
changeEvent.initEvent('change', true, true)
|
||||||
|
element.dispatchEvent(changeEvent)
|
||||||
|
console.debug('change event dispatched for element: ' + element.id)
|
||||||
|
}
|
4
src/zc-status.ts
Normal file
4
src/zc-status.ts
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
export class ZcStatus {
|
||||||
|
public user: string;
|
||||||
|
public loggedIn: boolean;
|
||||||
|
}
|
Reference in New Issue
Block a user