Add quick status buttons with SVG icons and status text support
Status buttons (Arbeiten, Besprechung, Fokus, Mittag, Feierabend) allow one-click 3CX presence changes including status text via DOM automation. Buttons are color-coded by status type (green/red/yellow) with Font Awesome SVG icons. Also reduces verbose console logging in search module. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
+72
-12
@@ -5,6 +5,20 @@ import { fireChangeEvents } from './utils'
|
||||
import GM_fetch from '@trim21/gm-fetch'
|
||||
import { Config } from './config'
|
||||
|
||||
const iconArbeiten = require('./briefcase-regular-full.svg')
|
||||
const iconBesprechung = require('./screen-users-sharp-regular-full.svg')
|
||||
const iconFokus = require('./headphones-regular-full.svg')
|
||||
const iconMittag = require('./grill-hot-regular-full.svg')
|
||||
const iconFeierabend = require('./beer-mug-empty-regular-full.svg')
|
||||
|
||||
const QUICK_BUTTONS = [
|
||||
{ icon: iconArbeiten, menuId: 'menuCustom1', message: '', css: 'tapi-btn-available', title: 'Arbeiten' },
|
||||
{ icon: iconBesprechung, menuId: 'menuOutofoffice', message: 'Besprechung', css: 'tapi-btn-dnd', title: 'Besprechung' },
|
||||
{ icon: iconFokus, menuId: 'menuOutofoffice', message: 'Fokus', css: 'tapi-btn-dnd', title: 'Fokus' },
|
||||
{ icon: iconMittag, menuId: 'menuAway', message: 'Mittag', css: 'tapi-btn-away', title: 'Mittag' },
|
||||
{ icon: iconFeierabend, menuId: 'menuAway', message: 'Feierabend', css: 'tapi-btn-away', title: 'Feierabend' },
|
||||
]
|
||||
|
||||
export class Search {
|
||||
private currentSearchText = ''
|
||||
|
||||
@@ -12,6 +26,7 @@ export class Search {
|
||||
console.log('Create TAPI Search')
|
||||
|
||||
var form = document.createElement('form')
|
||||
form.classList.add('tapi-form')
|
||||
form.onsubmit = () => {
|
||||
var items = document.getElementsByClassName('tapi-search-autocomplete-active')
|
||||
if (items.length === 0) {
|
||||
@@ -22,10 +37,20 @@ export class Search {
|
||||
} else {
|
||||
this.dial((<HTMLInputElement>document.getElementById('tapiSearchInput')).value)
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
QUICK_BUTTONS.forEach(btn => {
|
||||
var button = document.createElement('button')
|
||||
button.type = 'button'
|
||||
button.innerHTML = btn.icon
|
||||
button.classList.add('tapi-quick-btn')
|
||||
button.classList.add(btn.css)
|
||||
button.title = btn.title
|
||||
button.onclick = () => { this.setStatus(btn.menuId, btn.message) }
|
||||
form.appendChild(button)
|
||||
})
|
||||
|
||||
var searchBox = document.createElement('div')
|
||||
searchBox.classList.add('tapi-search-autocomplete')
|
||||
searchBox.style.width = '200px'
|
||||
@@ -39,17 +64,58 @@ export class Search {
|
||||
search.onfocus = () => { this.doSearch() }
|
||||
search.onkeydown = (ev) => { this.doSearchKeyDown(ev) }
|
||||
search.onblur = () => {
|
||||
console.log('TAPI Search exit', this)
|
||||
setTimeout(() => {
|
||||
console.log('TAPI clear search results')
|
||||
this.removeSearchResults()
|
||||
}, 250)
|
||||
setTimeout(() => { this.removeSearchResults() }, 250)
|
||||
}
|
||||
searchBox.appendChild(search)
|
||||
|
||||
element.parentElement.insertBefore(form, element)
|
||||
}
|
||||
|
||||
private delay (ms: number): Promise<void> {
|
||||
return new Promise(resolve => setTimeout(resolve, ms))
|
||||
}
|
||||
|
||||
private async setStatus (menuId: string, message: string) {
|
||||
var accMenu = document.getElementsByTagName('wc-account-menu')[0]
|
||||
var avatar = accMenu.getElementsByTagName('app-avatar')[0] as HTMLAnchorElement
|
||||
|
||||
avatar.click()
|
||||
await this.delay(1000)
|
||||
|
||||
if (message !== '') {
|
||||
var pencilBtn = document.getElementById(menuId + 'SetStatus') as HTMLElement
|
||||
if (pencilBtn) {
|
||||
pencilBtn.click()
|
||||
await this.delay(500)
|
||||
|
||||
var modalInput = document.querySelector('input[data-qa="input"][maxlength="128"]') as HTMLInputElement
|
||||
if (modalInput) {
|
||||
modalInput.value = message
|
||||
fireChangeEvents(modalInput)
|
||||
await this.delay(300)
|
||||
|
||||
var okBtn = Array.from(document.querySelectorAll('button')).find(btn =>
|
||||
btn.textContent && btn.textContent.trim() === 'OK' && btn.getBoundingClientRect().width > 0
|
||||
) as HTMLButtonElement
|
||||
if (okBtn) {
|
||||
okBtn.click()
|
||||
await this.delay(500)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var statusItem = document.getElementById(menuId) as HTMLElement
|
||||
if (!statusItem || statusItem.getBoundingClientRect().width === 0) {
|
||||
avatar.click()
|
||||
await this.delay(1000)
|
||||
statusItem = document.getElementById(menuId) as HTMLElement
|
||||
}
|
||||
if (statusItem) {
|
||||
statusItem.click()
|
||||
}
|
||||
}
|
||||
|
||||
private removeSearchResults () {
|
||||
var resultList = document.getElementById('tapi-search-autocomplete-list')
|
||||
if (resultList) {
|
||||
@@ -103,11 +169,8 @@ export class Search {
|
||||
} else if (searchText === this.currentSearchText) {
|
||||
return
|
||||
}
|
||||
console.log('Searching TAPI')
|
||||
var response = await GM_fetch(Config.tapi_server_url + '/search?query=' + encodeURIComponent(searchText))
|
||||
console.log('TAPI Search response', response)
|
||||
var contacts = await response.json() as TapiContact[]
|
||||
console.log('TAPI Contacts', contacts)
|
||||
this.removeSearchResults()
|
||||
this.currentSearchText = searchText
|
||||
|
||||
@@ -130,17 +193,14 @@ export class Search {
|
||||
}, 200)
|
||||
|
||||
private selectResult (item: Element) {
|
||||
console.log('Select item', item)
|
||||
var items = document.getElementsByClassName('tapi-search-autocomplete-active')
|
||||
for (var i of items) {
|
||||
i.classList.remove('tapi-search-autocomplete-active')
|
||||
}
|
||||
|
||||
item.classList.add('tapi-search-autocomplete-active')
|
||||
}
|
||||
|
||||
private dial (number: string) {
|
||||
console.log('TAPI Search dialing', number);
|
||||
var searchInput = document.getElementById('dialpad-input');
|
||||
(<HTMLInputElement>searchInput).value = number;
|
||||
(<HTMLInputElement>searchInput).focus;
|
||||
|
||||
Reference in New Issue
Block a user