updated vodia identity
This commit is contained in:
@@ -414,12 +414,18 @@ class AddressModel {
|
||||
}
|
||||
}
|
||||
|
||||
if (array_key_exists("pfm", $filter)) {
|
||||
$pfm = FronkDB::singleton()->escape($filter["pfm"]);
|
||||
if ($pfm) {
|
||||
$where .= " AND (phone like '%$pfm%' OR fax like '%$pfm%' OR mobile like '%$pfm%' )";
|
||||
$pfm = preg_replace('/^(43|0)/', '', preg_replace('/[^0-9]/', '', $filter['pfm'] ?? ''));
|
||||
if (!empty($pfm)) {
|
||||
$pfmEscaped = FronkDB::singleton()->escape($pfm);
|
||||
$searchColumns = ['phone', 'fax', 'mobile'];
|
||||
|
||||
$conditions = array_map(function ($column) use ($pfmEscaped) {
|
||||
$normalizedColumn = "REGEXP_REPLACE(REGEXP_REPLACE(`$column`, '[^0-9]', ''), '^(43|0)', '')";
|
||||
return "$normalizedColumn LIKE '%$pfmEscaped%'";
|
||||
}, $searchColumns);
|
||||
|
||||
$where .= " AND (" . implode(' OR ', $conditions) . ")";
|
||||
}
|
||||
}
|
||||
|
||||
if (array_key_exists("billing_type", $filter)) {
|
||||
$billing_type = FronkDB::singleton()->escape($filter["billing_type"]);
|
||||
|
||||
@@ -441,6 +441,9 @@ class UserController extends mfBaseController
|
||||
case "setVodiaIdentity":
|
||||
$return = $this->setVodiaIdentityApi();
|
||||
break;
|
||||
case "getVodiaCall":
|
||||
$return = $this->getVodiaCallApi();
|
||||
break;
|
||||
default:
|
||||
$return = false;
|
||||
}
|
||||
@@ -528,6 +531,44 @@ class UserController extends mfBaseController
|
||||
|
||||
}
|
||||
|
||||
private function getVodiaCallApi() {
|
||||
if(!ENABLE_VODIA_IDENTITY_SWITCHER) {
|
||||
return ["enabled" => false];
|
||||
}
|
||||
|
||||
$domain = $this->me->getFlag("vodia_identity_domain")->value();
|
||||
$username = $this->me->getFlag("vodia_identity_username")->value();
|
||||
|
||||
if(!$domain || !$username) {
|
||||
return ["enabled" => false];
|
||||
}
|
||||
|
||||
$vodia = new Vodia_Api(VODIA_API_URL, VODIA_API_ADMIN_USER, VODIA_API_ADMIN_PASS);
|
||||
|
||||
$calls = $vodia->getActiveCalls($domain, $username);
|
||||
if(!$calls) {
|
||||
return ["enabled" => true, "calls" => []];
|
||||
}
|
||||
|
||||
$from = null;
|
||||
foreach($calls as $call) {
|
||||
if(isset($call['from'])) {
|
||||
$from = $call['from'];
|
||||
if(preg_match('/<sip:([^@]+)@/', $from, $m)) {
|
||||
$from = $m[1];
|
||||
} elseif(preg_match('/<([^>]+)>/', $from, $m)) {
|
||||
$from = $m[1];
|
||||
} else {
|
||||
$from = str_replace('"', '', $from);
|
||||
}
|
||||
break; // only return the first call's from number
|
||||
}
|
||||
}
|
||||
|
||||
return ["enabled" => true, "number" => $from];
|
||||
|
||||
}
|
||||
|
||||
private function startSuperexpertApi() {
|
||||
$me = new User();
|
||||
$me->loadMe();
|
||||
|
||||
@@ -145,4 +145,32 @@ class Vodia_Api {
|
||||
return $user_settings;
|
||||
|
||||
}
|
||||
|
||||
public function getActiveCalls($domain, $user) {
|
||||
if(!$this->session_id) {
|
||||
$this->_authenticate($domain);
|
||||
}
|
||||
|
||||
$url = $this->baseurl.VODIA_API_EP_GET_USER_CALLS;
|
||||
$url = str_replace("{DOMAIN}", $domain, $url);
|
||||
$url = str_replace("{EXT}", $user, $url);
|
||||
|
||||
$ctx_options = [
|
||||
"http" => [
|
||||
"ignore_errors" => true,
|
||||
"method" => "GET",
|
||||
"header" => [
|
||||
"Cookie: session=".$this->session_id,
|
||||
"Accept: application/json",
|
||||
"Content-Type: application/json",
|
||||
],
|
||||
]
|
||||
];
|
||||
|
||||
$ctx = stream_context_create($ctx_options);
|
||||
$output = file_get_contents($url, false, $ctx);
|
||||
|
||||
return json_decode($output, true);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,6 +1,14 @@
|
||||
document.body.insertAdjacentHTML('beforeend', `
|
||||
<template id="vodia-identity-template">
|
||||
<li id="vodia-identity-container" class="dropdown notification-list ml-2 my-auto" style="display: none;">
|
||||
<a href="#" class="nav-link nav-user d-flex align-items-center" data-ref="callLookupButton" title="Aktuellen Anrufer nachschlagen" style="padding: 0!important;min-width: unset!important">
|
||||
<span class="fa-stack" data-ref="callLookupIconStack">
|
||||
<i class="fa-solid fa-phone fa-stack-1x" style="left: -5px; top: 6px;"></i>
|
||||
<i class="fa-solid fa-magnifying-glass fa-stack-1x" style="transform: scale(0.7);"></i>
|
||||
</span>
|
||||
<i class="fas fa-spinner fa-spin d-none" data-ref="callLookupSpinner" style="margin-right: 10px"></i>
|
||||
</a>
|
||||
|
||||
<a href="#" class="nav-link nav-user dropdown-toggle d-flex align-items-center" aria-haspopup="true" aria-expanded="false" data-ref="toggleButton">
|
||||
<i class="phone-icon fas fa-phone" data-ref="phoneIcon"></i>
|
||||
<div class="pro-user-name ml-2">
|
||||
@@ -40,7 +48,11 @@ class VodiaIdentitySwitcher {
|
||||
setting: "Ändere...",
|
||||
dropdownTitle: "Ausgehende Identität wählen:",
|
||||
ownExtension: "Eigene Nummer",
|
||||
customIdentity: "Andere Nummer"
|
||||
customIdentity: "Andere Nummer",
|
||||
// ## START: ADDED TEXT ##
|
||||
noActiveCall: "Kein aktiver Anruf gefunden.",
|
||||
lookupError: "Fehler bei der Anrufabfrage."
|
||||
// ## END: ADDED TEXT ##
|
||||
};
|
||||
|
||||
pollingTimer = null;
|
||||
@@ -69,7 +81,6 @@ class VodiaIdentitySwitcher {
|
||||
return JSON.parse(cachedString);
|
||||
} catch (e) {
|
||||
console.error("Vodia Cache Error: Could not parse cached data.", e);
|
||||
// Clean up corrupted data
|
||||
localStorage.removeItem(this.CACHE_KEY);
|
||||
return null;
|
||||
}
|
||||
@@ -90,6 +101,9 @@ class VodiaIdentitySwitcher {
|
||||
|
||||
this.elements = {
|
||||
container,
|
||||
callLookupButton: container.querySelector('[data-ref="callLookupButton"]'),
|
||||
callLookupIconStack: container.querySelector('[data-ref="callLookupIconStack"]'),
|
||||
callLookupSpinner: container.querySelector('[data-ref="callLookupSpinner"]'),
|
||||
toggleButton: container.querySelector('[data-ref="toggleButton"]'),
|
||||
phoneIcon: container.querySelector('[data-ref="phoneIcon"]'),
|
||||
currentName: container.querySelector('[data-ref="currentName"]'),
|
||||
@@ -115,11 +129,51 @@ class VodiaIdentitySwitcher {
|
||||
this.elements.toggleButton.setAttribute('aria-expanded', 'false');
|
||||
}
|
||||
});
|
||||
|
||||
this.elements.callLookupButton.addEventListener('click', e => {
|
||||
e.preventDefault();
|
||||
this._handleCallLookup();
|
||||
});
|
||||
}
|
||||
|
||||
_setLookupButtonLoadingState(isLoading) {
|
||||
const { callLookupButton, callLookupIconStack, callLookupSpinner } = this.elements;
|
||||
if (isLoading) {
|
||||
callLookupButton.setAttribute('disabled', 'true');
|
||||
callLookupIconStack.classList.add('d-none'); // Hide the icon stack
|
||||
callLookupSpinner.classList.remove('d-none'); // Show the spinner
|
||||
} else {
|
||||
callLookupButton.removeAttribute('disabled');
|
||||
callLookupIconStack.classList.remove('d-none'); // Show the icon stack
|
||||
callLookupSpinner.classList.add('d-none'); // Hide the spinner
|
||||
}
|
||||
}
|
||||
|
||||
async _handleCallLookup() {
|
||||
this._setLookupButtonLoadingState(true);
|
||||
try {
|
||||
const response = await fetch(`${this.API_BASE_URL}User/Api/do=getVodiaCall`);
|
||||
if (!response.ok) throw new Error('Network response was not ok');
|
||||
|
||||
const data = await response.json();
|
||||
if (data.status === 'OK' && data.result.number && data.result.number.length >= 5) {
|
||||
const url = `${this.API_BASE_URL}Address/Index?filter[pfm]=${data.result.number}`;
|
||||
window.open(url, '_blank'); // Open address book in a new tab
|
||||
} else {
|
||||
if (window.notify) window.notify('info', this.TEXT.noActiveCall);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Vodia Call Lookup Error:", error.message);
|
||||
if (window.notify) window.notify('error', this.TEXT.lookupError);
|
||||
} finally {
|
||||
this._setLookupButtonLoadingState(false);
|
||||
}
|
||||
}
|
||||
// ## END: ADDED METHOD TO HANDLE CALL LOOKUP ##
|
||||
|
||||
_setLoadingState(isLoading, message = '') {
|
||||
const { phoneIcon, currentName, currentNumber } = this.elements;
|
||||
phoneIcon.className = 'phone-icon fas fa-phone'; // Reset
|
||||
phoneIcon.className = 'phone-icon fas fa-phone';
|
||||
|
||||
if (isLoading) {
|
||||
phoneIcon.classList.add('fa-spin', 'text-warning');
|
||||
@@ -152,7 +206,7 @@ class VodiaIdentitySwitcher {
|
||||
}
|
||||
|
||||
if (vodiaState?.enabled) {
|
||||
this.elements.container.style.display = 'list-item';
|
||||
this.elements.container.style.display = 'flex'; // Use flex to align items
|
||||
this._updateUI(vodiaState);
|
||||
this._setLoadingState(false);
|
||||
} else {
|
||||
@@ -221,7 +275,6 @@ class VodiaIdentitySwitcher {
|
||||
const { 'default': defaultDisplay, default_number, current, identities } = vodiaState;
|
||||
const currentId = current.replaceAll(' ', "");
|
||||
|
||||
// Add "Own Extension"
|
||||
this.elements.identityList.appendChild(this._createListItem({
|
||||
name: this.TEXT.ownExtension,
|
||||
number: default_number.replaceAll(' ', ""),
|
||||
@@ -230,7 +283,6 @@ class VodiaIdentitySwitcher {
|
||||
isActive: currentId === default_number.replaceAll(' ', "")
|
||||
}));
|
||||
|
||||
// Add other identities
|
||||
if (!identities) return;
|
||||
for (const name in identities) {
|
||||
const ident = identities[name];
|
||||
@@ -262,6 +314,7 @@ class VodiaIdentitySwitcher {
|
||||
return item;
|
||||
}
|
||||
}
|
||||
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
const topbar = document.querySelector("#topbar");
|
||||
if (topbar) new VodiaIdentitySwitcher(topbar);
|
||||
|
||||
Reference in New Issue
Block a user