diff --git a/.gitignore b/.gitignore index 8fe3ba69..5901ad2b 100644 --- a/.gitignore +++ b/.gitignore @@ -15,3 +15,5 @@ t/TESTS* *.iml csc/ + +src/config.js diff --git a/debian/rules b/debian/rules index f5d30afc..d71d8c09 100755 --- a/debian/rules +++ b/debian/rules @@ -8,5 +8,6 @@ override_dh_auto_install: npm install + cp src/config.template.js src/config.js npm run build mv dist csc diff --git a/dev-config.sh b/dev-config.sh new file mode 100755 index 00000000..47d77ebd --- /dev/null +++ b/dev-config.sh @@ -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 diff --git a/dev-config/ngcp-panel_csc.customtt.tt2 b/dev-config/ngcp-panel_csc.customtt.tt2 new file mode 100644 index 00000000..c2b3c02e --- /dev/null +++ b/dev-config/ngcp-panel_csc.customtt.tt2 @@ -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 -%] diff --git a/dev-config/ngcp-panel_params.customtt.tt2 b/dev-config/ngcp-panel_params.customtt.tt2 new file mode 100644 index 00000000..04a100d8 --- /dev/null +++ b/dev-config/ngcp-panel_params.customtt.tt2 @@ -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; +} diff --git a/npm-shrinkwrap.json b/npm-shrinkwrap.json index c24a6832..198765f1 100644 --- a/npm-shrinkwrap.json +++ b/npm-shrinkwrap.json @@ -4958,9 +4958,9 @@ "resolved": "https://npm-registry.sipwise.com/quasar-extras/-/quasar-extras-0.0.8.tgz" }, "quasar-framework": { - "version": "0.14.6", - "from": "quasar-framework@>=0.14.4 <0.15.0", - "resolved": "https://npm-registry.sipwise.com/quasar-framework/-/quasar-framework-0.14.6.tgz" + "version": "0.14.9", + "from": "quasar-framework@0.14.9", + "resolved": "https://registry.npmjs.org/quasar-framework/-/quasar-framework-0.14.9.tgz" }, "query-string": { "version": "4.3.4", diff --git a/package.json b/package.json index 365cb1bf..5c635a59 100644 --- a/package.json +++ b/package.json @@ -14,7 +14,7 @@ "dependencies": { "babel-runtime": "^6.25.0", "quasar-extras": "0.x", - "quasar-framework": "^0.14.4", + "quasar-framework": "0.14.9", "uuid": "3.2.1", "vue": "^2.5.0", "vue-i18n": "7.3.2", diff --git a/src/api/call-forward.js b/src/api/call-forward.js index 16d449d5..81524c10 100644 --- a/src/api/call-forward.js +++ b/src/api/call-forward.js @@ -8,7 +8,7 @@ import { LIST_ALL_ROWS } from './common'; export function getMappings(id) { return new Promise((resolve, reject) => { - Vue.http.get('/api/cfmappings/' + id).then(result => { + Vue.http.get('api/cfmappings/' + id).then(result => { let jsonBody = getJsonBody(result.body); delete jsonBody._links; delete jsonBody.cfs; @@ -22,12 +22,12 @@ export function getMappings(id) { export function getSourcesets(id) { return new Promise((resolve, reject) => { Promise.resolve().then(() => { - return Vue.http.get('/api/cfsourcesets/', + return Vue.http.get('api/cfsourcesets/', { params: { subscriber_id: id, page: 1, rows: LIST_ALL_ROWS } }) }).then(result => { let totalCount = getJsonBody(result.body).total_count; if (totalCount > LIST_ALL_ROWS) { - return Vue.http.get('/api/cfsourcesets/', + return Vue.http.get('api/cfsourcesets/', { params: { subscriber_id: id, page: 1, rows: totalCount } }) } @@ -49,12 +49,12 @@ export function getSourcesets(id) { export function getTimesets(id) { return new Promise((resolve, reject) => { Promise.resolve().then(() => { - return Vue.http.get('/api/cftimesets/', + return Vue.http.get('api/cftimesets/', { params: { subscriber_id: id, page: 1, rows: LIST_ALL_ROWS } }) }).then(result => { let totalCount = getJsonBody(result.body).total_count; if (totalCount > LIST_ALL_ROWS) { - return Vue.http.get('/api/cftimesets/', + return Vue.http.get('api/cftimesets/', { params: { subscriber_id: id, page: 1, rows: totalCount } }) } @@ -74,12 +74,12 @@ export function getTimesets(id) { export function getDestinationsets(id) { return new Promise((resolve, reject) => { Promise.resolve().then(() => { - return Vue.http.get('/api/cfdestinationsets/', + return Vue.http.get('api/cfdestinationsets/', { params: { subscriber_id: id, page: 1, rows: LIST_ALL_ROWS } }) }).then(result => { let totalCount = getJsonBody(result.body).total_count; if (totalCount > LIST_ALL_ROWS) { - return Vue.http.get('/api/cfdestinationsets/', + return Vue.http.get('api/cfdestinationsets/', { params: { subscriber_id: id, page: 1, rows: totalCount } }) } @@ -214,7 +214,7 @@ export function addNameIdAndTerminating(options) { export function getDestinationsetById(id) { return new Promise((resolve, reject)=>{ - Vue.http.get('/api/cfdestinationsets/' + id).then((res)=>{ + Vue.http.get('api/cfdestinationsets/' + id).then((res)=>{ let destinationset = getJsonBody(res.body); delete destinationset['_links']; destinationset.destinations.sort((a, b) => { @@ -232,7 +232,7 @@ export function deleteDestinationFromDestinationset(options) { 'Content-Type': 'application/json-patch+json' }; return new Promise((resolve, reject) => { - Vue.http.patch('/api/cfdestinationsets/' + options.id, [{ + Vue.http.patch('api/cfdestinationsets/' + options.id, [{ op: 'replace', path: '/destinations', value: options.data @@ -255,7 +255,7 @@ export function deleteDestinationFromDestinationset(options) { export function deleteDestinationsetById(id) { return new Promise((resolve, reject) => { - Vue.http.delete('/api/cfdestinationsets/' + id).then(result => { + Vue.http.delete('api/cfdestinationsets/' + id).then(result => { resolve(result); }).catch(err => { reject(err); @@ -268,7 +268,7 @@ export function addDestinationToDestinationset(options) { 'Content-Type': 'application/json-patch+json' }; return new Promise((resolve, reject) => { - Vue.http.patch('/api/cfdestinationsets/' + options.id, [{ + Vue.http.patch('api/cfdestinationsets/' + options.id, [{ op: 'replace', path: '/destinations', value: options.data @@ -283,7 +283,7 @@ export function addDestinationToDestinationset(options) { export function addNewDestinationset() { let destinationsetName = `csc-${Date.now()}`; return new Promise((resolve, reject) => { - Vue.http.post('/api/cfdestinationsets/', { name: destinationsetName }) + Vue.http.post('api/cfdestinationsets/', { name: destinationsetName }) .then(response => { resolve(_.last(_.split(response.headers.get('Location'), '/'))); }).catch(err => { @@ -345,7 +345,7 @@ export function addDestinationToEmptyGroup(options) { export function addNewMapping(options) { let headers = { 'Content-Type': 'application/json-patch+json' }; return new Promise((resolve, reject) => { - Vue.http.patch('/api/cfmappings/' + options.subscriberId, [{ + Vue.http.patch('api/cfmappings/' + options.subscriberId, [{ op: 'replace', path: '/' + options.group, value: options.mappings @@ -362,7 +362,7 @@ export function changePositionOfDestination(options) { 'Content-Type': 'application/json-patch+json' }; return new Promise((resolve, reject) => { - Vue.http.patch('/api/cfdestinationsets/' + options.id, [{ + Vue.http.patch('api/cfdestinationsets/' + options.id, [{ op: 'replace', path: '/destinations', value: options.destinations @@ -580,7 +580,7 @@ export function deleteTimeFromTimeset(options) { 'Content-Type': 'application/json-patch+json' }; return new Promise((resolve, reject) => { - Vue.http.patch('/api/cftimesets/' + options.timesetId, [{ + Vue.http.patch('api/cftimesets/' + options.timesetId, [{ op: 'replace', path: '/times', value: options.times @@ -594,7 +594,7 @@ export function deleteTimeFromTimeset(options) { export function deleteTimesetById(id) { return new Promise((resolve, reject) => { - Vue.http.delete('/api/cftimesets/' + id).then(() => { + Vue.http.delete('api/cftimesets/' + id).then(() => { resolve(); }).catch(err => { reject(err); @@ -625,7 +625,7 @@ export function addTimeToTimeset(options) { let headers = { 'Content-Type': 'application/json-patch+json' }; - Vue.http.patch('/api/cftimesets/' + options.id, [{ + Vue.http.patch('api/cftimesets/' + options.id, [{ op: 'replace', path: '/times', value: options.times @@ -639,7 +639,7 @@ export function addTimeToTimeset(options) { export function addNewTimeset(timesetName) { return new Promise((resolve, reject) => { - Vue.http.post('/api/cftimesets/', { name: timesetName }) + Vue.http.post('api/cftimesets/', { name: timesetName }) .then(response => { resolve(_.last(_.split(response.headers.get('Location'), '/'))); }).catch(err => { @@ -721,7 +721,7 @@ export function createTimesetWithTime(options) { export function getTimesByTimesetId(id) { return new Promise((resolve, reject)=>{ - Vue.http.get('/api/cftimesets/' + id).then((res)=>{ + Vue.http.get('api/cftimesets/' + id).then((res)=>{ let timeset = getJsonBody(res.body); delete timeset['_links']; resolve(timeset.times); @@ -749,7 +749,7 @@ export function appendTimeToTimeset(options) { export function getSourcesBySourcesetId(id) { return new Promise((resolve, reject)=>{ - Vue.http.get('/api/cfsourcesets/' + id).then((res)=>{ + Vue.http.get('api/cfsourcesets/' + id).then((res)=>{ let sourceset = getJsonBody(res.body); resolve(sourceset.sources); }).catch((err)=>{ @@ -763,7 +763,7 @@ export function addSourceToSourceset(options) { let headers = { 'Content-Type': 'application/json-patch+json' }; - Vue.http.patch('/api/cfsourcesets/' + options.id, [{ + Vue.http.patch('api/cfsourcesets/' + options.id, [{ op: 'replace', path: '/sources', value: options.sources @@ -792,7 +792,7 @@ export function appendSourceToSourceset(options) { export function createSourcesetWithSource(options) { return new Promise((resolve, reject) => { - Vue.http.post('/api/cfsourcesets/', { + Vue.http.post('api/cfsourcesets/', { name: options.sourcesetName, subscriber_id: options.subscriberId, mode: options.mode, @@ -809,7 +809,7 @@ export function createSourcesetWithSource(options) { export function deleteSourcesetById(id) { return new Promise((resolve, reject) => { - Vue.http.delete('/api/cfsourcesets/' + id).then(() => { + Vue.http.delete('api/cfsourcesets/' + id).then(() => { resolve(); }).catch(err => { reject(err); @@ -832,7 +832,7 @@ export function deleteSourceFromSourcesetByIndex(options) { let headers = { 'Content-Type': 'application/json-patch+json' }; - Vue.http.patch('/api/cfsourcesets/' + options.sourceset.sourcesetId, [{ + Vue.http.patch('api/cfsourcesets/' + options.sourceset.sourcesetId, [{ op: 'replace', path: '/sources', value: sources diff --git a/src/api/common.js b/src/api/common.js index dbb4ce87..7ebb17dc 100644 --- a/src/api/common.js +++ b/src/api/common.js @@ -15,6 +15,9 @@ export function getList(options) { params: { page: LIST_DEFAULT_PAGE, rows: LIST_DEFAULT_ROWS + }, + headers: { + 'Accept': 'application/json' } }, options); Promise.resolve().then(()=>{ @@ -22,7 +25,8 @@ export function getList(options) { options.params.rows = LIST_ALL_ROWS; } return Vue.http.get(options.path, { - params: options.params + params: options.params, + headers: options.headers }); }).then((res)=>{ let body = getJsonBody(res.body); @@ -30,7 +34,8 @@ export function getList(options) { return Vue.http.get(options.path, { params: _.merge(options.params, { rows: body.total_count - }) + }), + headers: options.headers }); } else { @@ -54,7 +59,11 @@ export function getList(options) { export function get(options) { return new Promise((resolve, reject)=>{ - return Vue.http.get(options.path).then((result)=>{ + return Vue.http.get(options.path, { + headers: { + 'Accept': 'application/json' + } + }).then((result)=>{ resolve(getJsonBody(result.body)); }).catch((err)=>{ if(err.status && err.status >= 400) { diff --git a/src/api/communication.js b/src/api/communication.js index 2c574f0b..4523638f 100644 --- a/src/api/communication.js +++ b/src/api/communication.js @@ -8,7 +8,7 @@ export function createFax(options, subscriberId) { }; let mergedParams = Object.assign(options, subscriberId); let payload = JSON.stringify(mergedParams); - Vue.http.post('/api/faxes/', payload, { headers: headers }).then(() => { + Vue.http.post('api/faxes/', payload, { headers: headers }).then(() => { resolve(); }).catch((err)=>{ reject(err); diff --git a/src/api/conversations.js b/src/api/conversations.js index 1ce448f9..7ab675fe 100644 --- a/src/api/conversations.js +++ b/src/api/conversations.js @@ -9,7 +9,7 @@ export function getConversations(id, page, rows) { let params = { subscriber_id: id, page: page, rows: rows, order_by: 'timestamp', order_by_direction: 'desc' }; return new Promise((resolve, reject) => { - Vue.http.get('/api/conversations/', { params: params }) + Vue.http.get('api/conversations/', { params: params }) .then(result => { let jsonBody = getJsonBody(result.body); if (_.has(jsonBody, "_embedded.ngcp:conversations")) { @@ -38,7 +38,7 @@ export function getConversations(id, page, rows) { export function downloadVoiceMail(id) { return new Promise((resolve, reject)=>{ - Vue.http.get('/api/voicemailrecordings/' + id, { responseType: 'blob' }) + Vue.http.get('api/voicemailrecordings/' + id, { responseType: 'blob' }) .then(res => { return res.blob(); }).then(voicemail => { @@ -52,7 +52,7 @@ export function downloadVoiceMail(id) { export function downloadFax(id) { return new Promise((resolve, reject)=>{ - Vue.http.get('/api/faxrecordings/' + id, { responseType: 'blob' }) + Vue.http.get('api/faxrecordings/' + id, { responseType: 'blob' }) .then(res => { return res.blob(); }).then(fax => { diff --git a/src/api/pbx-config.js b/src/api/pbx-config.js index 4cc79c51..54017fbc 100644 --- a/src/api/pbx-config.js +++ b/src/api/pbx-config.js @@ -4,7 +4,7 @@ import Vue from 'vue'; import { getNumbers, assignNumbers } from './user'; import { createSubscriber, deleteSubscriber, setDisplayName, setPbxExtension, setPbxHuntPolicy, setPbxHuntTimeout, - setPbxGroupMemberIds, setPbxGroupIds, getSubscribers } from './subscriber'; + setPbxGroupMemberIds, setPbxGroupIds, getSubscribers, getSubscriber } from './subscriber'; import uuid from 'uuid'; import { getList, get } from './common' @@ -72,7 +72,7 @@ export function getDevices(options) { return new Promise((resolve, reject)=>{ options = options || {}; options = _.merge(options, { - path: '/api/pbxdevices/', + path: 'api/pbxdevices/', root: '_embedded.ngcp:pbxdevices' }); getList(options).then((list)=>{ @@ -87,7 +87,7 @@ export function getProfiles(options) { return new Promise((resolve, reject)=>{ options = options || {}; options = _.merge(options, { - path: '/api/pbxdeviceprofiles/', + path: 'api/pbxdeviceprofiles/', root: '_embedded.ngcp:pbxdeviceprofiles' }); getList(options).then((list)=>{ @@ -102,7 +102,7 @@ export function getModels(options) { return new Promise((resolve, reject)=>{ options = options || {}; options = _.merge(options, { - path: '/api/pbxdevicemodels/', + path: 'api/pbxdevicemodels/', root: '_embedded.ngcp:pbxdevicemodels' }); getList(options).then((list)=>{ @@ -278,18 +278,31 @@ export function getDevice(id, join) { let device; Promise.resolve().then(()=>{ return get({ - path: '/api/pbxdevices/' + id + path: 'api/pbxdevices/' + id }); }).then(($device)=> { device = $device; if(join === true) { - return getProfile(device.profile_id, join); + let requests = [ + getProfile(device.profile_id, join) + ]; + if(_.isArray(device.lines) && device.lines.length > 0) { + device.lines.forEach((line)=>{ + requests.push(getSubscriber(line.subscriber_id)); + }); + } + return Promise.all(requests); } else { resolve(device); } - }).then((profile)=>{ - device.profile = profile; + }).then((results)=>{ + device.profile = results[0]; + if(results.length > 1) { + for(let i = 1; i < results.length; i++) { + device.lines[i - 1].subscriber = results[i]; + } + } resolve(device); }).catch((err)=>{ reject(err); @@ -302,13 +315,13 @@ export function getProfile(id, join) { let profile; Promise.resolve().then(()=>{ return get({ - path: '/api/pbxdeviceprofiles/' + id + path: 'api/pbxdeviceprofiles/' + id }); }).then(($profile)=> { profile = $profile; if(join === true) { return Promise.all([ - // getModel(profile.device_id), + getModel(profile.device_id), getModelFrontImage(profile.device_id) ]); } @@ -316,8 +329,8 @@ export function getProfile(id, join) { resolve(profile); } }).then((res)=>{ - // profile.model = res[0]; - profile.modelFrontImage = res[0]; + profile.model = res[0]; + profile.modelFrontImage = res[1]; profile.modelFrontImageUrl = URL.createObjectURL(profile.modelFrontImage); resolve(profile); }).catch((err)=>{ @@ -330,7 +343,7 @@ export function getModel(id) { return new Promise((resolve, reject)=>{ Promise.resolve().then(()=>{ return get({ - path: '/api/pbxdevicemodels/' + id + path: 'api/pbxdevicemodels/' + id }); }).then((model)=> { resolve(model); @@ -342,7 +355,7 @@ export function getModel(id) { export function getModelFrontImage(id) { return new Promise((resolve, reject)=>{ - Vue.http.get('/api/pbxdevicemodelimages/' + id, { + Vue.http.get('api/pbxdevicemodelimages/' + id, { responseType: 'blob', params: { type: 'front' diff --git a/src/api/reminder.js b/src/api/reminder.js index cc05c4e0..6245e2ad 100644 --- a/src/api/reminder.js +++ b/src/api/reminder.js @@ -8,7 +8,7 @@ export function createReminder(id) { recur: 'never', active: false }; - Vue.http.post('/api/reminders/', data).then((result) => { + Vue.http.post('api/reminders/', data).then((result) => { var reminderID = result.headers.get('Location').split('/')[3]; resolve(reminderID); }).catch((err) => { @@ -19,7 +19,7 @@ export function createReminder(id) { export function getReminder(id) { return new Promise((resolve, reject) => { - Vue.http.get('/api/reminders/', { + Vue.http.get('api/reminders/', { params: { supplier_id: id } @@ -59,7 +59,7 @@ function patchReminder(id, field, value) { 'Content-Type': 'application/json-patch+json' } }; - Vue.http.patch('/api/reminders/' + id, data, patchHeaders).then(() => { + Vue.http.patch('api/reminders/' + id, data, patchHeaders).then(() => { resolve(); }).catch((err) => { reject(err); diff --git a/src/api/rtcsession.js b/src/api/rtcsession.js index 09c7bbf4..6bac6da2 100644 --- a/src/api/rtcsession.js +++ b/src/api/rtcsession.js @@ -1,10 +1,11 @@ +import config from '../config' import Vue from 'vue'; import { getJsonBody } from './utils'; export function create() { return new Promise((resolve, reject)=>{ - Vue.http.post('/api/rtcsessions/').then((res)=>{ + Vue.http.post('api/rtcsessions/').then((res)=>{ resolve(res); }).catch((err)=>{ reject(err); @@ -27,7 +28,7 @@ export function createSession() { Promise.resolve().then(()=>{ return create(); }).then((res)=>{ - return getByUrl(res.headers.get('Location')); + return getByUrl(config.baseHttpUrl + res.headers.get('Location')); }).then((res)=>{ resolve(res); }).catch((err)=>{ diff --git a/src/api/subscriber.js b/src/api/subscriber.js index 3025af57..99a1f19a 100644 --- a/src/api/subscriber.js +++ b/src/api/subscriber.js @@ -2,11 +2,11 @@ import _ from 'lodash'; import Vue from 'vue'; import { getJsonBody } from './utils' -import { getList } from './common' +import { getList, get } from './common' export function getPreferences(id) { return new Promise((resolve, reject)=>{ - Vue.http.get('/api/subscriberpreferences/' + id).then((result)=>{ + Vue.http.get('api/subscriberpreferences/' + id).then((result)=>{ resolve(getJsonBody(result.body)); }).catch((err)=>{ reject(err); @@ -19,7 +19,7 @@ export function setPreference(id, field, value) { var headers = {}; headers['Content-Type'] = 'application/json-patch+json'; Promise.resolve().then(()=>{ - return Vue.http.patch('/api/subscriberpreferences/' + id, [{ + return Vue.http.patch('api/subscriberpreferences/' + id, [{ op: 'replace', path: '/'+ field, value: value @@ -28,7 +28,7 @@ export function setPreference(id, field, value) { resolve(); }).catch((err)=>{ if(err.status === 422) { - Vue.http.patch('/api/subscriberpreferences/' + id, [{ + Vue.http.patch('api/subscriberpreferences/' + id, [{ op: 'add', path: '/'+ field, value: value @@ -54,7 +54,7 @@ export function prependItemToArrayPreference(id, field, value) { delete prefs._links; prefs[field] = _.get(prefs, field, []); prefs[field] = [value].concat(prefs[field]); - return Vue.http.put('/api/subscriberpreferences/' + id, prefs); + return Vue.http.put('api/subscriberpreferences/' + id, prefs); }).then(()=>{ resolve(); }).catch((err)=>{ @@ -72,7 +72,7 @@ export function appendItemToArrayPreference(id, field, value) { delete prefs._links; prefs[field] = _.get(prefs, field, []); prefs[field].push(value); - return Vue.http.put('/api/subscriberpreferences/' + id, prefs); + return Vue.http.put('api/subscriberpreferences/' + id, prefs); }).then(()=>{ resolve(); }).catch((err)=>{ @@ -90,7 +90,7 @@ export function editItemInArrayPreference(id, field, itemIndex, value) { delete prefs._links; if(_.isArray(prefs[field]) && itemIndex < prefs[field].length) { prefs[field][itemIndex] = value; - return Vue.http.put('/api/subscriberpreferences/' + id, prefs); + return Vue.http.put('api/subscriberpreferences/' + id, prefs); } else { return Promise.reject(new Error('Array index does not exists')); @@ -114,7 +114,7 @@ export function removeItemFromArrayPreference(id, field, itemIndex) { _.remove(prefs[field], (value, index)=>{ return index === itemIndex; }); - return Vue.http.put('/api/subscriberpreferences/' + id, prefs); + return Vue.http.put('api/subscriberpreferences/' + id, prefs); }).then(()=>{ resolve(); }).catch((err)=>{ @@ -185,7 +185,7 @@ export function disablePrivacy(id) { export function createSubscriber(subscriber) { return new Promise((resolve, reject)=>{ - Vue.http.post('/api/subscribers/', subscriber, { + Vue.http.post('api/subscribers/', subscriber, { params: { customer_id: subscriber.customer_id } @@ -204,7 +204,7 @@ export function createSubscriber(subscriber) { export function deleteSubscriber(id) { return new Promise((resolve, reject)=>{ - Vue.http.delete('/api/subscribers/' + id).then(()=>{ + Vue.http.delete('api/subscribers/' + id).then(()=>{ resolve(); }).catch((err)=>{ if(err.status >= 400) { @@ -219,7 +219,7 @@ export function deleteSubscriber(id) { export function setField(id, field, value) { return new Promise((resolve, reject)=>{ - Vue.http.patch('/api/subscribers/' + id, [{ + Vue.http.patch('api/subscribers/' + id, [{ op: 'replace', path: '/'+ field, value: value @@ -269,7 +269,7 @@ export function getSubscribers(options) { return new Promise((resolve, reject)=>{ options = options || {}; options = _.merge(options, { - path: '/api/subscribers/', + path: 'api/subscribers/', root: '_embedded.ngcp:subscribers' }); getList(options).then((list)=>{ @@ -279,3 +279,15 @@ export function getSubscribers(options) { }); }); } + +export function getSubscriber(id) { + return new Promise((resolve, reject)=>{ + get({ + path: 'api/subscribers/' + id + }).then((subscriber)=>{ + resolve(subscriber); + }).catch((err)=>{ + reject(err); + }); + }); +} diff --git a/src/api/user.js b/src/api/user.js index 895c87f4..04721c5a 100644 --- a/src/api/user.js +++ b/src/api/user.js @@ -7,7 +7,7 @@ export function login(username, password) { return new Promise((resolve, reject)=>{ var jwt = null; var subscriberId = null; - Vue.http.post('/login_jwt', { + Vue.http.post('login_jwt', { username: username, password: password }).then((result)=>{ @@ -46,7 +46,7 @@ export function getUserData(id) { export function getSubscriberById(id) { return new Promise((resolve, reject)=>{ - Vue.http.get('/api/subscribers/' + id).then((result)=>{ + Vue.http.get('api/subscribers/' + id).then((result)=>{ var body = JSON.parse(result.body); resolve(body); }).catch((err)=>{ @@ -57,7 +57,7 @@ export function getSubscriberById(id) { export function getCapabilities() { return new Promise((resolve, reject)=>{ - Vue.http.get('/api/capabilities/').then((result)=>{ + Vue.http.get('api/capabilities/').then((result)=>{ var capabilities = {}; var body = JSON.parse(result.body); if(_.isArray(body["_embedded"]["ngcp:capabilities"])) { @@ -77,7 +77,7 @@ export function assignNumber(numberId, subscriberId) { var headers = {}; headers['Content-Type'] = 'application/json-patch+json'; Promise.resolve().then(() => { - return Vue.http.patch('/api/numbers/' + numberId, [{ + return Vue.http.patch('api/numbers/' + numberId, [{ op: 'replace', path: '/subscriber_id', value: subscriberId @@ -114,7 +114,7 @@ export function assignNumbers(numberIds, subscriberId) { export function getNumbers() { return new Promise((resolve, reject)=>{ let params = {}; - let path = '/api/numbers'; + let path = 'api/numbers'; Promise.resolve().then(()=>{ return Vue.http.get(path, { params: _.assign(params, { diff --git a/src/components/pages/CallBlocking/CscCallBlocking.vue b/src/components/pages/CallBlocking/CscCallBlocking.vue index 323d17aa..27deeda3 100644 --- a/src/components/pages/CallBlocking/CscCallBlocking.vue +++ b/src/components/pages/CallBlocking/CscCallBlocking.vue @@ -37,7 +37,7 @@
- + diff --git a/src/components/pages/CallForward/CscSourcesets.vue b/src/components/pages/CallForward/CscSourcesets.vue index 61a61097..3926b00b 100644 --- a/src/components/pages/CallForward/CscSourcesets.vue +++ b/src/components/pages/CallForward/CscSourcesets.vue @@ -57,8 +57,7 @@ highlight separator v-for="(source, index) in sourcesetSources(sourceset.sourcesetId)" - class="source-item" - > + class="source-item" :key="index"> {{ source.source }} diff --git a/src/components/pages/PbxConfiguration/CscPbxDevice.vue b/src/components/pages/PbxConfiguration/CscPbxDevice.vue index 0d65d449..4d143ab6 100644 --- a/src/components/pages/PbxConfiguration/CscPbxDevice.vue +++ b/src/components/pages/PbxConfiguration/CscPbxDevice.vue @@ -1,36 +1,46 @@ + + + diff --git a/src/components/pages/PbxConfiguration/CscPbxDevices.vue b/src/components/pages/PbxConfiguration/CscPbxDevices.vue index c948bef1..3e7480d9 100644 --- a/src/components/pages/PbxConfiguration/CscPbxDevices.vue +++ b/src/components/pages/PbxConfiguration/CscPbxDevices.vue @@ -6,8 +6,10 @@
- + + +
{{ $t('pbxConfig.noDevices') }}
@@ -18,7 +20,7 @@ import { mapGetters } from 'vuex' import CscPage from '../../CscPage' import CscPbxDevice from './CscPbxDevice' - import { QSpinnerDots, QPagination } from 'quasar-framework' + import { QSpinnerDots, QPagination, QList } from 'quasar-framework' export default { data () { return { @@ -33,7 +35,8 @@ CscPage, CscPbxDevice, QSpinnerDots, - QPagination + QPagination, + QList }, computed: { ...mapGetters('pbxConfig', [ diff --git a/src/config.template.js b/src/config.template.js new file mode 100644 index 00000000..aa2c9e25 --- /dev/null +++ b/src/config.template.js @@ -0,0 +1,5 @@ + +export default { + baseHttpUrl: 'https://' + window.location.host, + baseWsUrl: 'wss://' + window.location.host +} diff --git a/src/helpers/cdk-lib.js b/src/helpers/cdk-lib.js index 4c4df88c..f510a802 100644 --- a/src/helpers/cdk-lib.js +++ b/src/helpers/cdk-lib.js @@ -1,15 +1,15 @@ +import config from '../config' import loadScript from 'load-script' var scriptId = 'cdk'; -var scriptPath = '/rtc/files/dist/cdk-prod.js'; -var webSocketPath = '/rtc/api'; -var webSocketUrl = 'wss://' + window.location.host + webSocketPath; +var scriptUrl = config.baseHttpUrl + '/rtc/files/dist/cdk-prod.js'; +var webSocketUrl = config.baseWsUrl + '/rtc/api'; export function loadCdkLib() { return new Promise((resolve, reject)=>{ if(!document.getElementById(scriptId)) { - loadScript(scriptPath, { + loadScript(scriptUrl, { attrs: { id: scriptId } diff --git a/src/helpers/graphics.js b/src/helpers/graphics.js new file mode 100644 index 00000000..78e94921 --- /dev/null +++ b/src/helpers/graphics.js @@ -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); + } +} diff --git a/src/main.js b/src/main.js index bd26471a..11ac52a9 100644 --- a/src/main.js +++ b/src/main.js @@ -17,6 +17,8 @@ import { RtcEngineCall } from './plugins/call' import App from './App.vue' import './filters' +import config from './config' + Vue.config.productionTip = false; Vue.use(Quasar); Vue.use(VueResource); @@ -24,6 +26,7 @@ Vue.use(RtcEngineCall); sync(store, router); +Vue.http.options.root = config.baseHttpUrl; Vue.http.interceptors.push(function(request, next) { var jwt = localStorage.getItem('jwt'); if(!_.isEmpty(jwt)) { diff --git a/src/store/pbx-config/mutations.js b/src/store/pbx-config/mutations.js index 769c7ae6..2e3065ae 100644 --- a/src/store/pbx-config/mutations.js +++ b/src/store/pbx-config/mutations.js @@ -147,12 +147,13 @@ export default { state.listLoadingSilently = _.get(options, 'silent', false); state.listState = RequestState.requesting; state.listError = null; + state.devices = {}; + state.devicesOrdered = []; }, deviceListSucceeded(state, data) { state.listState = RequestState.succeeded; state.listError = null; state.listLastPage = data.lastPage; - state.devices = {}; state.devicesOrdered = data.items; state.devicesOrdered.forEach((device)=>{ state.devices[device.id + ""] = device; @@ -171,7 +172,14 @@ export default { let deviceLoadingStates = _.clone(state.deviceLoadingStates); deviceLoadingStates[device.id + ""] = false; state.deviceLoadingStates = deviceLoadingStates; - state.devices[device.id + ""].profile = device.profile; + for(let i = 0; i <= state.devicesOrdered.length; i++) { + if(state.devicesOrdered[i].id === device.id) { + state.devicesOrdered[i] = device; + } + } + delete state.devices[device.id + ""]; + state.devices[device.id + ""] = device; + }, deviceFailed(state, deviceId, errorMessage) { let deviceLoadingStates = _.clone(state.deviceLoadingStates); diff --git a/t/Dockerfile b/t/Dockerfile index 717888e3..3f4feb0f 100644 --- a/t/Dockerfile +++ b/t/Dockerfile @@ -5,7 +5,7 @@ FROM docker.mgm.sipwise.com/sipwise-stretch:latest # is updated with the current date. It will force refresh of all # of the base images and things like `apt-get update` won't be using # old cached versions when the Dockerfile is built. -ENV REFRESHED_AT 2018-04-26 +ENV REFRESHED_AT 2018-05-24 ENV DEBIAN_FRONTEND noninteractive ENV DISPLAY=:0 diff --git a/t/api/call-blocking.js b/t/api/call-blocking.js index f518b725..e0533169 100644 --- a/t/api/call-blocking.js +++ b/t/api/call-blocking.js @@ -31,7 +31,7 @@ describe('CallBlocking', function(){ describe('Incoming', function(){ it('should enable call blocking for incoming calls', function(done) { Vue.http.interceptors.unshift((request, next)=>{ - assert.equal(request.url, '/api/subscriberpreferences/' + subscriberId); + assert.equal(request.url, 'api/subscriberpreferences/' + subscriberId); assert.equal(request.body[0].op, 'replace'); assert.equal(request.body[0].path, '/block_in_mode'); assert.equal(request.body[0].value, true); @@ -48,7 +48,7 @@ describe('CallBlocking', function(){ it('should disable call blocking for incoming calls', function(done) { Vue.http.interceptors.unshift((request, next)=>{ - assert.equal(request.url, '/api/subscriberpreferences/' + subscriberId); + assert.equal(request.url, 'api/subscriberpreferences/' + subscriberId); assert.equal(request.body[0].op, 'replace'); assert.equal(request.body[0].path, '/block_in_mode'); assert.equal(request.body[0].value, false); @@ -69,7 +69,7 @@ describe('CallBlocking', function(){ "0987654321" ]; Vue.http.interceptors.unshift((request, next)=>{ - assert.equal(request.url, '/api/subscriberpreferences/' + subscriberId); + assert.equal(request.url, 'api/subscriberpreferences/' + subscriberId); next(request.respondWith(JSON.stringify({ "block_in_list" : list, "block_in_mode" : true @@ -92,7 +92,7 @@ describe('CallBlocking', function(){ "0123456789" ]; Vue.http.interceptors.unshift((request, next)=>{ - assert.equal(request.url, '/api/subscriberpreferences/' + subscriberId); + assert.equal(request.url, 'api/subscriberpreferences/' + subscriberId); if(request.method === 'GET') { next(request.respondWith(JSON.stringify({ "block_in_list" : list @@ -119,7 +119,7 @@ describe('CallBlocking', function(){ "0123456789" ]; Vue.http.interceptors.unshift((request, next)=>{ - assert.equal(request.url, '/api/subscriberpreferences/' + subscriberId); + assert.equal(request.url, 'api/subscriberpreferences/' + subscriberId); if(request.method === 'GET') { next(request.respondWith(JSON.stringify({ "block_in_list" : list @@ -146,7 +146,7 @@ describe('CallBlocking', function(){ "0123456789" ]; Vue.http.interceptors.unshift((request, next)=>{ - assert.equal(request.url, '/api/subscriberpreferences/' + subscriberId); + assert.equal(request.url, 'api/subscriberpreferences/' + subscriberId); if(request.method === 'GET') { next(request.respondWith(JSON.stringify({ "block_in_list" : [].concat([number]).concat(list) @@ -171,7 +171,7 @@ describe('CallBlocking', function(){ describe('Outgoing', function(){ it('should enable call blocking for outgoing calls', function(done) { Vue.http.interceptors.unshift((request, next)=>{ - assert.equal(request.url, '/api/subscriberpreferences/' + subscriberId); + assert.equal(request.url, 'api/subscriberpreferences/' + subscriberId); assert.equal(request.body[0].op, 'replace'); assert.equal(request.body[0].path, '/block_out_mode'); assert.equal(request.body[0].value, true); @@ -188,7 +188,7 @@ describe('CallBlocking', function(){ it('should disable call blocking for outgoing calls', function(done) { Vue.http.interceptors.unshift((request, next)=>{ - assert.equal(request.url, '/api/subscriberpreferences/' + subscriberId); + assert.equal(request.url, 'api/subscriberpreferences/' + subscriberId); assert.equal(request.body[0].op, 'replace'); assert.equal(request.body[0].path, '/block_out_mode'); assert.equal(request.body[0].value, false); @@ -209,7 +209,7 @@ describe('CallBlocking', function(){ "0987654321" ]; Vue.http.interceptors.unshift((request, next)=>{ - assert.equal(request.url, '/api/subscriberpreferences/' + subscriberId); + assert.equal(request.url, 'api/subscriberpreferences/' + subscriberId); next(request.respondWith(JSON.stringify({ "block_out_list" : list, "block_out_mode" : true @@ -232,7 +232,7 @@ describe('CallBlocking', function(){ "0123456789" ]; Vue.http.interceptors.unshift((request, next)=>{ - assert.equal(request.url, '/api/subscriberpreferences/' + subscriberId); + assert.equal(request.url, 'api/subscriberpreferences/' + subscriberId); if(request.method === 'GET') { next(request.respondWith(JSON.stringify({ "block_out_list" : list @@ -259,7 +259,7 @@ describe('CallBlocking', function(){ "0123456789" ]; Vue.http.interceptors.unshift((request, next)=>{ - assert.equal(request.url, '/api/subscriberpreferences/' + subscriberId); + assert.equal(request.url, 'api/subscriberpreferences/' + subscriberId); if(request.method === 'GET') { next(request.respondWith(JSON.stringify({ "block_out_list" : list @@ -286,7 +286,7 @@ describe('CallBlocking', function(){ "0123456789" ]; Vue.http.interceptors.unshift((request, next)=>{ - assert.equal(request.url, '/api/subscriberpreferences/' + subscriberId); + assert.equal(request.url, 'api/subscriberpreferences/' + subscriberId); if(request.method === 'GET') { next(request.respondWith(JSON.stringify({ "block_out_list" : [].concat([number]).concat(list) diff --git a/t/api/reminder.js b/t/api/reminder.js index 1861260c..76b05d42 100644 --- a/t/api/reminder.js +++ b/t/api/reminder.js @@ -28,7 +28,7 @@ describe('Reminder', function() { it('should return 201 when creating a new reminder', function(done) { Vue.http.interceptors.unshift((request, next) => { - assert.equal(request.url, '/api/reminders/'); + assert.equal(request.url, 'api/reminders/'); assert.equal(request.body.subscriber_id, subscriberId); assert.equal(request.body.time, '00:00'); assert.equal(request.body.recur, 'never'); @@ -37,7 +37,7 @@ describe('Reminder', function() { request.respondWith('', { status: 201, headers: { - location: '/api/reminders/' + reminderID + location: 'api/reminders/' + reminderID } }) ) @@ -51,7 +51,7 @@ describe('Reminder', function() { it('should get the existing reminder', function(done) { Vue.http.interceptors.unshift((request, next) => { - assert.equal(request.url, '/api/reminders/'); + assert.equal(request.url, 'api/reminders/'); assert.equal(request.params.supplier_id, subscriberId); next(request.respondWith(JSON.stringify({ "_embedded": { @@ -88,7 +88,7 @@ describe('Reminder', function() { it('should activate a reminder', function(done) { Vue.http.interceptors.unshift((request, next) => { - assert.equal(request.url, '/api/reminders/' + reminderID); + assert.equal(request.url, 'api/reminders/' + reminderID); assert.equal(request.body[0].op, 'replace'); assert.equal(request.body[0].path, '/active'); assert.equal(request.body[0].value, true); @@ -105,7 +105,7 @@ describe('Reminder', function() { it('should deactivate a reminder', function(done) { Vue.http.interceptors.unshift((request, next) => { - assert.equal(request.url, '/api/reminders/' + reminderID); + assert.equal(request.url, 'api/reminders/' + reminderID); assert.equal(request.body[0].op, 'replace'); assert.equal(request.body[0].path, '/active'); assert.equal(request.body[0].value, false); @@ -122,7 +122,7 @@ describe('Reminder', function() { it('should set reminder time', function(done) { Vue.http.interceptors.unshift((request, next) => { - assert.equal(request.url, '/api/reminders/' + reminderID); + assert.equal(request.url, 'api/reminders/' + reminderID); assert.equal(request.body[0].op, 'replace'); assert.equal(request.body[0].path, '/time'); assert.equal(request.body[0].value, '22:22:00'); @@ -139,7 +139,7 @@ describe('Reminder', function() { it('should set reminder recurrence', function(done) { Vue.http.interceptors.unshift((request, next) => { - assert.equal(request.url, '/api/reminders/' + reminderID); + assert.equal(request.url, 'api/reminders/' + reminderID); assert.equal(request.body[0].op, 'replace'); assert.equal(request.body[0].path, '/recur'); assert.equal(request.body[0].value, 'always'); @@ -153,5 +153,5 @@ describe('Reminder', function() { done(err); }); }); - + });