9 Commits

9 changed files with 7994 additions and 16029 deletions

File diff suppressed because it is too large Load Diff

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')

11846
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,7 @@
{ {
"name": "3cx-tapi", "name": "3cx-tapi",
"description": "3CX CP Tapi and Projectmanager integration", "description": "3CX CP Tapi and Projectmanager integration",
"version": "9.0.0", "version": "9.1.0",
"author": { "author": {
"name": "Daniel Triendl", "name": "Daniel Triendl",
"email": "d.triendl@cp-solutions.at" "email": "d.triendl@cp-solutions.at"
@ -24,34 +24,33 @@
}, },
"private": true, "private": true,
"dependencies": { "dependencies": {
"axios": "0.21.1", "axios": "^1.4.0",
"axios-userscript-adapter": "0.1.4", "axios-userscript-adapter": "^0.2.0-alpha.2",
"chrono-node": "^2.3.0" "chrono-node": "^2.6.3"
}, },
"devDependencies": { "devDependencies": {
"@babel/core": "7.14.6", "@babel/core": "^7.22.5",
"@babel/preset-env": "7.14.5", "@babel/preset-env": "^7.22.5",
"@typescript-eslint/eslint-plugin": "4.27.0", "@typescript-eslint/eslint-plugin": "^5.60.1",
"@typescript-eslint/parser": "4.27.0", "@typescript-eslint/parser": "^5.60.1",
"babel-loader": "8.2.2", "babel-loader": "^9.1.2",
"browserslist": "4.16.6", "browserslist": "^4.21.9",
"css-loader": "5.2.6", "css-loader": "^6.8.1",
"eslint": "7.29.0", "eslint": "^8.43.0",
"eslint-config-standard": "16.0.3", "eslint-config-standard": "^17.1.0",
"eslint-plugin-import": "2.23.4", "eslint-plugin-import": "^2.27.5",
"eslint-plugin-node": "11.1.0", "eslint-plugin-node": "11.1.0",
"eslint-plugin-promise": "5.1.0", "eslint-plugin-promise": "^6.1.1",
"eslint-plugin-standard": "4.1.0", "less": "4.1.3",
"less": "4.1.1", "less-loader": "^11.1.3",
"less-loader": "10.0.0", "style-loader": "^3.3.3",
"style-loader": "2.0.0", "ts-loader": "^9.4.3",
"ts-loader": "9.2.3", "typescript": "^5.1.3",
"typescript": "4.3.4", "userscript-metadata-webpack-plugin": "^0.4.0",
"userscript-metadata-webpack-plugin": "0.1.0", "webpack": "^5.88.0",
"webpack": "5.39.1", "webpack-bundle-analyzer": "^4.9.0",
"webpack-bundle-analyzer": "4.4.2", "webpack-cli": "^5.1.4",
"webpack-cli": "4.7.2", "webpack-livereload-plugin": "3.0.2",
"webpack-livereload-plugin": "3.0.1", "webpack-merge": "^5.9.0"
"webpack-merge": "5.8.0"
} }
} }

View File

@ -22,9 +22,10 @@ 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.parseDate(date)
if (!parsedDate) { var parsedDateDe = chrono.de.parseDate(date)
parsedDate = chrono.parseDate(date) if (parsedDateDe) {
parsedDate = parsedDateDe
} }
if (!parsedDate) { if (!parsedDate) {
return return

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) }, true) waitForKeyElements('ongoing-call-button', (element) => { search.createSearchWindow(element) }, false)
const callNotification = new CallNotification() const callNotification = new CallNotification()
// eslint-disable-next-line no-undef // eslint-disable-next-line no-undef

39
src/search.css Normal file
View File

@ -0,0 +1,39 @@
.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:hover, .tapi-search-autocomplete-active {
/*when hovering an item:*/
background-color: #E7E6E6 !important;
}

View File

@ -1,3 +1,4 @@
import './search.css'
import { TapiContact } from './tapi-contact' import { TapiContact } from './tapi-contact'
import { debounce } from './debounce' import { debounce } from './debounce'
import { axios, fireChangeEvents } from './utils' import { axios, fireChangeEvents } from './utils'
@ -9,39 +10,29 @@ 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-result-selected') var items = document.getElementsByClassName('tapi-search-autocomplete-active')
if (items.length === 0) { if (items.length === 0) {
items = document.getElementsByClassName('tapi-search-result') items = document.getElementsByClassName('tapi-search-autocomplete-item')
} }
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('contact-search-box') searchBox.classList.add('tapi-search-autocomplete')
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) }
@ -50,22 +41,15 @@ export class Search {
setTimeout(() => { setTimeout(() => {
console.log('TAPI clear search results') console.log('TAPI clear search results')
this.removeSearchResults() this.removeSearchResults()
}, 500) }, 250)
} }
searchWrapper.appendChild(search) searchBox.appendChild(search)
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.parentElement.insertBefore(form, element) element.parentElement.insertBefore(form, element)
} }
private removeSearchResults () { private removeSearchResults () {
var resultList = document.getElementById('tapiResults') var resultList = document.getElementById('tapi-search-autocomplete-list')
if (resultList) { if (resultList) {
resultList.parentNode.removeChild(resultList) resultList.parentNode.removeChild(resultList)
} }
@ -74,12 +58,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-result-selected') let items = document.getElementsByClassName('tapi-search-autocomplete-active')
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-result') items = document.getElementsByClassName('tapi-search-autocomplete-item')
if (items.length > 0) { if (items.length > 0) {
prev = items[items.length - 1] prev = items[items.length - 1]
} }
@ -89,12 +73,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-result-selected') let items = document.getElementsByClassName('tapi-search-autocomplete-active')
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-result') items = document.getElementsByClassName('tapi-search-autocomplete-item')
if (items.length > 0) { if (items.length > 0) {
next = items[0] next = items[0]
} }
@ -125,48 +109,31 @@ export class Search {
this.removeSearchResults() this.removeSearchResults()
this.currentSearchText = searchText this.currentSearchText = searchText
var resultList = document.createElement('ul') var results = document.createElement('div');
resultList.id = 'tapiResults' results.setAttribute('id', 'tapi-search-autocomplete-list')
resultList.classList.add('search-nav-absolute') results.setAttribute('class', 'tapi-search-autocomplete-items')
resultList.classList.add('search-nav-ul') document.getElementById('tapiSearchBox').appendChild(results)
document.getElementById('tapiSearchBox').appendChild(resultList)
resultList.innerHTML = ''
contacts.forEach(contact => { contacts.forEach(contact => {
var li = document.createElement('li') var item = document.createElement('div');
li.classList.add('tapi-search-result') item.setAttribute('class', 'tapi-search-autocomplete-item')
li.classList.add('search-result') item.appendChild(document.createTextNode(contact.tD_NAME))
li.classList.add('pointer') item.appendChild(document.createTextNode(contact.tD_MEDIUM + ': ' + contact.tD_NUMBER_TAPI))
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 (resultLi: Element) { private selectResult (item: Element) {
var items = document.getElementsByClassName('tapi-search-result') console.log('Select item', item)
for (var item of items) { var items = document.getElementsByClassName('tapi-search-autocomplete-active')
item.classList.remove('bg-light') for (var i of items) {
item.classList.remove('tapi-search-result-selected') i.classList.remove('tapi-search-autocomplete-active')
} }
resultLi.classList.add('bg-light') item.classList.add('tapi-search-autocomplete-active')
resultLi.classList.add('tapi-search-result-selected')
} }
private dial (number: string) { private dial (number: string) {