forked from Mirrors/freeswitch
add portal, a nice GUI with pure html and javascript
This commit is contained in:
parent
3807dcb129
commit
c16843dc51
|
@ -0,0 +1,25 @@
|
|||
The FreeSWITCH Portal Project
|
||||
Copyright (C) 2013-2013, Seven Du <dujinfang@gmail.com>
|
||||
|
||||
Version: MPL 1.1
|
||||
|
||||
The contents of this file are subject to the Mozilla Public License Version
|
||||
1.1 (the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
http://www.mozilla.org/MPL/
|
||||
|
||||
Software distributed under the License is distributed on an "AS IS" basis,
|
||||
WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
for the specific language governing rights and limitations under the
|
||||
License.
|
||||
|
||||
The Original Code is The FreeSWITCH Portal Project Software/Application
|
||||
|
||||
The Initial Developer of the Original Code is
|
||||
Seven Du <dujinfang@gmail.com>
|
||||
Portions created by the Initial Developer are Copyright (C)
|
||||
the Initial Developer. All Rights Reserved.
|
||||
|
||||
Contributor(s):
|
||||
|
||||
Seven Du <dujinfang@gmail.com>
|
|
@ -0,0 +1,64 @@
|
|||
# The FreeSWITCH Portal Project
|
||||
|
||||
The FreeSWITCH Portal Project is designed to show an intuitive view of the FreeSWITCH internals.
|
||||
|
||||
It can be used by FreeSWITCH funs, administrators, developers etc.
|
||||
|
||||
It does not aims to replace GUIs such as fusionPBX or blue.box.
|
||||
|
||||
It would be very easy to use and super helpful for new FreeSWITCH users.
|
||||
|
||||
## Philosophy
|
||||
|
||||
To provide a GUI out of the box without depends on external resources like PHP or a webserver such as Apache or Nginx.
|
||||
|
||||
Mainly developed with static html and Javascripts, and perhaps some lua scripts can help do some more magic things later.
|
||||
|
||||
## Install
|
||||
|
||||
Assume you installed FreeSWITCH in the default place - /usr/local/freeswitch, you can do
|
||||
|
||||
cd /usr/local/freeswitch/htdocs
|
||||
git clone https://github.com/seven1240/FreeSWITCH-Portal.git portal
|
||||
|
||||
In FreeSWITCH you need to
|
||||
|
||||
load mod_xml_rpc
|
||||
|
||||
Open your browser (Only Chrome is tested) and go to
|
||||
|
||||
http://localhost:8080/portal/index.html
|
||||
|
||||
If you it asking for username and password you can find them in /usr/local/freeswitch/conf/autoload_configs/xml\_rpc.conf.xml. For more information see <http://wiki.freeswitch.org/wiki/Mod_xml_rpc> .
|
||||
|
||||
## Todo
|
||||
|
||||
* Websocket: by add websocket support in FreeSWITCH we can see channel changes lively, I have some working code as a patch to mod\_event\_socket.
|
||||
|
||||
* Modify users: A raw idea to add a new user would be something like below and reloadxml.
|
||||
|
||||
sed -e 's/1000/new-user/g' 1000.xml > new-user.xml
|
||||
|
||||
* Modify dialplan and/or other XMLs: possible to use some online XML editor and can save the XML with some lua or C code at the backend, although there are security concerns.
|
||||
|
||||
* Store information in DB: I guess the Dbh handle in lua should can do something like this.
|
||||
|
||||
* Web terminal: With terminal.js like things and websocket we can really build a web version of fs_cli
|
||||
|
||||
* rtmp web client support to make and receive calls
|
||||
|
||||
* WebRTC?
|
||||
|
||||
* Logging, Event Debugging or SIP tracing: Yeah, more magic
|
||||
|
||||
* i18n
|
||||
|
||||
## Security
|
||||
|
||||
The primary goal is to help new users learn and use FreeSWITCH. Please DON'T put this on your production server as I haven't think anything about security.
|
||||
|
||||
## Development
|
||||
|
||||
I started this project to learn how to use [bootstrap](twitter.github.com/bootstrap/index.html) and [ember.js](twitter.github.com/bootstrap/index.html), the latter said it is a framework for creating **ambitious** web applications.
|
||||
|
||||
Contributions and patches are welcome.
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
Binary file not shown.
After Width: | Height: | Size: 8.6 KiB |
Binary file not shown.
After Width: | Height: | Size: 12 KiB |
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,373 @@
|
|||
/*
|
||||
* The FreeSWITCH Portal Project
|
||||
* Copyright (C) 2013-2013, Seven Du <dujinfang@gmail.com>
|
||||
*
|
||||
* Version: MPL 1.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is The FreeSWITCH Portal Project Software/Application
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Seven Du <dujinfang@gmail.com>
|
||||
* Portions created by the Initial Developer are Copyright (C)
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Seven Du <dujinfang@gmail.com>
|
||||
*
|
||||
*
|
||||
* fsportal.js -- The FreeSWITCH Portal Project
|
||||
*
|
||||
*/
|
||||
|
||||
var App = Ember.Application.create({
|
||||
LOG_TRANSITIONS: true,
|
||||
rootElement: $('#container'),
|
||||
total: 0,
|
||||
ready: function(){
|
||||
}
|
||||
});
|
||||
|
||||
App.CallsRoute = Ember.Route.extend({
|
||||
setupController: function(controller) {
|
||||
// Set the IndexController's `title`
|
||||
// controller.set('title', "My App");
|
||||
// alert("a")
|
||||
console.log("callsRoute");
|
||||
App.callsController.load();
|
||||
}//,
|
||||
// renderTemplate: function() {
|
||||
// this.render('calls');
|
||||
// }
|
||||
});
|
||||
|
||||
App.ChannelsRoute = Ember.Route.extend({
|
||||
setupController: function(controller) {
|
||||
// Set the IndexController's `title`
|
||||
// controller.set('title', "My App");
|
||||
// alert("a")
|
||||
console.log("callsRoute");
|
||||
App.channelsController.load();
|
||||
}//,
|
||||
// renderTemplate: function() {
|
||||
// this.render('calls');
|
||||
// }
|
||||
});
|
||||
|
||||
|
||||
App.ShowApplicationsRoute = Ember.Route.extend({
|
||||
setupController: function(controller) {
|
||||
// Set the Controller's `title`
|
||||
controller.set('title', "ShowApplications");
|
||||
console.log("showApplications");
|
||||
App.applicationsController.load();
|
||||
}//,
|
||||
// renderTemplate: function() {
|
||||
// this.render('calls');
|
||||
// }
|
||||
});
|
||||
|
||||
App.ShowEndpointsRoute = Ember.Route.extend({
|
||||
setupController: function(controller) {
|
||||
// Set the Controller's `title`
|
||||
controller.set('title', "ShowEndpoints");
|
||||
console.log(controller);
|
||||
App.showEndpointsController.load();
|
||||
}//,
|
||||
// renderTemplate: function() {
|
||||
// this.render('calls');
|
||||
// }
|
||||
});
|
||||
|
||||
App.ShowCodecsRoute = Ember.Route.extend({
|
||||
setupController: function(controller) {
|
||||
App.showCodecsController.load();
|
||||
}
|
||||
});
|
||||
|
||||
App.UsersRoute = Ember.Route.extend({
|
||||
setupController: function(controller) {
|
||||
App.usersController.load();
|
||||
}
|
||||
});
|
||||
|
||||
App.Router.map(function(){
|
||||
this.route("calls");
|
||||
this.route("channels");
|
||||
this.route("showApplications");
|
||||
this.route("showEndpoints");
|
||||
this.route("showCodecs");
|
||||
this.route("showFiles");
|
||||
this.route("showAPIs");
|
||||
this.route("show");
|
||||
this.route("users");
|
||||
this.route("about", { path: "/about" });
|
||||
});
|
||||
|
||||
App.User = Em.Object.extend({
|
||||
id: null,
|
||||
context: null,
|
||||
domain: null,
|
||||
group: null,
|
||||
contact: null
|
||||
});
|
||||
|
||||
App.Call = Em.Object.extend({
|
||||
uuid: null,
|
||||
cidName: null,
|
||||
cidNumber: null
|
||||
|
||||
});
|
||||
|
||||
App.Channel = Em.Object.extend({
|
||||
uuid: null,
|
||||
cidName: null,
|
||||
cidNumber: null
|
||||
|
||||
});
|
||||
|
||||
App.callsController = Ember.ArrayController.create({
|
||||
content: [],
|
||||
init: function(){
|
||||
},
|
||||
load: function() {
|
||||
var me = this;
|
||||
$.getJSON("/txtapi/show?calls%20as%20json", function(data){
|
||||
// var channels = JSON.parse(data);
|
||||
console.log(data.row_count);
|
||||
me.set('total', data.row_count);
|
||||
me.content.clear();
|
||||
if (data.row_count == 0) return;
|
||||
|
||||
// me.pushObjects(data.rows);
|
||||
data.rows.forEach(function(r) {
|
||||
me.pushObject(App.Call.create(r));
|
||||
});
|
||||
|
||||
});
|
||||
},
|
||||
dump: function(uuid) {
|
||||
var obj = this.content.findProperty("uuid", uuid);
|
||||
console.log(obj.getProperties(["uuid", "cid_num"]));
|
||||
},
|
||||
raw: function() {
|
||||
$.get("/api/show?calls", function(data){
|
||||
$('#aa').html(data);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
App.channelsController = Ember.ArrayController.create({
|
||||
content: [],
|
||||
listener: undefined,
|
||||
init: function(){
|
||||
},
|
||||
load: function() {
|
||||
var me = this;
|
||||
$.getJSON("/txtapi/show?channels%20as%20json", function(data){
|
||||
// var channels = JSON.parse(data);
|
||||
console.log(data.row_count);
|
||||
me.set('total', data.row_count);
|
||||
me.content.clear();
|
||||
if (data.row_count == 0) return;
|
||||
data.rows.forEach(function(row) {
|
||||
me.pushObject(App.Channel.create(row));
|
||||
});
|
||||
|
||||
});
|
||||
},
|
||||
delete: function(uuid) {
|
||||
var obj = this.content.findProperty("uuid", uuid);
|
||||
if (obj) this.content.removeObject(obj);// else alert(uuid);
|
||||
},
|
||||
dump: function(uuid) {
|
||||
var obj = this.content.findProperty("uuid", uuid);
|
||||
console.log(obj.getProperties(["uuid", "cid_num"]));
|
||||
},
|
||||
checkEvent: function () { // event_sink with json is not yet support in FS
|
||||
console.log("check");
|
||||
var me = this;
|
||||
if (!this.get("listener")) {
|
||||
$.getJSON("/api/event_sink?command=create-listener&events=ALL&format=json", function(data){
|
||||
console.log(data);
|
||||
if (data.listener) {
|
||||
me.set("listener", data.listener["listen-id"]);
|
||||
}
|
||||
});
|
||||
}
|
||||
if (!me.get("listener")) return;
|
||||
|
||||
$.getJSON("/api/event_sink?command=check-listener&listen-id=" +
|
||||
me.get("listener") + "&format=json", function(data){
|
||||
console.log(data);
|
||||
if (!data.listener) {
|
||||
me.set("listener", undefined);
|
||||
} else {
|
||||
data.events.forEach(function(e) {
|
||||
eventCallback(e);
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
checkXMLEvent: function() {
|
||||
console.log("check XML Event");
|
||||
var me = this;
|
||||
if (!this.get("listener")) {
|
||||
$.get("/api/event_sink?command=create-listener&events=ALL", function(data){
|
||||
// console.log(data);
|
||||
var listen_id = data.getElementsByTagName("listen-id")[0];
|
||||
if (listen_id) {
|
||||
me.set("listener", listen_id.textContent);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (!me.get("listener")) return;
|
||||
|
||||
$.get("/api/event_sink?command=check-listener&listen-id=" + me.get("listener"), function(data){
|
||||
// console.log(data);
|
||||
var listener = data.getElementsByTagName("listener")[0];
|
||||
if (!listener) {
|
||||
me.set("listener", undefined);
|
||||
} else {
|
||||
var events = data.getElementsByTagName("event");
|
||||
for (var i=0; i<events.length; i++) {
|
||||
var e = {};
|
||||
var headers = events[i].getElementsByTagName("headers")[0];
|
||||
for (var j=0; j<headers.childNodes.length; j++) {
|
||||
e[headers.childNodes[j].nodeName] = headers.childNodes[j].textContent;
|
||||
}
|
||||
// console.log(e);
|
||||
eventCallback(e);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
App.applicationsController = Ember.ArrayController.create({
|
||||
content: [],
|
||||
init: function(){
|
||||
},
|
||||
load: function() {
|
||||
var me = this;
|
||||
$.getJSON("/txtapi/show?application%20as%20json", function(data){
|
||||
// var channels = JSON.parse(data);
|
||||
console.log(data.row_count);
|
||||
me.set('total', data.row_count);
|
||||
me.content.clear();
|
||||
if (data.row_count == 0) return;
|
||||
|
||||
me.pushObjects(data.rows);
|
||||
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
App.showEndpointsController = Ember.ArrayController.create({
|
||||
content: [],
|
||||
init: function(){
|
||||
},
|
||||
load: function() {
|
||||
var me = this;
|
||||
$.getJSON("/txtapi/show?endpoints%20as%20json", function(data){
|
||||
// var channels = JSON.parse(data);
|
||||
console.log(data.row_count);
|
||||
me.set('total', data.row_count);
|
||||
me.content.clear();
|
||||
if (data.row_count == 0) return;
|
||||
|
||||
me.pushObjects(data.rows);
|
||||
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
App.showCodecsController = Ember.ArrayController.create({
|
||||
content: [],
|
||||
init: function(){
|
||||
},
|
||||
load: function() {
|
||||
var me = this;
|
||||
$.getJSON("/txtapi/show?codec%20as%20json", function(data){
|
||||
// var channels = JSON.parse(data);
|
||||
console.log(data.row_count);
|
||||
me.set('total', data.row_count);
|
||||
me.content.clear();
|
||||
if (data.row_count == 0) return;
|
||||
|
||||
me.pushObjects(data.rows);
|
||||
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
App.usersController = Ember.ArrayController.create({
|
||||
content: [],
|
||||
init: function(){
|
||||
},
|
||||
load: function() {
|
||||
var me = this;
|
||||
$.get("/txtapi/list_users", function(data){
|
||||
// var channels = JSON.parse(data);
|
||||
lines = data.split("\n");
|
||||
me.content.clear();
|
||||
var users = [];
|
||||
for (var i=1; i<lines.length; i++) {
|
||||
var line = lines[i];
|
||||
var fields = line.split("|");
|
||||
if (fields.length == 1) break;
|
||||
var user = {
|
||||
id: fields.shift(),
|
||||
context: fields.shift(),
|
||||
domain: fields.shift(),
|
||||
group: fields.shift(),
|
||||
contact: fields.shift(),
|
||||
callgroup: fields.shift(),
|
||||
cid_name: fields.shift(),
|
||||
cid_number: fields.shift()
|
||||
}
|
||||
// me.pushObject(App.User.create(user));
|
||||
users.push(App.User.create(user));
|
||||
}
|
||||
me.pushObjects(users);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
App.initialize();
|
||||
|
||||
|
||||
function eventCallback(data) {
|
||||
console.log(data["Event-Name"]);
|
||||
if (data["Event-Name"] == "CHANNEL_CREATE") {
|
||||
var channel = {
|
||||
uuid: data["Unique-ID"],
|
||||
cid_num: data["Caller-Caller-ID-Number"],
|
||||
dest: data["Caller-Destination-Number"],
|
||||
callstate: data["Channel-Call-State"],
|
||||
direction: data["Call-Direction"]
|
||||
}
|
||||
App.channelsController.pushObject(App.Channel.create(channel));
|
||||
} else if (data["Event-Name"] == "CHANNEL_HANGUP_COMPLETE") {
|
||||
App.channelsController.delete(data["Unique-ID"]);
|
||||
} else if (data["Event-Name"] == "CHANNEL_CALLSTATE") {
|
||||
var obj = App.channelsController.content.findProperty("uuid", data["Unique-ID"]);
|
||||
if (obj) {
|
||||
obj.set("callstate", data["Channel-Call-State"]);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
|
@ -0,0 +1,383 @@
|
|||
<!DOCTYPE html>
|
||||
<!--
|
||||
/*
|
||||
* The FreeSWITCH Portal Project
|
||||
* Copyright (C) 2013-2013, Seven Du <dujinfang@gmail.com>
|
||||
*
|
||||
* Version: MPL 1.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is The FreeSWITCH Portal Project Software/Application
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Seven Du <dujinfang@gmail.com>
|
||||
* Portions created by the Initial Developer are Copyright (C)
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Seven Du <dujinfang@gmail.com>
|
||||
*
|
||||
*
|
||||
* index.html -- The FreeSWITCH Portal Project
|
||||
*
|
||||
*/
|
||||
-->
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Bootstrap, from Twitter</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<meta name="description" content="">
|
||||
<meta name="author" content="">
|
||||
|
||||
<!-- Le styles -->
|
||||
<link href="assets/bootstrap/css/bootstrap.css" rel="stylesheet">
|
||||
<style>
|
||||
body {
|
||||
padding-top: 60px; /* 60px to make the container go all the way to the bottom of the topbar */
|
||||
}
|
||||
</style>
|
||||
<link href="assets/bootstrap/css/bootstrap-responsive.css" rel="stylesheet">
|
||||
|
||||
<!-- HTML5 shim, for IE6-8 support of HTML5 elements -->
|
||||
<!--[if lt IE 9]>
|
||||
<script src="assets/js/html5shiv.js"></script>
|
||||
<![endif]-->
|
||||
|
||||
<!-- Fav and touch icons -->
|
||||
<link rel="apple-touch-icon-precomposed" sizes="144x144" href="assets/ico/apple-touch-icon-144-precomposed.png">
|
||||
<link rel="apple-touch-icon-precomposed" sizes="114x114" href="assets/ico/apple-touch-icon-114-precomposed.png">
|
||||
<link rel="apple-touch-icon-precomposed" sizes="72x72" href="assets/ico/apple-touch-icon-72-precomposed.png">
|
||||
<link rel="apple-touch-icon-precomposed" href="assets/ico/apple-touch-icon-57-precomposed.png">
|
||||
<link rel="shortcut icon" href="assets/ico/favicon.png">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<div class="navbar navbar-inverse navbar-fixed-top">
|
||||
<div class="navbar-inner">
|
||||
<div class="container">
|
||||
<button type="button" class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
|
||||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
</button>
|
||||
<a class="brand" href="#">FreeSWITCH Portal</a>
|
||||
<div class="pull-right" id='ws-status' style="padding-top:5px"></div>
|
||||
<div class="nav-collapse collapse">
|
||||
<ul class="nav">
|
||||
<li class="active"><a href="#">Home</a></li>
|
||||
<li><a id="menu-users" href="#users">Users</a></li>
|
||||
<li><a id="menu-calls" href="#calls">Calls</a></li>
|
||||
<li><a id="menu-channels" href="#channels">Channels</a></li>
|
||||
<li><a href="#show">Show</a></li>
|
||||
<li><a href="#about">About</a></li>
|
||||
</ul>
|
||||
</div><!--/.nav-collapse -->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="container" id="container">
|
||||
<div id="calls" style="display:none"></div>
|
||||
<div id="channels" style="display:none"></div>
|
||||
</div> <!-- /container -->
|
||||
|
||||
<div id="aa"></div>
|
||||
<script type="text/x-handlebars" data-template-name="index">
|
||||
<h1>Welcome to FreeSWITCH Portal</h1>
|
||||
Welcome
|
||||
</script>
|
||||
|
||||
<script type="text/x-handlebars" data-template-name="showApplications">
|
||||
<h1>Applications</h1>
|
||||
<div>
|
||||
<table class="table">
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
<th>Description</th>
|
||||
<th>Syntax</th>
|
||||
<th>iKey</th>
|
||||
</tr>
|
||||
{{#each App.applicationsController.content}}
|
||||
<tr>
|
||||
<td>{{ name }}</td>
|
||||
<td>{{ description }}</td>
|
||||
<td>{{ syntax }}</td>
|
||||
<td>{{ ikey }}</td>
|
||||
</tr>
|
||||
{{/each}}
|
||||
</table>
|
||||
</div>
|
||||
</script>
|
||||
|
||||
<script type="text/x-handlebars" data-template-name="showEndpoints">
|
||||
<h1>Endpoints</h1>
|
||||
<div>
|
||||
<table class="table">
|
||||
<tr>
|
||||
<th>Type</th>
|
||||
<th>Name</th>
|
||||
<th>iKey</th>
|
||||
</tr>
|
||||
{{#each App.showEndpointsController.content}}
|
||||
<tr>
|
||||
<td>{{ type }}</td>
|
||||
<td>{{ name }}</td>
|
||||
<td>{{ ikey }}</td>
|
||||
</tr>
|
||||
{{/each}}
|
||||
</table>
|
||||
</div>
|
||||
</script>
|
||||
|
||||
<script type="text/x-handlebars" data-template-name="showCodecs">
|
||||
<h1>Codecs</h1>
|
||||
<div>
|
||||
<table class="table">
|
||||
<tr>
|
||||
<th>Type</th>
|
||||
<th>Name</th>
|
||||
<th>iKey</th>
|
||||
</tr>
|
||||
{{#each App.showCodecsController.content}}
|
||||
<tr>
|
||||
<td>{{ type }}</td>
|
||||
<td>{{ name }}</td>
|
||||
<td>{{ ikey }}</td>
|
||||
</tr>
|
||||
{{/each}}
|
||||
</table>
|
||||
</div>
|
||||
</script>
|
||||
|
||||
<script type="text/x-handlebars" data-template-name="showFiles">
|
||||
Unimplemented
|
||||
</script>
|
||||
|
||||
<script type="text/x-handlebars" data-template-name="showAPIs">
|
||||
Unimplemented
|
||||
</script>
|
||||
|
||||
<script type="text/x-handlebars" data-template-name="show">
|
||||
<h1>Show</h1>
|
||||
{{#linkTo "showApplications"}} Applications {{/linkTo}} |
|
||||
{{#linkTo "showEndpoints"}} Endpoints {{/linkTo}} |
|
||||
{{#linkTo "showCodecs"}} Codecs {{/linkTo}} |
|
||||
{{#linkTo "showFiles"}} Files {{/linkTo}} |
|
||||
{{#linkTo "showAPIs"}} APIs {{/linkTo}}
|
||||
</script>
|
||||
|
||||
<script type="text/x-handlebars" data-template-name="about">
|
||||
<h1>About FreeSWITCH Portal</h1>
|
||||
<p>
|
||||
The FreeSWITCH Portal Project is Created by <a href="http://www.dujinfang.com">Seven Du</a>.
|
||||
Available with MPL1.1 licence - Same as FreeSWITCH.
|
||||
</p>
|
||||
</script>
|
||||
|
||||
<script type="text/x-handlebars" data-template-name="users">
|
||||
<h1>Users</h1>
|
||||
<div>
|
||||
<table class="table">
|
||||
<tr>
|
||||
<th>ID</th>
|
||||
<th>Context</th>
|
||||
<th>Domain</th>
|
||||
<th>Group</th>
|
||||
<th>Contact</th>
|
||||
<th>Callgroup</th>
|
||||
<th>Caller ID Name</th>
|
||||
<th>Caller ID Number</th>
|
||||
</tr>
|
||||
{{#each App.usersController.content}}
|
||||
<tr>
|
||||
<td>{{ id }}</td>
|
||||
<td>{{ context }}</td>
|
||||
<td>{{ domain }}</td>
|
||||
<td>{{ group }}</td>
|
||||
<td>{{ contact }}</td>
|
||||
<td>{{ callgroup }}</td>
|
||||
<td>{{ cid_name }}</td>
|
||||
<td>{{ cid_number }}</td>
|
||||
</tr>
|
||||
{{/each}}
|
||||
</table>
|
||||
</div>
|
||||
</script>
|
||||
|
||||
<script type="text/x-handlebars" data-template-name="calls">
|
||||
<div class="pull-right">
|
||||
<label><input type="checkbox" id="auto_update_calls" value="1" onclick="auto_update_calls();">Auto Update</label>
|
||||
</div>
|
||||
|
||||
<h1>Calls</h1>
|
||||
|
||||
<div>
|
||||
<table class="table">
|
||||
<tr>
|
||||
<th>Call UUID</th>
|
||||
<th>CID</th>
|
||||
<th>Dest</th>
|
||||
<th>Call State</th>
|
||||
<th>Direction / Created</th>
|
||||
</tr>
|
||||
{{#each App.callsController.content}}
|
||||
<tr>
|
||||
<td>{{uuid}} <br>{{ b_uuid }}</td>
|
||||
<td>{{ cid_num }}<br>{{ b_cid_num }}</td>
|
||||
<td>{{ dest }}<br>{{ b_dest }}</td>
|
||||
<td>{{ callstate }}<br>{{ b_callstate }}</td>
|
||||
<td>{{ direction }} / {{ b_direction }}<br>
|
||||
<a href='#' {{action "dump" uuid target="App.callsController"}}>{{created}}</a>
|
||||
<!--<a href='#' {{action "raw" uuid target="App.callsController"}}>Raw</a>-->
|
||||
</td>
|
||||
</tr>
|
||||
{{/each}}
|
||||
</table>
|
||||
</div>
|
||||
|
||||
</script>
|
||||
|
||||
<script type="text/x-handlebars" data-template-name="channels">
|
||||
|
||||
<h1>Channels</h1>
|
||||
|
||||
<div>
|
||||
|
||||
<table class="table">
|
||||
<tr>
|
||||
<th>Call UUID</th>
|
||||
<th>CID</th>
|
||||
<th>Dest</th>
|
||||
<th>Call State</th>
|
||||
<th>Direction / Created</th>
|
||||
</tr>
|
||||
{{#each App.channelsController.content}}
|
||||
<tr>
|
||||
<td>{{uuid}}</td>
|
||||
<td>{{ cid_num }}</td>
|
||||
<td>{{ dest }}<br></td>
|
||||
<td>{{ callstate }}</td>
|
||||
<td>{{ direction }}<br>
|
||||
<a href='#' {{action "dump" uuid target="App.channelsController"}}>{{created}}</a>
|
||||
</td>
|
||||
</tr>
|
||||
{{/each}}
|
||||
</table>
|
||||
|
||||
</div>
|
||||
|
||||
</script>
|
||||
<!-- Le javascript
|
||||
================================================== -->
|
||||
<!-- Placed at the end of the document so the pages load faster -->
|
||||
<script src="assets/js/jquery-1.9.1.min.js"></script>
|
||||
<script src="assets/js/handlebars.js"></script>
|
||||
<script src="assets/js/ember-1.0.0-rc.1.js"></script>
|
||||
<script src="assets/js/ember-data.js"></script>
|
||||
<script src="assets/js/fsportal.js"></script>
|
||||
<!--
|
||||
<script src="assets/js/bootstrap-transition.js"></script>
|
||||
<script src="assets/js/bootstrap-alert.js"></script>
|
||||
<script src="assets/js/bootstrap-modal.js"></script>
|
||||
<script src="assets/js/bootstrap-dropdown.js"></script>
|
||||
<script src="assets/js/bootstrap-scrollspy.js"></script>
|
||||
<script src="assets/js/bootstrap-tab.js"></script>
|
||||
<script src="assets/js/bootstrap-tooltip.js"></script>
|
||||
<script src="assets/js/bootstrap-popover.js"></script>
|
||||
<script src="assets/js/bootstrap-button.js"></script>
|
||||
<script src="assets/js/bootstrap-collapse.js"></script>
|
||||
<script src="assets/js/bootstrap-carousel.js"></script>
|
||||
<script src="assets/js/bootstrap-typeahead.js"></script>
|
||||
-->
|
||||
<script type="text/javascript">
|
||||
|
||||
function auto_update_calls() {
|
||||
var x = $('#auto_update_calls')[0];
|
||||
if (typeof x != "undefined" && x.checked) {
|
||||
console.log("tick")
|
||||
App.callsController.load();
|
||||
setTimeout(auto_update_calls, 2000);
|
||||
}
|
||||
}
|
||||
|
||||
// $("#menu-channels").click(function(e){
|
||||
// e.preventDefault();
|
||||
// App.channelsController.load();
|
||||
// $('#calls').hide();
|
||||
// $('#channels').show();
|
||||
// });
|
||||
|
||||
// $("#menu-calls").click(function(e){
|
||||
// e.preventDefault();
|
||||
// App.callsController.load();
|
||||
// $('#channels').hide();
|
||||
// $('#calls').show();
|
||||
// });
|
||||
|
||||
// var callsView = Ember.View.create({
|
||||
// templateName: 'calls',
|
||||
// name: "callsView"
|
||||
// });
|
||||
|
||||
// // $('#container').html('');
|
||||
// callsView.appendTo('#calls');
|
||||
|
||||
// var channelsView = Ember.View.create({
|
||||
// templateName: 'channels',
|
||||
// name: "channelsView"
|
||||
// });
|
||||
// channelsView.appendTo('#channels');
|
||||
|
||||
function dump_call(uuid) {
|
||||
obj = App.callsController.content.findProperty("uuid", uuid);
|
||||
console.log(obj);
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<script type="text/javascript">
|
||||
|
||||
var socket = new WebSocket("ws://localhost:8086/socket", "websocket");
|
||||
|
||||
try {
|
||||
socket.onopen = function() {
|
||||
$('#ws-status').html('Socket Connected').css("color", "green");
|
||||
// socket.send("event json all");
|
||||
socket.send("event json CHANNEL_CREATE");
|
||||
socket.send("event json CHANNEL_HANGUP_COMPLETE");
|
||||
socket.send("event json CHANNEL_CALLSTATE");
|
||||
}
|
||||
|
||||
socket.onmessage =function(msg) {
|
||||
// console.log(msg.data);
|
||||
var data = JSON.parse(msg.data);
|
||||
console.log(data["Event-Name"]);
|
||||
|
||||
eventCallback(data);
|
||||
}
|
||||
|
||||
socket.onclose = function(){
|
||||
$('#ws-status').html('Socket Disconnected!').css("color", "red");
|
||||
console.log("socket disconnected, fallback to event_sink");
|
||||
// setInterval("App.channelsController.checkEvent()", 2000);
|
||||
setInterval("App.channelsController.checkXMLEvent()", 2000);
|
||||
}
|
||||
} catch(exception) {
|
||||
alert('Error' + exception);
|
||||
}
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
Loading…
Reference in New Issue