Change-Id: I86d48c11bcb3fdda2193df2d00de61d24123467achanges/98/21398/6
parent
803128ea22
commit
6071b43b49
@ -0,0 +1,15 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
case "$1" in
|
||||||
|
*)
|
||||||
|
cp ./dev-config/ngcp-panel_csc.customtt.tt2 /etc/ngcp-config/templates/etc/nginx/sites-available/
|
||||||
|
cp ./dev-config/ngcp-panel_params.customtt.tt2 /etc/ngcp-config/templates/etc/nginx/
|
||||||
|
|
||||||
|
ngcpcfg set /etc/ngcp-config/config.yml www_admin.http_csc.csc_js_enable=yes
|
||||||
|
ngcpcfg set /etc/ngcp-config/config.yml rtcengine.enable=yes
|
||||||
|
ngcpcfg set /etc/ngcp-config/config.yml pbx.enable=yes
|
||||||
|
ngcpcfg set /etc/ngcp-config/config.yml www_admin.privileges.subscriberadmin.subscribers.0=write
|
||||||
|
|
||||||
|
ngcpcfg apply 'csc, pbx, rtcengine'
|
||||||
|
;;
|
||||||
|
esac
|
@ -0,0 +1,229 @@
|
|||||||
|
[%
|
||||||
|
PROCESS '/usr/lib/ngcp-ngcpcfg/get_hostname';
|
||||||
|
hostname = out;
|
||||||
|
|
||||||
|
argv.host=hostname; argv.type='sip_ext';
|
||||||
|
PROCESS '/usr/lib/ngcp-ngcpcfg/get_all_shared_ips_for_host';
|
||||||
|
sip_ext_ips = out;
|
||||||
|
|
||||||
|
IF !sip_ext_ips.size;
|
||||||
|
argv.type='sip_ext';
|
||||||
|
PROCESS '/usr/lib/ngcp-ngcpcfg/get_all_ips_for_host';
|
||||||
|
sip_ext_ips = out;
|
||||||
|
END;
|
||||||
|
ext_ip = sip_ext_ips.0;
|
||||||
|
|
||||||
|
argv.type='web_ext';
|
||||||
|
PROCESS '/usr/lib/ngcp-ngcpcfg/get_all_shared_ips_for_host';
|
||||||
|
web_ext_ips = out;
|
||||||
|
PROCESS '/usr/lib/ngcp-ngcpcfg/get_all_shared_v6ips_for_host';
|
||||||
|
web_ext_v6ips = out;
|
||||||
|
|
||||||
|
argv.type='web_ext';
|
||||||
|
PROCESS '/usr/lib/ngcp-ngcpcfg/get_all_ips_for_host';
|
||||||
|
web_ext_ips = out.merge(web_ext_ips);
|
||||||
|
|
||||||
|
argv.type='web_ext';
|
||||||
|
PROCESS '/usr/lib/ngcp-ngcpcfg/get_all_v6ips_for_host';
|
||||||
|
web_ext_v6ips = out.merge(web_ext_v6ips);
|
||||||
|
|
||||||
|
argv.role='mgmt';
|
||||||
|
PROCESS '/usr/lib/ngcp-ngcpcfg/has_role';
|
||||||
|
is_mgmt = out;
|
||||||
|
|
||||||
|
argv.role='proxy'; argv.type='sip_int';
|
||||||
|
PROCESS '/usr/lib/ngcp-ngcpcfg/get_all_shared_ips';
|
||||||
|
sip_int_ips = out;
|
||||||
|
IF !sip_int_ips.size;
|
||||||
|
argv.type='sip_int';
|
||||||
|
PROCESS '/usr/lib/ngcp-ngcpcfg/get_all_ips_for_host';
|
||||||
|
sip_int_ips = out;
|
||||||
|
END;
|
||||||
|
-%]
|
||||||
|
[% IF www_admin.enable == 'yes' && is_mgmt -%]
|
||||||
|
[% IF www_admin.http_admin.port != 80 && www_admin.http_csc.port != 80 -%]
|
||||||
|
server {
|
||||||
|
listen [::]:80 ipv6only=off;
|
||||||
|
|
||||||
|
location /handbook {
|
||||||
|
return 301 http://$host:[% www_admin.http_admin.port %]$request_uri;
|
||||||
|
}
|
||||||
|
|
||||||
|
location /login/subscriber {
|
||||||
|
return 301 https://$host:[% www_admin.http_csc.port %]$request_uri;
|
||||||
|
}
|
||||||
|
|
||||||
|
location /login/admin {
|
||||||
|
return 301 https://$host:[% www_admin.http_admin.port %]$request_uri;
|
||||||
|
}
|
||||||
|
|
||||||
|
location / {
|
||||||
|
return 301 https://$host:[% www_admin.http_csc.port %]$request_uri;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
[% END -%]
|
||||||
|
[% IF rtcengine.enable == 'yes' -%]
|
||||||
|
upstream rtc_ws {
|
||||||
|
[% FOREACH ip IN sip_int_ips -%]
|
||||||
|
[% IF ip -%]
|
||||||
|
server [% ip %]:[% rtcengine.port %];
|
||||||
|
[% END -%]
|
||||||
|
[% END -%]
|
||||||
|
}
|
||||||
|
[% END -%]
|
||||||
|
|
||||||
|
server {
|
||||||
|
[% FOREACH ip IN web_ext_ips -%]
|
||||||
|
[% IF ip -%]
|
||||||
|
listen [% ip %]:[% www_admin.http_csc.port %];
|
||||||
|
[% END -%]
|
||||||
|
[% END -%]
|
||||||
|
[% FOREACH ip IN web_ext_v6ips -%]
|
||||||
|
[% IF ip -%]
|
||||||
|
listen [[% ip %]]:[% www_admin.http_csc.port %];
|
||||||
|
[% END -%]
|
||||||
|
[% END -%]
|
||||||
|
server_name [% www_admin.http_csc.servername.remove('\"') %];
|
||||||
|
|
||||||
|
ssl_certificate [% www_admin.http_csc.sslcertfile %];
|
||||||
|
ssl_certificate_key [% www_admin.http_csc.sslcertkeyfile %];
|
||||||
|
include /etc/nginx/ssl_params;
|
||||||
|
client_max_body_size [% www_admin.filesize_limit ? www_admin.filesize_limit : "128M"%];
|
||||||
|
|
||||||
|
location ~* /login(/)?$ {
|
||||||
|
return 301 /login/subscriber;
|
||||||
|
}
|
||||||
|
|
||||||
|
location /login/admin {
|
||||||
|
return 301 https://$host:[% www_admin.http_admin.port %]$request_uri;
|
||||||
|
}
|
||||||
|
|
||||||
|
location /favicon.ico {
|
||||||
|
alias /usr/share/ngcp-panel/static/favicon.ico;
|
||||||
|
}
|
||||||
|
|
||||||
|
location /static {
|
||||||
|
root /usr/share/ngcp-panel;
|
||||||
|
}
|
||||||
|
|
||||||
|
[% IF rtcengine.enable == 'yes' -%]
|
||||||
|
location ~* /rtc/api(/)?$ {
|
||||||
|
|
||||||
|
add_header 'Access-Control-Allow-Origin' '*' always;
|
||||||
|
add_header 'Access-Control-Allow-Headers' 'Authorization,DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type' always;
|
||||||
|
add_header 'Access-Control-Allow-Methods' 'POST, GET, PUT, DELETE, PATCH, OPTIONS' always;
|
||||||
|
add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range,Location';
|
||||||
|
|
||||||
|
if ($request_method = 'OPTIONS') {
|
||||||
|
add_header 'Access-Control-Allow-Origin' '*' always;
|
||||||
|
add_header 'Access-Control-Allow-Headers' 'Authorization,DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type' always;
|
||||||
|
add_header 'Access-Control-Allow-Methods' 'POST, GET, PUT, DELETE, PATCH, OPTIONS' always;
|
||||||
|
add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range,Location';
|
||||||
|
add_header 'Access-Control-Max-Age' '1728000' always;
|
||||||
|
add_header 'Content-Type' 'text/plain charset=UTF-8' always;
|
||||||
|
add_header 'Content-Length' '0' always;
|
||||||
|
return 204;
|
||||||
|
}
|
||||||
|
|
||||||
|
### Set proxy ####
|
||||||
|
proxy_max_temp_file_size 0;
|
||||||
|
proxy_connect_timeout 43200000;
|
||||||
|
proxy_send_timeout 43200000;
|
||||||
|
proxy_read_timeout 43200000;
|
||||||
|
|
||||||
|
proxy_buffer_size 4k;
|
||||||
|
proxy_buffers 4 32k;
|
||||||
|
proxy_busy_buffers_size 64k;
|
||||||
|
proxy_temp_file_write_size 64k;
|
||||||
|
|
||||||
|
### Set headers ####
|
||||||
|
proxy_set_header Upgrade $http_upgrade;
|
||||||
|
proxy_set_header Connection $connection_upgrade;
|
||||||
|
proxy_set_header Accept-Encoding "";
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
|
proxy_set_header X-Server-IP $server_addr;
|
||||||
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
|
proxy_set_header X-Forwarded-Proto $scheme;
|
||||||
|
add_header Front-End-Https on;
|
||||||
|
|
||||||
|
proxy_pass http://rtc_ws;
|
||||||
|
proxy_http_version 1.1;
|
||||||
|
}
|
||||||
|
|
||||||
|
location /rtc/files {
|
||||||
|
|
||||||
|
add_header 'Access-Control-Allow-Origin' '*' always;
|
||||||
|
add_header 'Access-Control-Allow-Headers' 'Authorization,DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type' always;
|
||||||
|
add_header 'Access-Control-Allow-Methods' 'POST, GET, PUT, DELETE, PATCH, OPTIONS' always;
|
||||||
|
add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range,Location';
|
||||||
|
|
||||||
|
if ($request_method = 'OPTIONS') {
|
||||||
|
add_header 'Access-Control-Allow-Origin' '*' always;
|
||||||
|
add_header 'Access-Control-Allow-Headers' 'Authorization,DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type' always;
|
||||||
|
add_header 'Access-Control-Allow-Methods' 'POST, GET, PUT, DELETE, PATCH, OPTIONS' always;
|
||||||
|
add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range,Location';
|
||||||
|
add_header 'Access-Control-Max-Age' '1728000' always;
|
||||||
|
add_header 'Content-Type' 'text/plain charset=UTF-8' always;
|
||||||
|
add_header 'Content-Length' '0' always;
|
||||||
|
return 204;
|
||||||
|
}
|
||||||
|
|
||||||
|
rewrite /rtc/files/(.*) /$1 break;
|
||||||
|
index index.html;
|
||||||
|
root /usr/share/ngcp-rtcengine/public/;
|
||||||
|
}
|
||||||
|
[% END -%]
|
||||||
|
[% IF rtcengine.expose_provisioning_api == 'yes' %]
|
||||||
|
location /rtc/prov/ {
|
||||||
|
rewrite /rtc/prov/(.*) /$1 break;
|
||||||
|
proxy_pass http://rtc_ws;
|
||||||
|
proxy_http_version 1.1;
|
||||||
|
}
|
||||||
|
[% END %]
|
||||||
|
|
||||||
|
|
||||||
|
location /api {
|
||||||
|
include /etc/nginx/ngcp-panel_params;
|
||||||
|
# fastcgi_param SSL_CLIENT_CERT $ssl_client_raw_cert;
|
||||||
|
# fastcgi_param SSL_CLIENT_M_SERIAL $ssl_client_serial;
|
||||||
|
# fastcgi_param SSL_CLIENT_M_DN $ssl_client_s_dn;
|
||||||
|
fastcgi_param NGCP_API_REALM "subscriber";
|
||||||
|
proxy_buffers 8 1024k;
|
||||||
|
proxy_buffer_size 1024k;
|
||||||
|
proxy_busy_buffers_size 1024k;
|
||||||
|
fastcgi_buffers 8 16k;
|
||||||
|
fastcgi_buffer_size 32k;
|
||||||
|
}
|
||||||
|
|
||||||
|
location / {
|
||||||
|
include /etc/nginx/ngcp-panel_params;
|
||||||
|
}
|
||||||
|
|
||||||
|
location ~ ^/wss/xmpp/(.*)$ {
|
||||||
|
proxy_pass https://127.0.0.1:5281/xmpp-websocket/$1;
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
proxy_buffering off;
|
||||||
|
tcp_nodelay on;
|
||||||
|
proxy_http_version 1.1;
|
||||||
|
proxy_set_header Upgrade $http_upgrade;
|
||||||
|
proxy_set_header Connection "upgrade";
|
||||||
|
}
|
||||||
|
|
||||||
|
location ~ ^/wss/sip/(.*)$ {
|
||||||
|
proxy_pass https://[% ext_ip %]:[% kamailio.lb.tls.port %]/ws/$1;
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
proxy_buffering off;
|
||||||
|
tcp_nodelay on;
|
||||||
|
proxy_http_version 1.1;
|
||||||
|
proxy_set_header Upgrade $http_upgrade;
|
||||||
|
proxy_set_header Connection "upgrade";
|
||||||
|
}
|
||||||
|
|
||||||
|
[% IF www_admin.http_csc.csc_js_enable == "yes" -%]
|
||||||
|
location /csc {
|
||||||
|
root /usr/share/ngcp-csc;
|
||||||
|
}
|
||||||
|
[% END -%]
|
||||||
|
}
|
||||||
|
[% END -%]
|
@ -0,0 +1,21 @@
|
|||||||
|
include /etc/nginx/fastcgi_params;
|
||||||
|
# Catalyst requires setting PATH_INFO (instead of SCRIPT_NAME) to $fastcgi_script_name
|
||||||
|
fastcgi_param SCRIPT_NAME '';
|
||||||
|
fastcgi_param PATH_INFO $fastcgi_script_name;
|
||||||
|
fastcgi_pass unix:/var/run/fastcgi/ngcp-panel.sock;
|
||||||
|
|
||||||
|
add_header 'Access-Control-Allow-Origin' '*' always;
|
||||||
|
add_header 'Access-Control-Allow-Headers' 'Authorization,DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type' always;
|
||||||
|
add_header 'Access-Control-Allow-Methods' 'POST, GET, PUT, DELETE, PATCH, OPTIONS' always;
|
||||||
|
add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range,Location';
|
||||||
|
|
||||||
|
if ($request_method = 'OPTIONS') {
|
||||||
|
add_header 'Access-Control-Allow-Origin' '*' always;
|
||||||
|
add_header 'Access-Control-Allow-Headers' 'Authorization,DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type' always;
|
||||||
|
add_header 'Access-Control-Allow-Methods' 'POST, GET, PUT, DELETE, PATCH, OPTIONS' always;
|
||||||
|
add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range,Location';
|
||||||
|
add_header 'Access-Control-Max-Age' '1728000' always;
|
||||||
|
add_header 'Content-Type' 'text/plain charset=UTF-8' always;
|
||||||
|
add_header 'Content-Length' '0' always;
|
||||||
|
return 204;
|
||||||
|
}
|
@ -0,0 +1,271 @@
|
|||||||
|
<template>
|
||||||
|
<div ref="config" class="csc-pbx-device-config justify-center row">
|
||||||
|
<div class="csc-pbx-device-canvas" :style="canvasStyles">
|
||||||
|
<div ref="imageWrapper" class="csc-pbx-device-image" :style="imageWrapperStyles">
|
||||||
|
<img ref="image" :src="imageUrl" @load="imageLoaded" :style="imageStyles" />
|
||||||
|
</div>
|
||||||
|
<div :class="spotClasses(index)" v-for="(key,index) in keys"
|
||||||
|
:key="index" :style="spotPosition(key)">
|
||||||
|
<span>{{ index + 1 }}</span>
|
||||||
|
<q-popover ref="keyPopover">
|
||||||
|
<div class="csc-pbx-key-popover">
|
||||||
|
<q-field v-if="getLineByKey(index) !== null" :icon="getIconByKey(index)">
|
||||||
|
<q-input :value="getLineByKey(index).subscriber.display_name" readonly :float-label="'Key ' + (index + 1)" />
|
||||||
|
</q-field>
|
||||||
|
<q-field v-else >
|
||||||
|
<q-input value="Empty" readonly :float-label="'Key ' + (index + 1)" />
|
||||||
|
</q-field>
|
||||||
|
<q-btn icon="clear" :small="!isMobile" class="absolute-top-right"
|
||||||
|
@click="$refs.keyPopover[index].close()" flat round color="primary" />
|
||||||
|
</div>
|
||||||
|
</q-popover>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<q-window-resize-observable @resize="windowResize" />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
|
||||||
|
import _ from 'lodash'
|
||||||
|
import { QList, QItem, QItemMain, QItemTile, QTabs, QTab, Platform,
|
||||||
|
QTabPane, QChip, QWindowResizeObservable, QModal, QBtn, QPopover, QIcon, QField, QInput } from 'quasar-framework'
|
||||||
|
import { BoundingBox2D } from '../../../helpers/graphics'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'csc-pbx-device-config',
|
||||||
|
props: [
|
||||||
|
'device',
|
||||||
|
'loading',
|
||||||
|
],
|
||||||
|
components: {
|
||||||
|
QList, QItem, QItemMain, QItemTile, QTabs, QTab, Platform,
|
||||||
|
QTabPane, QChip, QWindowResizeObservable, QModal, QBtn, QPopover, QIcon, QField, QInput
|
||||||
|
},
|
||||||
|
data () {
|
||||||
|
return {
|
||||||
|
configWidth: 0,
|
||||||
|
imageDeltaX: 0,
|
||||||
|
imageScaleFactor: 1,
|
||||||
|
imageWidth: 0,
|
||||||
|
boundingBox: null,
|
||||||
|
scaledBoundingBox: null,
|
||||||
|
modalOpened: false,
|
||||||
|
selectedKey: null,
|
||||||
|
selectedKeyIndex: null,
|
||||||
|
selectedLine: null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
isMobile() {
|
||||||
|
return Platform.is.mobile;
|
||||||
|
},
|
||||||
|
imageUrl() {
|
||||||
|
return _.get(this.device, 'profile.modelFrontImageUrl');
|
||||||
|
},
|
||||||
|
keys() {
|
||||||
|
return _.get(this.device, 'profile.model.linerange[0].keys', []);
|
||||||
|
},
|
||||||
|
canvasStyles() {
|
||||||
|
return {
|
||||||
|
width: this.configWidth + "px"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
imageWrapperStyles() {
|
||||||
|
return {
|
||||||
|
width: this.configWidth + "px"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
imageStyles() {
|
||||||
|
return {
|
||||||
|
left: this.imageDeltaX + "px",
|
||||||
|
width: (this.imageWidth * this.imageScaleFactor) + "px"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
this.boundingBox = BoundingBox2D.createFromPoints(this.keys);
|
||||||
|
this.boundingBox.addMargin(40);
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
getLineByKey(key) {
|
||||||
|
let line = null;
|
||||||
|
this.device.lines.forEach(($line)=>{
|
||||||
|
if($line.key_num === key) {
|
||||||
|
line = $line;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return line;
|
||||||
|
},
|
||||||
|
openModal(key, index) {
|
||||||
|
this.$refs.modal.open();
|
||||||
|
this.selectedKey = key;
|
||||||
|
this.selectedKeyIndex = index + 1;
|
||||||
|
this.selectedLine = this.getLineByKey(index);
|
||||||
|
},
|
||||||
|
closeModal() {
|
||||||
|
this.$refs.modal.close();
|
||||||
|
this.selectedKey = null;
|
||||||
|
this.selectedKeyIndex = null;
|
||||||
|
},
|
||||||
|
windowResize() {
|
||||||
|
this.resize();
|
||||||
|
this.placeImage();
|
||||||
|
},
|
||||||
|
imageLoaded() {
|
||||||
|
this.resize();
|
||||||
|
this.placeImage();
|
||||||
|
},
|
||||||
|
resize() {
|
||||||
|
this.imageWidth = this.$refs.image.naturalWidth;
|
||||||
|
this.configWidth = this.$refs.config.clientWidth;
|
||||||
|
if(this.boundingBox !== null ) {
|
||||||
|
if (this.boundingBox.getWidth() > this.configWidth) {
|
||||||
|
this.imageScaleFactor = this.configWidth / this.boundingBox.getWidth();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.imageScaleFactor = 1;
|
||||||
|
}
|
||||||
|
this.scaledBoundingBox = this.boundingBox.clone();
|
||||||
|
this.scaledBoundingBox.scale(this.imageScaleFactor);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
placeImage() {
|
||||||
|
let configCenterX = this.configWidth / 2;
|
||||||
|
if (this.scaledBoundingBox !== null) {
|
||||||
|
this.imageDeltaX = -1 * this.scaledBoundingBox.getCenterX() + configCenterX;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
getScaleFactorX() {
|
||||||
|
if (_.isObject(this.$refs.image)) {
|
||||||
|
return this.$refs.image.width / this.$refs.image.naturalWidth;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
},
|
||||||
|
getScaleFactorY() {
|
||||||
|
if (_.isObject(this.$refs.image)) {
|
||||||
|
return this.$refs.image.height / this.$refs.image.naturalHeight;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
},
|
||||||
|
keyPointing(key) {
|
||||||
|
let pointing = {
|
||||||
|
left: 'right',
|
||||||
|
right: 'left',
|
||||||
|
top: 'down',
|
||||||
|
bottom: 'up'
|
||||||
|
};
|
||||||
|
return pointing[key.labelpos];
|
||||||
|
},
|
||||||
|
spotPosition(key) {
|
||||||
|
let deltaX = 0;
|
||||||
|
if(this.scaledBoundingBox !== null) {
|
||||||
|
deltaX = -1 * this.scaledBoundingBox.getCenterX() + this.configWidth / 2;
|
||||||
|
}
|
||||||
|
let width = 25 * this.imageScaleFactor;
|
||||||
|
let height = 25 * this.imageScaleFactor;
|
||||||
|
let x = (key.x * this.imageScaleFactor) + deltaX;
|
||||||
|
let y = (key.y * this.imageScaleFactor);
|
||||||
|
switch(key.labelpos){
|
||||||
|
case 'left':
|
||||||
|
y = y - height / 2;
|
||||||
|
x = x - width;
|
||||||
|
break;
|
||||||
|
case 'right':
|
||||||
|
y = y - height / 2;
|
||||||
|
break;
|
||||||
|
case 'top':
|
||||||
|
x = x - width / 2;
|
||||||
|
y = y - height;
|
||||||
|
break;
|
||||||
|
case 'bottom':
|
||||||
|
x = x - width / 2;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
top: y + "px",
|
||||||
|
left: x + "px",
|
||||||
|
width: width + "px",
|
||||||
|
height: height + "px",
|
||||||
|
position: 'absolute',
|
||||||
|
lineHeight: width + "px",
|
||||||
|
zIndex: 10
|
||||||
|
};
|
||||||
|
},
|
||||||
|
spotClasses(key) {
|
||||||
|
let classes = ['csc-pbx-device-button-spot', 'shadow-3'];
|
||||||
|
if(this.getLineByKey(key) !== null) {
|
||||||
|
classes.push('csc-pbx-device-button-active');
|
||||||
|
}
|
||||||
|
return classes;
|
||||||
|
},
|
||||||
|
getIconByKey(key) {
|
||||||
|
let line = this.getLineByKey(key);
|
||||||
|
if(line !== null && line.subscriber.is_pbx_group === true) {
|
||||||
|
return 'group';
|
||||||
|
}
|
||||||
|
else if(line !== null && line.subscriber.is_pbx_group === false) {
|
||||||
|
return 'person';
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return ''
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="stylus" rel="stylesheet/stylus">
|
||||||
|
@import '../../../themes/app.common'
|
||||||
|
|
||||||
|
$spotSize = 25px
|
||||||
|
|
||||||
|
.csc-pbx-device-key-details
|
||||||
|
padding 50px
|
||||||
|
position relative
|
||||||
|
|
||||||
|
.csc-pbx-device-config
|
||||||
|
position relative
|
||||||
|
.spot-modal-content
|
||||||
|
position relative
|
||||||
|
|
||||||
|
.csc-pbx-device-image
|
||||||
|
position relative
|
||||||
|
overflow hidden
|
||||||
|
img
|
||||||
|
display block
|
||||||
|
position relative
|
||||||
|
|
||||||
|
.csc-pbx-device-canvas
|
||||||
|
position: relative
|
||||||
|
|
||||||
|
.csc-pbx-key-popover-title
|
||||||
|
font-size 18px
|
||||||
|
font-weight 400
|
||||||
|
letter-spacing normal
|
||||||
|
line-height 1.8rem
|
||||||
|
|
||||||
|
.csc-pbx-device-button-spot
|
||||||
|
border-radius: 50%;
|
||||||
|
width $spotSize
|
||||||
|
height $spotSize
|
||||||
|
background-color white
|
||||||
|
line-height $spotSize
|
||||||
|
color $primary
|
||||||
|
text-align center
|
||||||
|
cursor pointer
|
||||||
|
font-weight bold
|
||||||
|
|
||||||
|
.csc-pbx-device-button
|
||||||
|
background-color $primary
|
||||||
|
|
||||||
|
.csc-pbx-device-button-active
|
||||||
|
background-color $primary
|
||||||
|
color white
|
||||||
|
|
||||||
|
.csc-pbx-key-popover
|
||||||
|
min-height 40px
|
||||||
|
padding 16px
|
||||||
|
padding-right 40px
|
||||||
|
|
||||||
|
</style>
|
@ -0,0 +1,5 @@
|
|||||||
|
|
||||||
|
export default {
|
||||||
|
baseHttpUrl: 'https://' + window.location.host,
|
||||||
|
baseWsUrl: 'wss://' + window.location.host
|
||||||
|
}
|
@ -0,0 +1,93 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
import _ from 'lodash'
|
||||||
|
|
||||||
|
export class BoundingBox2D {
|
||||||
|
|
||||||
|
constructor(points) {
|
||||||
|
this.points = points;
|
||||||
|
this.topLeftX = null;
|
||||||
|
this.topLeftY = null;
|
||||||
|
this.bottomRightX = null;
|
||||||
|
this.bottomRightY = null;
|
||||||
|
this.init();
|
||||||
|
}
|
||||||
|
|
||||||
|
init() {
|
||||||
|
if(_.isArray(this.points)) {
|
||||||
|
for(let i = 0; i < this.points.length; i++) {
|
||||||
|
if(this.points[i].x < this.topLeftX || this.topLeftX === null) {
|
||||||
|
this.topLeftX = this.points[i].x;
|
||||||
|
}
|
||||||
|
if(this.points[i].x > this.bottomRightX || this.bottomRightX === null) {
|
||||||
|
this.bottomRightX = this.points[i].x;
|
||||||
|
}
|
||||||
|
if(this.points[i].y < this.topLeftY || this.topLeftY === null) {
|
||||||
|
this.topLeftY = this.points[i].y;
|
||||||
|
}
|
||||||
|
if(this.points[i].y > this.bottomRightY || this.bottomRightY === null) {
|
||||||
|
this.bottomRightY = this.points[i].y;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
getTopLeftX() {
|
||||||
|
return this.topLeftX;
|
||||||
|
}
|
||||||
|
|
||||||
|
getTopLeftY() {
|
||||||
|
return this.topLeftY;
|
||||||
|
}
|
||||||
|
|
||||||
|
getBottomRightX() {
|
||||||
|
return this.bottomRightX;
|
||||||
|
}
|
||||||
|
|
||||||
|
getBottomRightY() {
|
||||||
|
return this.bottomRightY;
|
||||||
|
}
|
||||||
|
|
||||||
|
getCenterX() {
|
||||||
|
return this.getTopLeftX() + this.getWidth() / 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
getCenterY() {
|
||||||
|
return this.getTopLeftY() + this.getHeight() / 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
getWidth() {
|
||||||
|
return this.getBottomRightX() - this.getTopLeftX();
|
||||||
|
}
|
||||||
|
|
||||||
|
getHeight() {
|
||||||
|
return this.getBottomRightY() - this.getTopLeftY();
|
||||||
|
}
|
||||||
|
|
||||||
|
addMargin(margin) {
|
||||||
|
this.topLeftX = this.topLeftX - margin;
|
||||||
|
this.topLeftY = this.topLeftY - margin;
|
||||||
|
this.bottomRightX = this.bottomRightX + margin;
|
||||||
|
this.bottomRightY = this.bottomRightY + margin;
|
||||||
|
}
|
||||||
|
|
||||||
|
scale(factor) {
|
||||||
|
this.topLeftX = this.topLeftX * factor;
|
||||||
|
this.topLeftY = this.topLeftY * factor;
|
||||||
|
this.bottomRightX = this.bottomRightX * factor;
|
||||||
|
this.bottomRightY = this.bottomRightY * factor;
|
||||||
|
}
|
||||||
|
|
||||||
|
clone() {
|
||||||
|
let boundingBox = new BoundingBox2D();
|
||||||
|
boundingBox.topLeftX = this.getTopLeftX();
|
||||||
|
boundingBox.topLeftY = this.getTopLeftY();
|
||||||
|
boundingBox.bottomRightX = this.getBottomRightX();
|
||||||
|
boundingBox.bottomRightY = this.getBottomRightY();
|
||||||
|
return boundingBox;
|
||||||
|
}
|
||||||
|
|
||||||
|
static createFromPoints(points) {
|
||||||
|
return new BoundingBox2D(points);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in new issue