mirror of
https://gitcode.com/gh_mirrors/hy/Hydro.git
synced 2026-10-20 01:38:19 +08:00
core, ui, judge: rewrite http & ws layer (#352)
This commit is contained in:
1 parent
3d2384f31a
commit
5af082eac8
37 files changed
+868
-889
No files matched your search
@@ -6,60 +6,62 @@ import i18n from 'vj/utils/i18n';
|
||||
import tpl from 'vj/utils/tpl';
|
||||
|
||||
const messagePage = new AutoloadPage('messagePage', (pagename) => {
|
||||
if (pagename === 'home_messages') return;
|
||||
let visible = true;
|
||||
document.addEventListener('visibilitychange', () => {
|
||||
const state = document.visibilityState;
|
||||
if (state === 'hidden' && visible) visible = false;
|
||||
if (state === 'visible' && !visible) visible = true;
|
||||
});
|
||||
if (pagename === 'home_messages' || !UserContext._id) return;
|
||||
|
||||
async function init() {
|
||||
if (UserContext.unreadMsg) {
|
||||
new VjNotification({
|
||||
type: 'info',
|
||||
message: i18n(`You have ${UserContext.unreadMsg > 1 ? 'new messages' : 'a new message'}.`),
|
||||
duration: 5000,
|
||||
action: () => window.open('/home/messages', '_blank'),
|
||||
}).show();
|
||||
}
|
||||
|
||||
const { default: SockJs } = await import('../socket');
|
||||
|
||||
const sock = new SockJs('/home/messages-conn', true, true);
|
||||
sock.onmessage = (message) => {
|
||||
const msg = JSON.parse(message.data);
|
||||
console.log('Received message', msg);
|
||||
if (msg.mdoc.flag & FLAG_ALERT) {
|
||||
// Is alert
|
||||
new InfoDialog({
|
||||
cancelByClickingBack: false,
|
||||
$body: tpl`
|
||||
<div class="typo">
|
||||
${{ templateRaw: true, html: i18n('Message from {0}:', `<div data-user>${msg.mdoc.from}</div>`) }}
|
||||
<p>${i18n(msg.mdoc.content)}</p>
|
||||
</div>`,
|
||||
}).open();
|
||||
} else if (msg.udoc._id === 1 && msg.mdoc.flag & 4) {
|
||||
new VjNotification({
|
||||
message: i18n('You received a system message, click here to view.'),
|
||||
duration: 15000,
|
||||
action: () => window.open(`/home/messages?uid=${msg.udoc._id}`, '_blank'),
|
||||
}).show();
|
||||
} else {
|
||||
// Is message
|
||||
new VjNotification({
|
||||
title: msg.udoc.uname,
|
||||
avatar: msg.udoc.avatarUrl,
|
||||
message: msg.mdoc.content,
|
||||
duration: 15000,
|
||||
action: () => window.open(`/home/messages?uid=${msg.udoc._id}`, '_blank'),
|
||||
}).show();
|
||||
}
|
||||
};
|
||||
if (UserContext.unreadMsg) {
|
||||
new VjNotification({
|
||||
type: 'info',
|
||||
message: i18n(`You have ${UserContext.unreadMsg > 1 ? 'new messages' : 'a new message'}.`),
|
||||
duration: 5000,
|
||||
action: () => window.open('/home/messages', '_blank'),
|
||||
}).show();
|
||||
}
|
||||
|
||||
if (UserContext._id !== 0) init();
|
||||
const onmessage = (message) => {
|
||||
const msg = JSON.parse(message);
|
||||
console.log('Received message', msg);
|
||||
if (msg.mdoc.flag & FLAG_ALERT) {
|
||||
// Is alert
|
||||
return new InfoDialog({
|
||||
cancelByClickingBack: false,
|
||||
$body: tpl`
|
||||
<div class="typo">
|
||||
${{ templateRaw: true, html: i18n('Message from {0}:', `<div data-user>${msg.mdoc.from}</div>`) }}
|
||||
<p>${i18n(msg.mdoc.content)}</p>
|
||||
</div>`,
|
||||
}).open();
|
||||
}
|
||||
if (msg.udoc._id === 1 && msg.mdoc.flag & 4) {
|
||||
// System notification
|
||||
return new VjNotification({
|
||||
message: i18n('You received a system message, click here to view.'),
|
||||
duration: 15000,
|
||||
action: () => window.open(`/home/messages?uid=${msg.udoc._id}`, '_blank'),
|
||||
}).show();
|
||||
}
|
||||
// Is message
|
||||
return new VjNotification({
|
||||
title: msg.udoc.uname,
|
||||
avatar: msg.udoc.avatarUrl,
|
||||
message: msg.mdoc.content,
|
||||
duration: 15000,
|
||||
action: () => window.open(`/home/messages?uid=${msg.udoc._id}`, '_blank'),
|
||||
}).show();
|
||||
};
|
||||
|
||||
const path = new URL('/home/messages-conn', window.location.href).toString();
|
||||
const worker = new SharedWorker('/sharedworker.js', { name: 'Hydro Messages Shared Worker' });
|
||||
worker.port.start();
|
||||
worker.port.postMessage({ type: 'init', path, cookie: document.cookie });
|
||||
worker.port.onmessage = (e) => {
|
||||
if (e.data.type !== 'message') return;
|
||||
if (document.hidden) {
|
||||
worker.port.postMessage({ type: 'fail' });
|
||||
} else {
|
||||
worker.port.postMessage({ type: 'success' });
|
||||
onmessage(e.data.payload);
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
export default messagePage;
|
||||
@@ -35,7 +35,6 @@ function handlerSwitchAccount(ev) {
|
||||
</div>
|
||||
`,
|
||||
onDispatch(action) {
|
||||
console.log(action, userSelector.value());
|
||||
if (action === 'ok' && userSelector.value() === null) {
|
||||
userSelector.focus();
|
||||
return false;
|
||||
|
||||
@@ -1,88 +1,38 @@
|
||||
import SockJS from 'sockjs-client';
|
||||
import $ from 'jquery';
|
||||
import Notification from 'vj/components/notification/index';
|
||||
import i18n from 'vj/utils/i18n';
|
||||
import tpl from 'vj/utils/tpl';
|
||||
|
||||
const notification = tpl`<div style="position: fixed; left: 0px; bottom: -100px; width: 100%; \
|
||||
background: rgb(255, 241, 184); z-index: 2147483647; color: rgb(97, 52, 0); \
|
||||
text-align: center; font-size: 18px; font-family: Consolas, Menlo, Courier, monospace; \
|
||||
padding: 8px 0px; box-shadow: rgba(0, 0, 0, 0.1) 0px 4px 8px;" id="disconnect_notification" \
|
||||
>${i18n('Disconnected from the server, trying to reconnect...')}</div>`;
|
||||
|
||||
const $el = $(notification);
|
||||
$el.appendTo('body');
|
||||
$el.hide();
|
||||
function create() {
|
||||
$el.show();
|
||||
$el.animate({ bottom: 0 }, 100);
|
||||
}
|
||||
function remove() {
|
||||
$el.animate({ bottom: -100 }, 100, () => $el.remove());
|
||||
}
|
||||
import ReconnectingWebSocket from 'reconnecting-websocket';
|
||||
|
||||
export default class Sock {
|
||||
constructor(url, showNotification = true, useShared = false) {
|
||||
this.url = url;
|
||||
this.shared = false;
|
||||
this.isreconnect = false;
|
||||
this.retryCount = 0;
|
||||
if (useShared && window.SharedWorker) this.initShared();
|
||||
else this.init();
|
||||
this.showNotification = showNotification;
|
||||
}
|
||||
|
||||
onauth() {
|
||||
remove();
|
||||
this.retryCount = 0;
|
||||
if (this.onopen) this.onopen(this.sock);
|
||||
}
|
||||
|
||||
init() {
|
||||
this.sock = new SockJS(this.url);
|
||||
// SockJS wouldn't send cookie. hack.
|
||||
this.sock.onopen = () => this.send(document.cookie);
|
||||
constructor(url) {
|
||||
const i = new URL(url, window.location.href);
|
||||
i.protocol = i.protocol.replace('http', 'ws');
|
||||
this.url = i.toString();
|
||||
this.closed = false;
|
||||
this.sock = new ReconnectingWebSocket(this.url);
|
||||
this.sock.onopen = () => {
|
||||
console.log('Connected');
|
||||
this.onopen?.(this.sock);
|
||||
};
|
||||
this.sock.onclose = ({ code, reason }) => {
|
||||
this.retryCount++;
|
||||
console.warn('Connection closed, ', code, reason);
|
||||
if (code >= 4000) this.closed = true;
|
||||
if (!this.closed) {
|
||||
this.isreconnect = setTimeout(this.init.bind(this), 3000);
|
||||
}
|
||||
if (this.showNotification && this.retryCount > 3) create();
|
||||
if (this.onclose) this.onclose(code, reason);
|
||||
this.onclose?.(code, reason);
|
||||
};
|
||||
this.sock.onmessage = (message) => {
|
||||
if (process.env.NODE_ENV !== 'production') console.log('Sock.onmessage: ', message);
|
||||
const msg = JSON.parse(message.data);
|
||||
if (msg.event === 'auth') {
|
||||
if (msg.error === 'PermissionError' || msg.error === 'PrivilegeError') {
|
||||
if (this.showNotification) Notification.info(i18n('Connect fail: Permission denied.'));
|
||||
this.closed = true;
|
||||
} else this.onauth();
|
||||
} else if (this.onmessage) this.onmessage(message);
|
||||
this.close();
|
||||
}
|
||||
} else this.onmessage?.(message);
|
||||
};
|
||||
}
|
||||
|
||||
initShared() {
|
||||
this.shared = true;
|
||||
const worker = new SharedWorker('/sharedworker.js', { name: 'Hydro Shared Connections Worker' });
|
||||
worker.port.start();
|
||||
const path = `${new URL(this.url, window.location.href).href.replace('http', 'ws')}/websocket`;
|
||||
worker.port.postMessage({ type: 'sharedConn', path, cookie: document.cookie });
|
||||
worker.port.onmessage = (e) => {
|
||||
if (e.data.type === 'message') this.onmessage({ data: e.data.payload });
|
||||
};
|
||||
this.worker = worker;
|
||||
}
|
||||
|
||||
send(data) {
|
||||
if (this.shared) this.worker.port.postMessage({ type: 'message', path: this.url, payload: data });
|
||||
else this.sock.send(data);
|
||||
this.sock.send(data);
|
||||
}
|
||||
|
||||
close() {
|
||||
this.closed = true;
|
||||
if (!this.shared) this.sock.close();
|
||||
this.sock?.close?.();
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@hydrooj/ui-default",
|
||||
"version": "4.34.40",
|
||||
"version": "4.35.0",
|
||||
"author": "undefined <i@undefined.moe>",
|
||||
"license": "AGPL-3.0",
|
||||
"main": "hydro.js",
|
||||
@@ -26,7 +26,6 @@
|
||||
"@types/katex": "^0.14.0",
|
||||
"@types/qrcode": "^1.4.2",
|
||||
"@types/redux-logger": "^3.0.9",
|
||||
"@types/sockjs-client": "^1.5.1",
|
||||
"@undefined-moe/monaco-yaml": "^2.5.1",
|
||||
"ansi_up": "^5.1.0",
|
||||
"autoprefixer": "^9.8.8",
|
||||
@@ -89,7 +88,6 @@
|
||||
"redux-thunk": "^2.4.1",
|
||||
"rupture": "^0.7.1",
|
||||
"slideout": "^1.0.1",
|
||||
"sockjs-client": "^1.6.0",
|
||||
"speed-measure-webpack-plugin": "^1.5.0",
|
||||
"sticky-kit": "^1.1.3",
|
||||
"style-loader": "^2.0.0",
|
||||
|
||||
@@ -23,7 +23,7 @@ const page = new NamedPage('home_messages', () => {
|
||||
}
|
||||
|
||||
async function mountComponent() {
|
||||
const { default: SockJs } = await import('../components/socket');
|
||||
const { default: WebSocket } = await import('../components/socket');
|
||||
const { default: MessagePadApp } = await import('../components/messagepad');
|
||||
const { default: MessagePadReducer } = await import('../components/messagepad/reducers');
|
||||
const {
|
||||
@@ -32,7 +32,7 @@ const page = new NamedPage('home_messages', () => {
|
||||
|
||||
reduxStore = store;
|
||||
|
||||
const sock = new SockJs('/home/messages-conn');
|
||||
const sock = new WebSocket('/home/messages-conn');
|
||||
sock.onmessage = (message) => {
|
||||
const msg = JSON.parse(message.data);
|
||||
store.dispatch({
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { NamedPage } from 'vj/misc/Page';
|
||||
|
||||
const page = new NamedPage('manage_dashboard', async () => {
|
||||
const { default: SockJs } = await import('../components/socket');
|
||||
const { default: WebSocket } = await import('../components/socket');
|
||||
|
||||
const sock = new SockJs('/manage/check-conn');
|
||||
const sock = new WebSocket('/manage/check-conn');
|
||||
sock.onopen = () => {
|
||||
$('<blockquote class="blue"><p>Connection opened.</p></blockquote>').appendTo('#messages');
|
||||
};
|
||||
|
||||
@@ -129,14 +129,14 @@ const page = new NamedPage(['problem_detail', 'contest_detail_problem', 'homewor
|
||||
if (reactLoaded) return;
|
||||
$('.loader-container').show();
|
||||
|
||||
const { default: SockJs } = await import('../components/socket');
|
||||
const { default: WebSocket } = await import('../components/socket');
|
||||
const { default: ScratchpadApp } = await import('../components/scratchpad');
|
||||
const { default: ScratchpadReducer } = await import('../components/scratchpad/reducers');
|
||||
const {
|
||||
React, render, unmountComponentAtNode, Provider, store,
|
||||
} = await loadReactRedux(ScratchpadReducer);
|
||||
|
||||
const sock = new SockJs(UiContext.pretestConnUrl);
|
||||
const sock = new WebSocket(UiContext.pretestConnUrl);
|
||||
sock.onmessage = (message) => {
|
||||
const msg = JSON.parse(message.data);
|
||||
store.dispatch({
|
||||
|
||||
@@ -2,12 +2,12 @@ import { NamedPage } from 'vj/misc/Page';
|
||||
|
||||
const page = new NamedPage('record_detail', async () => {
|
||||
if (!UiContext.socketUrl) return;
|
||||
const [{ default: SockJs }, { DiffDOM }] = await Promise.all([
|
||||
const [{ default: WebSocket }, { DiffDOM }] = await Promise.all([
|
||||
import('../components/socket'),
|
||||
import('diff-dom'),
|
||||
]);
|
||||
|
||||
const sock = new SockJs(UiContext.socketUrl);
|
||||
const sock = new WebSocket(UiContext.socketUrl);
|
||||
const dd = new DiffDOM();
|
||||
sock.onmessage = (message) => {
|
||||
const msg = JSON.parse(message.data);
|
||||
|
||||
@@ -5,12 +5,12 @@ import tpl from 'vj/utils/tpl';
|
||||
import getAvailableLangs from 'vj/utils/availableLangs';
|
||||
|
||||
const page = new NamedPage('record_main', async () => {
|
||||
const [{ default: SockJs }, { DiffDOM }] = await Promise.all([
|
||||
const [{ default: WebSocket }, { DiffDOM }] = await Promise.all([
|
||||
import('../components/socket'),
|
||||
import('diff-dom'),
|
||||
]);
|
||||
|
||||
const sock = new SockJs(UiContext.socketUrl);
|
||||
const sock = new WebSocket(UiContext.socketUrl);
|
||||
const dd = new DiffDOM();
|
||||
|
||||
let firstLoad = true;
|
||||
|
||||
@@ -1,63 +1,54 @@
|
||||
import ReconnectingWebsocket from 'reconnecting-websocket';
|
||||
|
||||
console.log('SharedWorker init');
|
||||
const ports: MessagePort[] = [];
|
||||
let conn: ReconnectingWebsocket;
|
||||
|
||||
const sharedConnections: Record<string, [ReconnectingWebsocket, MessagePort[]]> = {};
|
||||
interface RequestInitSharedConnPayload {
|
||||
type: 'sharedConn';
|
||||
cookie: any;
|
||||
path: string;
|
||||
}
|
||||
interface RequestSendMessagePayload {
|
||||
type: 'message';
|
||||
path: string;
|
||||
payload: string;
|
||||
}
|
||||
type RequestPayload = RequestInitSharedConnPayload | RequestSendMessagePayload;
|
||||
|
||||
function broadcastMsg(ports: MessagePort[], message: any) {
|
||||
for (const p of ports) p.postMessage(message);
|
||||
}
|
||||
function closeSharedConn(path: string) {
|
||||
sharedConnections[path][0].close();
|
||||
delete sharedConnections[path];
|
||||
}
|
||||
function initSharedConn(path: string, port: MessagePort, cookie: any) {
|
||||
if (!sharedConnections[path]) {
|
||||
console.log('Init connection for', path);
|
||||
const sock = new ReconnectingWebsocket(path);
|
||||
const ports: MessagePort[] = [];
|
||||
sharedConnections[path] = [sock, ports];
|
||||
|
||||
sock.onopen = () => sock.send(cookie);
|
||||
sock.onmessage = (message) => {
|
||||
if (process.env.NODE_ENV !== 'production') console.log('SharedWorker.port.onmessage: ', message);
|
||||
const payload = JSON.parse(message.data);
|
||||
if (payload.event === 'auth') {
|
||||
if (['PermissionError', 'PrivilegeError'].includes(payload.error)) {
|
||||
broadcastMsg(ports, { type: 'close', path, error: payload.error });
|
||||
closeSharedConn(path);
|
||||
} else {
|
||||
console.log('Connected to', path);
|
||||
broadcastMsg(ports, { type: 'open', path });
|
||||
}
|
||||
} else broadcastMsg(ports, { type: 'message', path, payload: message.data });
|
||||
};
|
||||
sock.onerror = () => broadcastMsg(ports, { type: 'error', path });
|
||||
sock.onclose = (ev) => broadcastMsg(ports, { type: 'close', path, error: ev.reason });
|
||||
}
|
||||
|
||||
sharedConnections[path][1].push(port);
|
||||
function initSharedConn(path: string, sid: string) {
|
||||
if (conn) return;
|
||||
console.log('Init connection for', path);
|
||||
const url = new URL(path);
|
||||
url.protocol = url.protocol.replace('http', 'ws');
|
||||
url.searchParams.append('sid', sid);
|
||||
const sock = new ReconnectingWebsocket(url.toString());
|
||||
conn = sock;
|
||||
sock.onopen = () => console.log('Connected');
|
||||
sock.onerror = console.error;
|
||||
sock.onclose = (...args) => console.log('Closed', ...args);
|
||||
sock.onmessage = async (message) => {
|
||||
if (process.env.NODE_ENV !== 'production') console.log('SharedWorker.port.onmessage: ', message);
|
||||
const payload = JSON.parse(message.data);
|
||||
if (payload.event === 'auth') {
|
||||
if (['PermissionError', 'PrivilegeError'].includes(payload.error)) {
|
||||
conn?.close();
|
||||
conn = null;
|
||||
}
|
||||
return;
|
||||
}
|
||||
for (const port of ports) {
|
||||
port.postMessage({ type: 'message', payload: message.data });
|
||||
const success = await new Promise((resolve) => {
|
||||
const handle = (msg) => {
|
||||
if (['success', 'fail'].includes(msg.data.type)) {
|
||||
port.removeEventListener('message', handle);
|
||||
resolve(msg.data.type === 'success');
|
||||
}
|
||||
};
|
||||
port.addEventListener('message', handle);
|
||||
});
|
||||
if (success) return;
|
||||
}
|
||||
console.log('Failed to push notification');
|
||||
// TODO try system notification
|
||||
};
|
||||
}
|
||||
|
||||
// @ts-ignore
|
||||
onconnect = function (e) { // eslint-disable-line no-undef
|
||||
const port: MessagePort = e.ports[0];
|
||||
|
||||
port.addEventListener('message', (msg: { data: RequestPayload }) => {
|
||||
if (msg.data.type === 'sharedConn') initSharedConn(msg.data.path, port, msg.data.cookie);
|
||||
if (msg.data.type === 'message') sharedConnections[msg.data.path]?.[0].send(msg.data.payload);
|
||||
port.addEventListener('message', (msg) => {
|
||||
initSharedConn(msg.data.path, msg.data.cookie);
|
||||
});
|
||||
|
||||
port.start();
|
||||
ports.push(port);
|
||||
};
|
||||
@@ -2,11 +2,11 @@
|
||||
{%- if not invalid -%}
|
||||
{% set _linkArgs = { pid:pdoc.pid|default(pdoc.docId) } %}
|
||||
{% if tdoc %}{{ set(_linkArgs, 'query', {tid:tdoc.docId}) }}{% endif %}
|
||||
{% if pdoc.domainId !== handler.domainId %}{{ set(_linkArgs, 'domainId', pdoc.domainId) }}{% endif %}
|
||||
{% if pdoc.domainId !== handler.args.domainId %}{{ set(_linkArgs, 'domainId', pdoc.domainId) }}{% endif %}
|
||||
<a href="{{ url('problem_detail', _linkArgs) }}"{% if small %} data-tooltip="{{ pdoc.title }}"{% endif %}>
|
||||
{%- endif -%}
|
||||
{%- if pdoc.domainId !== handler.domainId -%}<b>{{ pdoc.domainId }}#</b>{%- endif -%}
|
||||
<b>{{ pdoc.pid or 'P'+pdoc.docId if pdoc.domainId === handler.domainId else pdoc.docId }}</b>
|
||||
{%- if pdoc.domainId !== handler.args.domainId -%}<b>{{ pdoc.domainId }}#</b>{%- endif -%}
|
||||
<b>{{ pdoc.pid or 'P'+pdoc.docId if pdoc.domainId === handler.args.domainId else pdoc.docId }}</b>
|
||||
{%- if not small -%} {{ pdoc.title }}{%- endif -%}
|
||||
{%- if not invalid -%}
|
||||
</a>
|
||||
|
||||
@@ -49,7 +49,7 @@
|
||||
<td class="col--pid display-mode-hide">{{ pdoc.docId }}</td>
|
||||
{% if handler.user.hasPriv(PRIV.PRIV_USER_PROFILE) %}
|
||||
{% if psdoc['rid'] %}
|
||||
{{ record.render_status_td(psdoc, rid_key='rid', class="edit-mode-hide", allDomain=pdoc.domainId!==handler.domainId) }}
|
||||
{{ record.render_status_td(psdoc, rid_key='rid', class="edit-mode-hide", allDomain=pdoc.domainId!==handler.args.domainId) }}
|
||||
{% else %}
|
||||
<td class="col--status record-status--border edit-mode-hide"></td>
|
||||
{% endif %}
|
||||
|
||||
@@ -13,14 +13,14 @@
|
||||
{{ set(UiContext, 'postSubmitUrl', url('problem_submit', pid=pdoc.docId, query={tid:tdoc.docId})) }}
|
||||
{{ set(UiContext, 'getSubmissionsUrl', url('record_main', query={fullStatus:'true', pid:pdoc.docId, tid:tdoc.docId})) }}
|
||||
{{ set(UiContext, 'getRecordDetailUrl', url('record_detail', rid='{rid}', query={tid:tdoc.docId})) }}
|
||||
{{ set(UiContext, 'pretestConnUrl', "/record-conn?pretest=1&uidOrName=" + handler.user._id + "&pid=" + pdoc.docId + "&domainId=" + handler.domainId + "&tid=" + tdoc.docId) }}
|
||||
{{ set(UiContext, 'pretestConnUrl', "/record-conn?pretest=1&uidOrName=" + handler.user._id + "&pid=" + pdoc.docId + "&domainId=" + handler.args.domainId + "&tid=" + tdoc.docId) }}
|
||||
{{ set(UiContext, 'tdoc', tdoc) }}
|
||||
{% else %}
|
||||
{{ set(UiContext, 'canViewRecord', true) }}
|
||||
{{ set(UiContext, 'postSubmitUrl', url('problem_submit', pid=pdoc.docId)) }}
|
||||
{{ set(UiContext, 'getSubmissionsUrl', url('record_main', query={fullStatus:'true', pid:pdoc.docId})) }}
|
||||
{{ set(UiContext, 'getRecordDetailUrl', url('record_detail', rid='{rid}')) }}
|
||||
{{ set(UiContext, 'pretestConnUrl', "/record-conn?pretest=1&uidOrName=" + handler.user._id + "&pid=" + pdoc.docId + "&domainId=" + handler.domainId) }}
|
||||
{{ set(UiContext, 'pretestConnUrl', "/record-conn?pretest=1&uidOrName=" + handler.user._id + "&pid=" + pdoc.docId + "&domainId=" + handler.args.domainId) }}
|
||||
{% endif %}
|
||||
</script>
|
||||
<div class="row">
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
{% block content %}
|
||||
{{ set(
|
||||
UiContext, 'socketUrl',
|
||||
"/record-conn?domainId=" + handler.domainId
|
||||
"/record-conn?domainId=" + handler.args.domainId
|
||||
+ (("&tid=" + filterTid) if filterTid else "")
|
||||
+ (("&uidOrName=" + filterUidOrName) if filterUidOrName else "")
|
||||
+ (("&pid=" + filterPid) if filterPid else "")
|
||||
|
||||
Reference in new issue
Block a user