Added Voice Functionality
[KolmisoftMore] implemented getActiveCalls function [menu.php] added menu point for active voice calls [config.sample.php] added KOLMISOFT configuration constants [VoiceCallActive] implemented active voice calls view [VoiceCallHistoryController] fixed importCallsFromToday Time [tt-table] fixed pagination displays
This commit is contained in:
97
Layout/default/VoiceCallActive/Index.php
Normal file
97
Layout/default/VoiceCallActive/Index.php
Normal file
@@ -0,0 +1,97 @@
|
|||||||
|
<?php /** @noinspection PhpUndefinedClassInspection
|
||||||
|
* @var string $mfLayoutPackage
|
||||||
|
* @var TYPE_NAME $git_merge_ts
|
||||||
|
*/
|
||||||
|
|
||||||
|
//additional css /css/views/RaspberryDisplay.css
|
||||||
|
|
||||||
|
$JSGlobals = ["BASE_URL" => self::getUrl("VoiceCallActive"),
|
||||||
|
"DASHBOARD_URL" => self::getUrl("Dashboard"),
|
||||||
|
"MFAPPNAME" => MFAPPNAME_SLUG,
|
||||||
|
"PAGE_TITLE" => "Active Voice Calls",
|
||||||
|
"PATH" => [
|
||||||
|
["text" => MFAPPNAME_SLUG, "href" => self::getUrl("Dashboard")],
|
||||||
|
["text" => "Active Voice Calls", "href" => self::getUrl("VoiceCallActive")]
|
||||||
|
],
|
||||||
|
"VOICE_CALL_ACTIVE_API_URL" => self::getUrl("VoiceCallActive/api"),
|
||||||
|
];
|
||||||
|
|
||||||
|
$additionalJS = ["plugins/vue/vue.js",
|
||||||
|
"plugins/axios/axios.min.js",
|
||||||
|
"plugins/vue/tt-components/tt-page-title.js",
|
||||||
|
"plugins/vue/tt-components/tt-table.js",
|
||||||
|
];
|
||||||
|
$additionalCSS = [
|
||||||
|
'plugins/vue/tt-components/css/tt-table.css',
|
||||||
|
];
|
||||||
|
|
||||||
|
include(realpath(dirname(__FILE__) . "/../../$mfLayoutPackage") . "/header.php"); ?>
|
||||||
|
|
||||||
|
<div id="app">
|
||||||
|
<tt-page-title :title="window['TT_CONFIG']['PAGE_TITLE']" :path="window['TT_CONFIG']['PATH']"></tt-page-title>
|
||||||
|
|
||||||
|
<tt-table :fetch-url="window['TT_CONFIG']['VOICE_CALL_ACTIVE_API_URL'] + '?do=getActiveCalls'" :table-config="VoiceCallActiveTableConfig"
|
||||||
|
small ref="table">
|
||||||
|
|
||||||
|
<template v-slot:top-buttons>
|
||||||
|
<button type="button" class="btn btn-primary" @click="refresh">
|
||||||
|
<template v-if="refreshLoading">
|
||||||
|
<span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span>
|
||||||
|
</template>
|
||||||
|
<template v-else>
|
||||||
|
<i class="fas fa-sync-alt"></i>
|
||||||
|
Refresh
|
||||||
|
</template>
|
||||||
|
</button>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<!-- Slot to show DNS records button -->
|
||||||
|
<template v-slot:answer_time="{ row }">
|
||||||
|
{{ new Date(row.answer_time).toLocaleString() }}
|
||||||
|
</template>
|
||||||
|
|
||||||
|
</tt-table>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- TODO: download from cdn to local -->
|
||||||
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-select@1.13.14/dist/css/bootstrap-select.min.css">
|
||||||
|
|
||||||
|
<script type="text/javascript" src="https://cdn.jsdelivr.net/momentjs/latest/moment.min.js"></script>
|
||||||
|
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/daterangepicker/daterangepicker.min.js"></script>
|
||||||
|
<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/daterangepicker/daterangepicker.css" />
|
||||||
|
|
||||||
|
<script>
|
||||||
|
new Vue({
|
||||||
|
el: '#app',
|
||||||
|
data: {
|
||||||
|
window: window,
|
||||||
|
VoiceCallActiveTableConfig: {
|
||||||
|
headers: [
|
||||||
|
{text: 'ID', key: 'id', filter: false},
|
||||||
|
{text: 'Status', key: 'status', filter: false},
|
||||||
|
{text: 'Answer Time', key: 'answer_time', filter: false},
|
||||||
|
{text: 'Duration', key: 'duration', filter: false},
|
||||||
|
{text: 'Source', key: 'src', filter: false},
|
||||||
|
{text: 'Device Type', key: 'device_type', filter: false},
|
||||||
|
{text: 'Destination', key: 'localized_dst', filter: false},
|
||||||
|
{text: 'Destination User', key: 'dst_user', filter: false},
|
||||||
|
{text: 'Destination Device Extension', key: 'dst_device_extension', filter: false},
|
||||||
|
],
|
||||||
|
tableHeader: 'Voice Call History',
|
||||||
|
},
|
||||||
|
refreshLoading: false,
|
||||||
|
},
|
||||||
|
mounted() {},
|
||||||
|
methods: {
|
||||||
|
async refresh() {
|
||||||
|
this.refreshLoading = true;
|
||||||
|
this.$refs.table.loading = true;
|
||||||
|
await this.$refs.table.fetchData();
|
||||||
|
this.$refs.table.loading = false;
|
||||||
|
this.refreshLoading = false;
|
||||||
|
},
|
||||||
|
}
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
<?php include(realpath(dirname(__FILE__) . "/../../$mfLayoutPackage") . "/footer.php"); ?>
|
||||||
|
|
||||||
@@ -77,8 +77,9 @@ include(realpath(dirname(__FILE__) . "/../../$mfLayoutPackage") . "/header.php")
|
|||||||
methods: {
|
methods: {
|
||||||
async importCallsFromToday() {
|
async importCallsFromToday() {
|
||||||
this.importCallsFromTodayLoading = true;
|
this.importCallsFromTodayLoading = true;
|
||||||
await axios.get(window['TT_CONFIG']['VOICE_CALL_HISTORY_API_URL'] + '?do=importCallsFromToday');
|
const response = await axios.get(window['TT_CONFIG']['VOICE_CALL_HISTORY_API_URL'] + '?do=importCallsFromToday');
|
||||||
this.$refs.table.fetchData();
|
window.notify(response.data.status === 'success' ? 'success' : 'error', response.data.message);
|
||||||
|
await this.$refs.table.fetchData();
|
||||||
this.importCallsFromTodayLoading = false;
|
this.importCallsFromTodayLoading = false;
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -127,6 +127,7 @@
|
|||||||
<?php if($me->isAdmin() || $me->can("Voipnumbering")): ?><li><a href="<?=self::getUrl("Voicenumberblock")?>"><i class="fad fa-fw fa-phone-office text-info"></i> Rufnummernblöcke</a></li><?php endif; ?>
|
<?php if($me->isAdmin() || $me->can("Voipnumbering")): ?><li><a href="<?=self::getUrl("Voicenumberblock")?>"><i class="fad fa-fw fa-phone-office text-info"></i> Rufnummernblöcke</a></li><?php endif; ?>
|
||||||
<?php if($me->isAdmin() || $me->can("Voiceplan")): ?><li><a href="<?=self::getUrl("Voiceplan")?>"><i class="fas fa-fw fa-phone-arrow-up-right text-info"></i> Sprachtarife</a></li><?php endif; ?>
|
<?php if($me->isAdmin() || $me->can("Voiceplan")): ?><li><a href="<?=self::getUrl("Voiceplan")?>"><i class="fas fa-fw fa-phone-arrow-up-right text-info"></i> Sprachtarife</a></li><?php endif; ?>
|
||||||
<?php if($me->isAdmin() || $me->can("VoiceCallHistory")): ?><li><a href="<?=self::getUrl("VoiceCallHistory")?>"><i class="fas fa-fw fa-phone-arrow-down-left text-info"></i> Voice Call History</a></li><?php endif; ?>
|
<?php if($me->isAdmin() || $me->can("VoiceCallHistory")): ?><li><a href="<?=self::getUrl("VoiceCallHistory")?>"><i class="fas fa-fw fa-phone-arrow-down-left text-info"></i> Voice Call History</a></li><?php endif; ?>
|
||||||
|
<?php if($me->isAdmin() || $me->can("VoiceCallActive")): ?><li><a href="<?=self::getUrl("VoiceCallActive")?>"><i class="fas fa-fw fa-phone-volume text-info"></i> Active Voice Calls</a></li><?php endif; ?>
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
|
|||||||
9
application/VoiceCallActive/VoiceCallActive.php
Normal file
9
application/VoiceCallActive/VoiceCallActive.php
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @property mixed|null $name
|
||||||
|
*/
|
||||||
|
class VoiceCallActive extends mfBaseModel
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
61
application/VoiceCallActive/VoiceCallActiveController.php
Normal file
61
application/VoiceCallActive/VoiceCallActiveController.php
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
class VoiceCallActiveController extends mfBaseController {
|
||||||
|
private User $me;
|
||||||
|
private string $VOICE_PORTAL_HOST = KOLMISOFT_API_HOST;
|
||||||
|
private string $VOICE_PORTAL_API_KEY = KOLMISOFT_API_KEY;
|
||||||
|
private string $VOICE_PORTAL_USERNAME = KOLMISOFT_API_USERNAME;
|
||||||
|
|
||||||
|
private KolmisoftMore $kolmisoftMore;
|
||||||
|
|
||||||
|
|
||||||
|
protected function init(): void {
|
||||||
|
$me = new User();
|
||||||
|
$me->loadMe();
|
||||||
|
$this->layout()->set("me", $me);
|
||||||
|
$this->me = $me;
|
||||||
|
|
||||||
|
if (!$this->me->isAdmin()) {
|
||||||
|
$this->redirect("dashboard");
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->kolmisoftMore = new KolmisoftMore($this->VOICE_PORTAL_HOST, $this->VOICE_PORTAL_API_KEY, $this->VOICE_PORTAL_USERNAME);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function indexAction(): void {
|
||||||
|
$this->layout()->setTemplate("VoiceCallActive/Index");
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function apiAction() {
|
||||||
|
$do = $this->request->do;
|
||||||
|
|
||||||
|
if (!$this->me->isAdmin()) {
|
||||||
|
$this->redirect("dashboard");
|
||||||
|
}
|
||||||
|
|
||||||
|
switch ($do) {
|
||||||
|
case "getActiveCalls":
|
||||||
|
$return = $this->getActiveCalls();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
$return = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$return) {
|
||||||
|
$return = [
|
||||||
|
"status" => "error",
|
||||||
|
"message" => "Invalid request."
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
die(json_encode($return));
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getActiveCalls(): array {
|
||||||
|
return [
|
||||||
|
"rows" => $this->kolmisoftMore->getActiveCalls()
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,15 +1,10 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
//display errors
|
|
||||||
//ini_set('display_errors', 1);
|
|
||||||
//ini_set('display_startup_errors', 1);
|
|
||||||
//error_reporting(E_ALL);
|
|
||||||
|
|
||||||
class VoiceCallHistoryController extends mfBaseController {
|
class VoiceCallHistoryController extends mfBaseController {
|
||||||
private User $me;
|
private User $me;
|
||||||
private string $VOICE_PORTAL_HOST = "vportal.xinon.at";
|
private string $VOICE_PORTAL_HOST = KOLMISOFT_API_HOST;
|
||||||
private string $VOICE_PORTAL_API_KEY = "2f9mpw3oamALg7gSgtWUTCKNZ01fFRDh";
|
private string $VOICE_PORTAL_API_KEY = KOLMISOFT_API_KEY;
|
||||||
private string $VOICE_PORTAL_USERNAME = "700342020";
|
private string $VOICE_PORTAL_USERNAME = KOLMISOFT_API_USERNAME;
|
||||||
|
|
||||||
private KolmisoftMore $kolmisoftMore;
|
private KolmisoftMore $kolmisoftMore;
|
||||||
|
|
||||||
@@ -62,8 +57,8 @@ class VoiceCallHistoryController extends mfBaseController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private function importCallsFromToday(): array {
|
private function importCallsFromToday(): array {
|
||||||
$startDate = strtotime(date("Y-m-d 8:00:00"));
|
$startDate = strtotime(date("Y-m-d 0:00:00"));
|
||||||
$endDate = strtotime(date("Y-m-d 9:00:59"));
|
$endDate = strtotime(date("Y-m-d 23:59:59"));
|
||||||
|
|
||||||
$callHistory = $this->kolmisoftMore->getVoiceCallHistory($startDate, $endDate);
|
$callHistory = $this->kolmisoftMore->getVoiceCallHistory($startDate, $endDate);
|
||||||
|
|
||||||
|
|||||||
@@ -7,9 +7,9 @@
|
|||||||
|
|
||||||
class VoiceCallHistoryJobController extends mfBaseController {
|
class VoiceCallHistoryJobController extends mfBaseController {
|
||||||
private User $me;
|
private User $me;
|
||||||
private string $VOICE_PORTAL_HOST = "vportal.xinon.at";
|
private string $VOICE_PORTAL_HOST = KOLMISOFT_API_HOST;
|
||||||
private string $VOICE_PORTAL_API_KEY = "2f9mpw3oamALg7gSgtWUTCKNZ01fFRDh";
|
private string $VOICE_PORTAL_API_KEY = KOLMISOFT_API_KEY;
|
||||||
private string $VOICE_PORTAL_USERNAME = "700342020";
|
private string $VOICE_PORTAL_USERNAME = KOLMISOFT_API_USERNAME;
|
||||||
|
|
||||||
private KolmisoftMore $kolmisoftMore;
|
private KolmisoftMore $kolmisoftMore;
|
||||||
|
|
||||||
@@ -43,9 +43,6 @@ class VoiceCallHistoryJobController extends mfBaseController {
|
|||||||
case "runJobs":
|
case "runJobs":
|
||||||
$return = $this->runJobs();
|
$return = $this->runJobs();
|
||||||
break;
|
break;
|
||||||
case "importCallsFromToday":
|
|
||||||
$return = $this->importCallsFromToday();
|
|
||||||
break;
|
|
||||||
default:
|
default:
|
||||||
$return = false;
|
$return = false;
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -691,3 +691,7 @@ define("TT_MBI_API_KEY", "");
|
|||||||
//Raspberry Display Configuration
|
//Raspberry Display Configuration
|
||||||
define("XINON_RASPBERRY_DISPLAY_SSH_USER", "");
|
define("XINON_RASPBERRY_DISPLAY_SSH_USER", "");
|
||||||
define("XINON_RASPBERRY_DISPLAY_SSH_PASS", "");
|
define("XINON_RASPBERRY_DISPLAY_SSH_PASS", "");
|
||||||
|
|
||||||
|
define("TT_KOLMISOFT_API_URL", "vportal.xxx.xx");
|
||||||
|
define("TT_KOLMISOFT_API_KEY", "");
|
||||||
|
define("TT_KOLMISOFT_API_USERNAME", "");
|
||||||
|
|||||||
@@ -79,4 +79,22 @@ class KolmisoftMore {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getActiveCalls() {
|
||||||
|
$queryParameters = ['u' => $this->username];
|
||||||
|
|
||||||
|
$hash = $this->generateHash($queryParameters);
|
||||||
|
|
||||||
|
$queryParameters['hash'] = $hash;
|
||||||
|
|
||||||
|
$queryString = http_build_query($queryParameters);
|
||||||
|
|
||||||
|
$response = $this->makeRequest('active_calls_get', $queryString);
|
||||||
|
|
||||||
|
if ($response) {
|
||||||
|
return $response['status']['active_call'];
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -143,7 +143,7 @@ Vue.component('tt-table', {
|
|||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
<span class="text-center"
|
<span class="text-center"
|
||||||
v-text="Math.max(pagination.page * pagination.per_page - pagination.per_page + 1, pagination.total_rows)
|
v-text="Math.min(pagination.page * pagination.per_page - pagination.per_page + 1, pagination.total_rows)
|
||||||
+ ' bis ' + Math.min(pagination.page * pagination.per_page, pagination.total_rows) + ' von ' + pagination.total_rows"></span>
|
+ ' bis ' + Math.min(pagination.page * pagination.per_page, pagination.total_rows) + ' von ' + pagination.total_rows"></span>
|
||||||
<select v-model="pagination.per_page" v-on:change="fetchRows(1)" class="form-control form-control-sm">
|
<select v-model="pagination.per_page" v-on:change="fetchRows(1)" class="form-control form-control-sm">
|
||||||
<option value="10">10</option>
|
<option value="10">10</option>
|
||||||
@@ -238,7 +238,7 @@ Vue.component('tt-table', {
|
|||||||
* @param {number} page The page number to fetch data for.
|
* @param {number} page The page number to fetch data for.
|
||||||
* @async
|
* @async
|
||||||
*/
|
*/
|
||||||
async fetchData(page) {
|
async fetchData(page= 0) {
|
||||||
try {
|
try {
|
||||||
const fetchTimestamp = Date.now();
|
const fetchTimestamp = Date.now();
|
||||||
this.latestFetchTimestamp = fetchTimestamp;
|
this.latestFetchTimestamp = fetchTimestamp;
|
||||||
|
|||||||
Reference in New Issue
Block a user