Compare commits
	
		
			11 Commits
		
	
	
		
			v7.0.0
			...
			3e33155276
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 3e33155276 | |||
| de34a6c66e | |||
| a4a346b48d | |||
| cd303869c8 | |||
| 4283ee6b5c | |||
|   | fec9885a64 | ||
|   | 29fc426161 | ||
|   | 231d24b26a | ||
|   | f3693162ab | ||
|   | c09bdd856b | ||
|   | ecb9097f5f | 
							
								
								
									
										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 | ||||
							
								
								
									
										13293
									
								
								3CX_TAPI.user.js
									
									
									
									
									
								
							
							
						
						
									
										13293
									
								
								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', | ||||
|   version: pkg.version, | ||||
|   author: pkg.author, | ||||
|   copyright: 'Copyright 2020 CP Solutions GmbH', | ||||
|   copyright: 'Copyright 2021 CP Solutions GmbH', | ||||
|   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: [ | ||||
|     'https://192.168.0.154: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` | ||||
|   ], | ||||
|   grant: [ | ||||
|     'GM_xmlhttpRequest', | ||||
|     'GM.notification' | ||||
|     'GM.xmlHttpRequest', | ||||
|     'GM.notification', | ||||
|     'GM.getValue', | ||||
|     'GM.setValue' | ||||
|   ], | ||||
|   connect: [ | ||||
|     'cpatapi.cpsrvweb2016.cp-austria.at' | ||||
| @@ -1,42 +1,38 @@ | ||||
| const path = require('path') | ||||
| const webpack = require('webpack') | ||||
| const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer') | ||||
| 
 | ||||
| const webpackConfig = { | ||||
|   node: { | ||||
|     Buffer: false | ||||
|   }, | ||||
|   resolve: { | ||||
|     extensions: ['.js', '.ts'] | ||||
|   }, | ||||
|   // performance: {
 | ||||
|   // hints: false
 | ||||
|   // },
 | ||||
|   optimization: { | ||||
|     minimize: false | ||||
|     minimize: false, | ||||
|     moduleIds: 'named', | ||||
|   }, | ||||
|   entry: './src/js/index.js', | ||||
|   entry: './src/index.js', | ||||
|   output: { | ||||
|     path: path.resolve(__dirname, '../dist') | ||||
|   }, | ||||
|   externals: { | ||||
|     jquery: '$', | ||||
|     axios: 'axios', | ||||
|     'axios-userscript-adapter': 'axiosGmxhrAdapter' | ||||
|   }, | ||||
|   module: { | ||||
|     rules: [ | ||||
|       { | ||||
|         use: { | ||||
|           loader: 'babel-loader', | ||||
|         }, | ||||
|         test: /\.js$/, | ||||
|         exclude: /node_modules/, | ||||
|         loader: 'eslint-loader' | ||||
|       }, | ||||
|       { | ||||
|         test: /\.ts$/, | ||||
|         exclude: /node_modules/, | ||||
|         loader: 'ts-loader' | ||||
|       }, | ||||
|       { | ||||
|         test: /\.less$/, | ||||
|         loader: [ | ||||
|         use: [ | ||||
|           'style-loader', | ||||
|           'css-loader', | ||||
|           'less-loader', // 将 Less 编译为 CSS
 | ||||
| @@ -44,16 +40,14 @@ const webpackConfig = { | ||||
|       }, | ||||
|       { | ||||
|         test: /\.css$/, | ||||
|         loader: [ | ||||
|         use: [ | ||||
|           'style-loader', | ||||
|           'css-loader', | ||||
|         ] | ||||
|       } | ||||
|     ] | ||||
|   }, | ||||
|   plugins: [ | ||||
|     new webpack.HashedModuleIdsPlugin() | ||||
|   ] | ||||
|   plugins: process.env.npm_config_report ? [new BundleAnalyzerPlugin()] : [], | ||||
| } | ||||
| 
 | ||||
| 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
											
										
									
								
							
							
								
								
									
										68
									
								
								package.json
									
									
									
									
									
								
							
							
						
						
									
										68
									
								
								package.json
									
									
									
									
									
								
							| @@ -1,59 +1,57 @@ | ||||
| { | ||||
|   "name": "3cp-tapi", | ||||
|   "description": "Build your UserScript with webpack", | ||||
|   "version": "7.0.0", | ||||
|   "version": "8.0.0", | ||||
|   "author": { | ||||
|     "name": "Daniel Triendl", | ||||
|     "email": "d.triendl@cp-solutions.at" | ||||
|   }, | ||||
|   "browserslist": [ | ||||
|     "last 2 version", | ||||
|     "> 1%" | ||||
|   ], | ||||
|   "eslintIgnore": [ | ||||
|     "dist/*.js" | ||||
|     "dist/*.js", | ||||
|     "node_modules" | ||||
|   ], | ||||
|   "scripts": { | ||||
|     "lint": "eslint src", | ||||
|     "lint": "eslint --ext .ts,.js src", | ||||
|     "preversion": "npm run lint", | ||||
|     "postversion": "git push --follow-tags", | ||||
|     "anylize": "npm_config_report=true npm run build", | ||||
|     "build": "webpack --mode production --config config/webpack.config.production.js", | ||||
|     "dev": "webpack --mode development --config config/webpack.config.dev.js" | ||||
|     "build": "webpack --mode production --config config/webpack.config.production.cjs", | ||||
|     "dev": "webpack --mode development --config config/webpack.config.dev.cjs" | ||||
|   }, | ||||
|   "repository": { | ||||
|     "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, | ||||
|   "dependencies": { | ||||
|     "axios": "0.20.0", | ||||
|     "axios-userscript-adapter": "0.0.7", | ||||
|     "chrono-node": "2.1.9", | ||||
|     "jquery": "3.5.1" | ||||
|     "axios": "0.21.1", | ||||
|     "axios-userscript-adapter": "0.1.4", | ||||
|     "chrono-node": "^2.3.0" | ||||
|   }, | ||||
|   "devDependencies": { | ||||
|     "@typescript-eslint/eslint-plugin": "4.3.0", | ||||
|     "@typescript-eslint/parser": "4.3.0", | ||||
|     "css-loader": "4.3.0", | ||||
|     "eslint": "7.10.0", | ||||
|     "eslint-config-standard": "14.1.1", | ||||
|     "eslint-loader": "4.0.2", | ||||
|     "eslint-plugin-import": "2.22.1", | ||||
|     "@babel/core": "7.14.6", | ||||
|     "@babel/preset-env": "7.14.5", | ||||
|     "@typescript-eslint/eslint-plugin": "4.27.0", | ||||
|     "@typescript-eslint/parser": "4.27.0", | ||||
|     "babel-loader": "8.2.2", | ||||
|     "browserslist": "4.16.6", | ||||
|     "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-promise": "4.2.1", | ||||
|     "eslint-plugin-standard": "4.0.1", | ||||
|     "less": "3.12.2", | ||||
|     "less-loader": "7.0.1", | ||||
|     "style-loader": "1.2.1", | ||||
|     "ts-loader": "8.0.4", | ||||
|     "typescript": "4.0.3", | ||||
|     "userscript-metadata-webpack-plugin": "0.0.6", | ||||
|     "webpack": "4.44.2", | ||||
|     "webpack-bundle-analyzer": "3.9.0", | ||||
|     "webpack-cli": "3.3.12", | ||||
|     "webpack-dev-server": "^3.11.0", | ||||
|     "webpack-livereload-plugin": "2.3.0", | ||||
|     "webpack-merge": "5.1.4" | ||||
|     "eslint-plugin-promise": "5.1.0", | ||||
|     "eslint-plugin-standard": "4.1.0", | ||||
|     "less": "4.1.1", | ||||
|     "less-loader": "10.0.0", | ||||
|     "style-loader": "2.0.0", | ||||
|     "ts-loader": "9.2.3", | ||||
|     "typescript": "4.3.4", | ||||
|     "userscript-metadata-webpack-plugin": "0.1.0", | ||||
|     "webpack": "5.39.1", | ||||
|     "webpack-bundle-analyzer": "4.4.2", | ||||
|     "webpack-cli": "4.7.2", | ||||
|     "webpack-livereload-plugin": "3.0.1", | ||||
|     "webpack-merge": "5.8.0" | ||||
|   } | ||||
| } | ||||
|   | ||||
| @@ -43,11 +43,11 @@ npm run build | ||||
| ## 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 | ||||
|  | ||||
| ## see also | ||||
|  | ||||
| Based on [webpack-userscript-template](https://github.com/Trim21/webpack-userscript-template/. | ||||
| Based on [webpack-userscript-template](https://github.com/Trim21/webpack-userscript-template/) | ||||
|   | ||||
| @@ -6,11 +6,10 @@ export class CallHistory { | ||||
|   private callerIds: { [number: string]: TapiContact } = {} | ||||
| 
 | ||||
|   private updateCallHistoryEntry (call: HTMLElement, callerId: TapiContact) { | ||||
|     if (callerId.tD_NAME !== '') { | ||||
|       var span = call.querySelector('span') | ||||
| 
 | ||||
|       this.showTimeManager(call, span.nextSibling.textContent, callerId) | ||||
|     var span = call.querySelector('span') | ||||
|     this.showTimeManager(call, span.nextSibling.textContent.trim(), callerId) | ||||
| 
 | ||||
|     if (callerId && callerId.tD_NAME !== '') { | ||||
|       var text = span.textContent | ||||
|       span.textContent = callerId.tD_NAME | ||||
|       var br = document.createElement('br') | ||||
| @@ -22,40 +21,43 @@ export class CallHistory { | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   private showTimeManager (call: HTMLElement, time: string, callerId: TapiContact) { | ||||
|     if (!callerId.tD_ID) { | ||||
|       return | ||||
|   private showTimeManager (call: HTMLElement, date: string, callerId: TapiContact) { | ||||
|     var dateParts = date.match(/^(?<date>.*), (?<duration>[0-9]{2}:[0-9]{2}:[0-9]{2})$/) | ||||
|     var duration = '00:00:00' | ||||
|     if (dateParts) { | ||||
|       date = dateParts.groups.date | ||||
|       duration = dateParts.groups.duration | ||||
|     } | ||||
| 
 | ||||
|     var timeParts = time.split(/, /) | ||||
|     var duration = '00:00:00' | ||||
|     if (timeParts.length >= 1) { | ||||
|       time = timeParts[0] | ||||
|     } | ||||
|     if (timeParts.length >= 2) { | ||||
|       duration = timeParts[1] | ||||
|     } | ||||
|     var parsedDate = chrono.de.parseDate(time) | ||||
|     var parsedDate = chrono.de.parseDate(date) | ||||
|     if (!parsedDate) { | ||||
|       parsedDate = chrono.parseDate(time) | ||||
|       parsedDate = chrono.parseDate(date) | ||||
|     } | ||||
|     if (!parsedDate) { | ||||
|       return | ||||
|     } | ||||
|     // Date parsing is awful, just assume the first number is the day of month
 | ||||
|     var day = date.match(/[0-9]+/)[0] | ||||
| 
 | ||||
|     var parsedDuration = chrono.parseDate(duration) | ||||
|     console.log('TAPI call history time:', time, 'parsedDate:', parsedDate, 'duration:', duration, 'parsedDuration:', parsedDuration) | ||||
|     console.log('TAPI call history time:', date, 'parsedDate:', parsedDate, 'duration:', duration, 'parsedDuration:', parsedDuration) | ||||
| 
 | ||||
|     var connect = parsedDate.getFullYear().toString() + | ||||
|       (parsedDate.getMonth() + 1).toString().padStart(2, '0') + // (January gives 0)
 | ||||
|       parsedDate.getDate().toString().padStart(2, '0') + | ||||
|       day.toString().padStart(2, '0') + | ||||
|       parsedDate.getHours().toString().padStart(2, '0') + | ||||
|       parsedDate.getMinutes().toString().padStart(2, '0') | ||||
| 
 | ||||
|     var length = (parsedDuration.getHours() * 60 + parsedDuration.getMinutes()).toString() | ||||
| 
 | ||||
|     var toolbar = call.querySelector('.wcToolbarTiles') | ||||
|     var href = 'domizil://PM/Zeitbuchung?' | ||||
|     if (callerId && callerId.tD_ID) { | ||||
|       href += 'KontaktId=' + callerId.tD_ID + '&' | ||||
|     } | ||||
|     href += 'connect=' + connect + '&length=' + length | ||||
|     var a = document.createElement('a') | ||||
|     var href = 'domizil://PM/Zeitbuchung?KontaktId=' + callerId.tD_ID + '&connect=' + connect + '&length=' + length | ||||
|     a.title = 'PM Zeitbuchung' | ||||
|     a.dataset.domizilLink = href | ||||
|     a.onclick = () => { | ||||
|       window.open(href) | ||||
| @@ -79,6 +81,7 @@ export class CallHistory { | ||||
|     var span = element.querySelector('span') | ||||
|     var number = extractNumber(span.textContent) | ||||
|     if (!number) { | ||||
|       this.updateCallHistoryEntry(element, undefined) | ||||
|       return | ||||
|     } | ||||
| 
 | ||||
| @@ -21,7 +21,7 @@ export class CallNotification { | ||||
|     if (response.status === 200) { | ||||
|       var callerId = response.data | ||||
|       if (callerId) { | ||||
|         notification.text = callerId.tD_NAME + '\r\n' + number | ||||
|         notification.text = callerId.tD_NAME + '\r\n' + number + ' (' + callerId.tD_MEDIUM + ')' | ||||
|       } | ||||
|     } | ||||
| 
 | ||||
							
								
								
									
										0
									
								
								src/js/decs.d.ts → src/decs.d.ts
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										0
									
								
								src/js/decs.d.ts → src/decs.d.ts
									
									
									
									
										vendored
									
									
								
							| @@ -3,6 +3,7 @@ import * as chrono from 'chrono-node' | ||||
| import { CallHistory } from './call-history' | ||||
| import { CallNotification } from './call-notification' | ||||
| import { Search } from './search' | ||||
| import { Status } from './status' | ||||
| 
 | ||||
| console.log('script start') | ||||
| 
 | ||||
| @@ -17,3 +18,7 @@ waitForKeyElements('call-view', (element) => { callNotification.showCallNotifica | ||||
| const callHistory = new CallHistory() | ||||
| // eslint-disable-next-line no-undef
 | ||||
| waitForKeyElements('.call-history-list call', (element) => { callHistory.showCallHistory(element) }, false) | ||||
| 
 | ||||
| const status = new Status() | ||||
| // eslint-disable-next-line no-undef
 | ||||
| waitForKeyElements('#status-change', (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]+)/.exec(s) | ||||
|   if (!match) { | ||||
|     return undefined | ||||
|   } | ||||
|  | ||||
|   var number = match[1] | ||||
|   if (number.startsWith('+')) { | ||||
|     number = number.replace('+', '00') | ||||
|   } | ||||
|  | ||||
|   return number | ||||
| } | ||||
| @@ -1,6 +1,6 @@ | ||||
| import { TapiContact } from './tapi-contact' | ||||
| import { debounce } from './debounce' | ||||
| import { axios } from './utils' | ||||
| import { axios, fireChangeEvents } from './utils' | ||||
| 
 | ||||
| export class Search { | ||||
|   private currentSearchText = '' | ||||
| @@ -13,7 +13,10 @@ export class Search { | ||||
|     form.style.float = 'right' | ||||
|     form.style.marginRight = '20px' | ||||
|     form.onsubmit = () => { | ||||
|       var items = document.getElementsByClassName('tapi-search-result') | ||||
|       var items = document.getElementsByClassName('tapi-search-result-selected') | ||||
|       if (items.length === 0) { | ||||
|         items = document.getElementsByClassName('tapi-search-result') | ||||
|       } | ||||
|       if (items.length > 0) { | ||||
|         this.dial((<HTMLElement>items[0]).dataset.tapiNumber) | ||||
|       } | ||||
| @@ -148,7 +151,7 @@ export class Search { | ||||
|       resultText.appendChild(line1) | ||||
| 
 | ||||
|       var line2 = document.createElement('div') | ||||
|       line2.appendChild(document.createTextNode(contact.tD_NUMBER_TAPI)) | ||||
|       line2.appendChild(document.createTextNode(contact.tD_MEDIUM + ': ' + contact.tD_NUMBER_TAPI)) | ||||
|       resultText.appendChild(line2) | ||||
| 
 | ||||
|       resultList.appendChild(li) | ||||
| @@ -172,23 +175,7 @@ export class Search { | ||||
|       (<HTMLInputElement>searchInput[0]).value = number | ||||
|       searchInput[0].focus() | ||||
| 
 | ||||
|       this.fireChangeEvents(searchInput[0]) | ||||
|       fireChangeEvents(searchInput[0]) | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   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; | ||||
| } | ||||
							
								
								
									
										133
									
								
								src/status.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										133
									
								
								src/status.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,133 @@ | ||||
| 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); | ||||
|  | ||||
|     var div = document.createElement('div'); | ||||
|     div.classList.add('tapi-dropdown'); | ||||
|  | ||||
|     var button = document.createElement('button'); | ||||
|     button.id = 'tapi-zc-button'; | ||||
|     button.classList.add('btn'); | ||||
|     button.classList.add('btn-default'); | ||||
|     button.innerText = 'ZeitConsens'; | ||||
|     button.onclick = () => { | ||||
|       document.getElementById('tapi-zc-dropdown').classList.toggle('show'); | ||||
|     } | ||||
|     div.appendChild(button); | ||||
|  | ||||
|     var html = | ||||
|       '<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 in</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>'; | ||||
|  | ||||
|     var dropdown = document.createElement('div'); | ||||
|     dropdown.classList.add('tapi-dropdown-content'); | ||||
|     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; | ||||
|     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; | ||||
|     } | ||||
|  | ||||
|     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); | ||||
|     } | ||||
|   } | ||||
| } | ||||
| @@ -4,4 +4,5 @@ export interface TapiContact { | ||||
|   tD_NAME: string; | ||||
|   tD_NUMBER?: string; | ||||
|   tD_NUMBER_TAPI?: string; | ||||
|   tD_MEDIUM?: string; | ||||
| } | ||||
							
								
								
									
										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