mirror of
https://github.com/signalwire/freeswitch.git
synced 2025-06-07 13:35:00 +00:00
add portal, a nice GUI with pure html and javascript
This commit is contained in:
parent
3807dcb129
commit
c16843dc51
25
htdocs/portal/LICENCE
Normal file
25
htdocs/portal/LICENCE
Normal file
@ -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>
|
64
htdocs/portal/README.md
Normal file
64
htdocs/portal/README.md
Normal file
@ -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.
|
1109
htdocs/portal/assets/bootstrap/css/bootstrap-responsive.css
vendored
Normal file
1109
htdocs/portal/assets/bootstrap/css/bootstrap-responsive.css
vendored
Normal file
File diff suppressed because it is too large
Load Diff
9
htdocs/portal/assets/bootstrap/css/bootstrap-responsive.min.css
vendored
Normal file
9
htdocs/portal/assets/bootstrap/css/bootstrap-responsive.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
6158
htdocs/portal/assets/bootstrap/css/bootstrap.css
vendored
Normal file
6158
htdocs/portal/assets/bootstrap/css/bootstrap.css
vendored
Normal file
File diff suppressed because it is too large
Load Diff
9
htdocs/portal/assets/bootstrap/css/bootstrap.min.css
vendored
Normal file
9
htdocs/portal/assets/bootstrap/css/bootstrap.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
Binary file not shown.
After Width: | Height: | Size: 8.6 KiB |
BIN
htdocs/portal/assets/bootstrap/img/glyphicons-halflings.png
Normal file
BIN
htdocs/portal/assets/bootstrap/img/glyphicons-halflings.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 12 KiB |
2276
htdocs/portal/assets/bootstrap/js/bootstrap.js
vendored
Normal file
2276
htdocs/portal/assets/bootstrap/js/bootstrap.js
vendored
Normal file
File diff suppressed because it is too large
Load Diff
6
htdocs/portal/assets/bootstrap/js/bootstrap.min.js
vendored
Normal file
6
htdocs/portal/assets/bootstrap/js/bootstrap.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
26839
htdocs/portal/assets/js/ember-1.0.0-rc.1.js
Normal file
26839
htdocs/portal/assets/js/ember-1.0.0-rc.1.js
Normal file
File diff suppressed because it is too large
Load Diff
20
htdocs/portal/assets/js/ember-1.0.0-rc.1.min.js
vendored
Normal file
20
htdocs/portal/assets/js/ember-1.0.0-rc.1.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
7832
htdocs/portal/assets/js/ember-data.js
Normal file
7832
htdocs/portal/assets/js/ember-data.js
Normal file
File diff suppressed because it is too large
Load Diff
373
htdocs/portal/assets/js/fsportal.js
Normal file
373
htdocs/portal/assets/js/fsportal.js
Normal file
@ -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"]);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
2201
htdocs/portal/assets/js/handlebars.js
Normal file
2201
htdocs/portal/assets/js/handlebars.js
Normal file
File diff suppressed because it is too large
Load Diff
5
htdocs/portal/assets/js/jquery-1.9.1.min.js
vendored
Normal file
5
htdocs/portal/assets/js/jquery-1.9.1.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
383
htdocs/portal/index.html
Normal file
383
htdocs/portal/index.html
Normal file
@ -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…
x
Reference in New Issue
Block a user