Init WebCG

This commit is contained in:
2026-08-12 14:21:28 +09:00
commit 5c01660f97
170 changed files with 46248 additions and 0 deletions
+651
View File
@@ -0,0 +1,651 @@
<!DOCTYPE html>
{{>copyright }}
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="/js/axios.min.js"></script>
<script src="/js/fontawesome.all.min.js"></script>
<script src="/js/Sortable.min.js"></script>
<script src="/js/anime.min.js"></script>
<script src="/js/socket.io.js"></script>
<script src="/js/spx_gc.js"></script>
<title>SPX | {{lang 'pagetitle.configapp'}}</title>
<link rel="icon" type="image/png" href="/img/spx-gc.ico">
<link rel="stylesheet" type="text/css" href="/css/spx_fonts.css">
<link rel="stylesheet" type="text/css" href="/css/spx_layout.css">
<link rel="stylesheet" type="text/css" href="/css/spx_forms.css">
<link rel="stylesheet" type="text/css" href="/css/spx_colors.css">
<link rel="stylesheet" type="text/css" href="/css/spx_modal.css">
<style>
.locked {
opacity: 0.3;
pointer-events: none;
}
#locked {
padding: 1em;
display: block;
font-size: 0.7em;
text-align: center;
color: rgb(255, 255, 255);
background-color: rgb(85, 3, 3);
}
.soloInfo {
color: #aaa;
padding: 0.6em;
border-radius: 0.4em;
background-color: rgba(0, 0, 0, 0.1);
border: 1px solid rgba(0, 0, 0, 0.5);
border-bottom: 1px solid rgba(255, 255, 255, 0.2);
box-shadow: inset 0 0 0.5em rgba(0, 0, 0, 0.5);
background-image: linear-gradient(
178deg,
transparent 30%,
rgba(0, 0, 0, 0.1) 55%
);
background-repeat: no-repeat;
}
.soloInfo h1 {
margin: 0;
font-size: 0.7em;
padding-bottom: 0.5em;
}
.soloInfo p {
font-size: clamp(11px, 1vw, 20px);
opacity: 0.8;
}
</style>
</head>
<body onload="pageInit();" class="bg_body" onmouseover="tip('');">
{{#ifValue config.general.disableConfigUI true}}
<div id="locked">Configuration locked by admin.</div>
{{/ifValue}}
<div class="wrapper">
<div class="header">
{{>header page="appconfig"}}
</div><!-- header ended -->
{{#ifValue config.general.disableConfigUI true}}
<div class="content locked">
{{else}}
<div class="content">
{{/ifValue}}
<div class="centerColumn pM wrapper ">
<div id="itemList" class="content pM scroller" style="border: 0px solid yellow;">
{{#if message}}
<div class="message">{{message}}</div>
{{/if}}
{{#if error}}
<div class="messagerror">{{error}}</div>
{{/if}}
<form name="config" id="config" method="post">
<input type="hidden" name="general[username]" value="{{config.general.username}}">
<input type="hidden" name="general[password]" value="{{config.general.password}}">
<input type="hidden" name="general[hostname]" value="{{config.general.hostname}}">
<input type="hidden" name="general[greeting]" value="{{config.general.greeting}}">
<input type="hidden" name="general[showusercommapass]" value="{{config.general.showusercommapass}}">
<table class="wide" border=0>
<TR>
<td colspan="2">
<div class="soloInfo" >
<h1>SPX Solo</h1>
<p>
This SPX Solo v.{{{ShowVersion}}} is a limited version of SPX Graphics for personal use and light productions. For more advanced professional features and capabilities, consider SPX Production or SPX Broadcast.
<a href="https://spxgraphics.com/software/#compare">Read more</a>
</div>
<br>
</td>
</TR>
<TR>
<td class="vmid tableheaderText">{{lang 'config.general'}} </td>
<td class="vmid tableheaderHelp aright" title="{{lang 'general.help'}}" onClick="help('config');" onmouseover="tip('{{lang 'hover.help'}}');"><i class="far fa-question-circle"></i>&nbsp;</td>
</TR>
</table>
<hr class="h2hr"><!-- =========================================== -->
<table style="width: 100%;" cellspacing="10" border="0">
<!--
<tr onmouseover="tip('{{lang 'hover.openbrowser'}}');">
<td width="40%">
<span class="spxConfigHead">{{lang 'config.openchrome'}}</span>
</td>
<td>
{{{ OpenChromeCheck }}}
</td>
</tr>
-->
<td width="40%">
<span class="spxConfigHead">Config file</span>
</td>
<td>
<span class="spxConfigHead">{{configfile}}</span>
</td>
</tr>
<tr onmouseover="tip('{{lang 'hover.lang'}}');">
<td width="40%">
<span class="spxConfigHead">{{lang 'config.language'}}</span>
</td>
<td>
<select class="wide drop bg_grey15" name="general[langfile]">
{{{ DropdownOptionsLANG }}}
</select>
<BR>
</td>
</tr>
<tr onmouseover="tip('{{lang 'hover.loglevel'}}');">
<td width="40%">
<span class="spxConfigHead">{{lang 'config.loglevel'}} *</span>
</td>
<td>
<select class="wide drop bg_grey15" name="general[loglevel]">
<!-- error, warn, info, verbose, debug -->
{{#ifValue config.general.loglevel "error"}}
<option selected>error</option>
{{else}}
<option>error</option>
{{/ifValue}}
{{#ifValue config.general.loglevel "warn"}}
<option selected>warn</option>
{{else}}
<option>warn</option>
{{/ifValue}}
{{#ifValue config.general.loglevel "info"}}
<option selected>info</option>
{{else}}
<option>info</option>
{{/ifValue}}
{{#ifValue config.general.loglevel "verbose"}}
<option selected>verbose</option>
{{else}}
<option>verbose</option>
{{/ifValue}}
{{#ifValue config.general.loglevel "debug"}}
<option selected>debug</option>
{{else}}
<option>debug</option>
{{/ifValue}}
</select>
</td>
</tr>
<tr onmouseover="tip('{{lang 'hover.logfolder'}}');">
<td>
<span class="spxConfigHead">{{lang 'config.logfolder'}} *</span>
</td>
<td>
<input type="text" class="wide bg_grey15 cfg" placeholder="Log folder" name="general[logfolder]" value="{{config.general.logfolder}}">
</td>
</tr>
<tr onmouseover="tip('{{lang 'hover.port'}}');">
<td>
<span class="spxConfigHead">{{lang 'config.serverport'}} *&nbsp;&nbsp;<i style="color:rgba(255, 166, 0, 0.472);" class="fas fa-exclamation-triangle" title="URL port must be changed after reload, otherwise this page will not load!"></i></span>
</td>
<td>
<input type="text" class="wide bg_grey15 cfg" placeholder="port" name="general[port]" value="{{config.general.port}}">
</td>
</tr>
<tr onmouseover="tip('{{lang 'hover.dataroot'}}');">
<td>
<span class="spxConfigHead">{{lang 'config.dataroot'}} *</span>
</td>
<td>
<input type="text" class="wide bg_grey15 cfg" placeholder="Dataroot folder" name="general[dataroot]" value="{{config.general.dataroot}}">
</td>
</tr>
<tr onmouseover="tip('{{lang 'hover.preview'}}');">
<td class="vtop">
<span class="spxConfigHead">{{lang 'config.preview'}}</span>
</td>
<td>
<select class="wide drop bg_grey15" name="general[preview]">
<!-- error, warn, info, verbose, debug -->
<option value="next" disabled {{#ifValue config.general.preview "next" }}selected{{/ifValue}}>Preview next item on play</option>
<option value="selected" {{#ifValue config.general.preview "selected"}}selected{{/ifValue}}>Preview selected item on focus</option><!-- this is the default -->
<option value="none" {{#ifValue config.general.preview "none"}}selected{{/ifValue}}>Disable preview</option>
</select>
</P>
</td>
</tr>
<tr onmouseover="tip('Should local renderer play items to match the rundown state?');">
<td class="vtop">
<span class="spxConfigHead">Local renderer autoplay</span>
</td>
<td>
<select class="wide drop bg_grey15" name="general[autoplayLocalRenderer]">
<option value="true" {{#ifValue config.general.autoplayLocalRenderer "true"}}selected{{/ifValue}}>Play (if saved state is playing)</option>
<option value="false" {{#ifValue config.general.autoplayLocalRenderer "false"}}selected{{/ifValue}}>Do nothing</option>
</select>
</P>
</td>
</tr>
<tr onmouseover="tip('{{lang 'hover.resolution'}}');">
<td class="vtop">
<span class="spxConfigHead">{{lang 'config.resolution'}}</span>
</td>
<td>
<select class="wide drop bg_grey15" name="general[resolution]">
{{{generateResolutionOptions config.general.resolution}}}
</select>
<P class="spxConfigHead" style="white-space: normal; line-height: 100%; opacity:0.5; margin-top: 0.2em; margin-bottom: 0.6em;">
<small>
{{lang 'config.resolutioninfo'}}
</small>
</P>
</td>
</tr>
<!-- external audio player is disabled:
<tr onmouseover="tip('{{lang 'hover.dataroot'}}');">
<td>
<span class="spxConfigHead">{{lang 'config.audioplayer'}}</span>
</td>
<td>
<input type="text" class="wide bg_grey15 cfg" placeholder="Audioplayer path" name="general[audioplayer]" value="{{config.general.audioplayer}}">
</td>
</tr>
<tr onmouseover="tip('{{lang 'hover.htmlfolder'}}');">
<td width="40%">
<span class="spxConfigHead">{{lang 'config.playerflags'}}</span>
</td>
<td>
<input type="text" class="wide bg_grey15 cfg" placeholder="Audioplayer arguments (%FILE%)" name="general[playerflags]" value="{{config.general.playerflags}}">
</td>
</tr>
audio player -->
</table>
<BR><BR>
<table class="wide" border=0>
<TR>
<td class="vmid tableheaderText">{{lang 'config.webplayout'}}</td>
<td class="vmid tableheaderHelp aright" title="{{lang 'general.help'}}" onClick="help('webplayout');" onmouseover="tip('{{lang 'hover.help'}}');"><i class="far fa-question-circle"></i>&nbsp;</td>
</TR>
</table>
<hr class="h2hr"><!-- =========================================== -->
<table style="width: 100%;" cellspacing="5" border="0">
<tr onmouseover="tip('{{lang 'hover.playouturl'}}');">
<td width="40%">
<a href="/renderer/" target="_player"><span style="border-bottom: 1px dashed rgb(0, 140, 255);" class="spxConfigHead">{{lang 'config.webplayurl'}} *</span></a>
</td>
<td>
<input type="text" class="wide bg_grey15 cfg" style="border: 1px dashed rgba(0, 140, 255, 0.507); background-color: #575757;" placeholder="URL for OBS / vMIX" id="rendererLink" value="">
</td>
</tr>
<!--
<tr onmouseover="tip('{{lang 'hover.remoteplayouturl'}}');">
<td width="40%">
<span class="spxConfigHead">DEMO RemoteRenderer</span>
</td>
<td>
<input type="text" class="wide bg_grey15 cfg" style="border: 1px dashed rgba(0, 140, 255, 0.507); background-color: #575757;" placeholder="URL for OBS / vMIX" value="remoteserver.address.com/webrenderer/index.html?gc={{{ getServerAddress }}}">
</td>
</tr>
-->
</table>
<BR><BR>
<table class="wide" border=0>
<TR>
<td class="vmid tableheaderText">API</td>
<td class="vmid tableheaderHelp aright" title="{{lang 'general.help'}}" onClick="help('api');" onmouseover="tip('{{lang 'hover.help'}}');"><i class="far fa-question-circle"></i>&nbsp;</td>
</TR>
</table>
<hr class="h2hr"><!-- =========================================== -->
<table style="width: 100%;" cellspacing="5" border="0">
<tr onmouseover="tip('API Commands');">
<td width="40%">
<a href="/api/v1/" target="_api"><span style="border-bottom: 1px dashed rgb(0, 140, 255);" class="spxConfigHead">API endpoints</span></a>
</td>
<td>
<input type="text" class="wide bg_grey15 cfg" style="border: 1px dashed rgba(0, 140, 255, 0.507); background-color: #575757;" placeholder="List of API endpoints" id="apiLink" value="">
</P>
</td>
</tr>
</table>
<BR><BR>
<table class="wide" border=0>
<TR>
<td class="vmid tableheaderText">{{lang 'config.casparcg'}} *</td>
<td class="vmid tableheaderHelp aright" title="{{lang 'general.help'}}" onClick="help('casparcg');" onmouseover="tip('{{lang 'hover.help'}}');"><i class="far fa-question-circle"></i>&nbsp;</td>
</TR>
</table>
<hr class="h2hr"><!-- =========================================== -->
<table style="width: 100%;" cellspacing="5" border="0">
<!-- THIS NOT NEEDED, HUH?
<tr onmouseover="tip('{{lang 'hover.ccgtemplatepath'}}');">
<td width="40%">
<span class="spxConfigHead">{{lang 'config.ccgtemplates'}}*</span>
</td>
<td>
<input type="text" class="wide bg_grey15 cfg" placeholder="From casparcg.config" name="casparcg[relativeTemplateFolder]" value="{{config.casparcg.relativeTemplateFolder}}">
</td>
</tr>
-->
{{#each config.casparcg.servers}}
<tr>
<td width="40%">
<span class="spxConfigHead">
{{#ifValue @index 0}}
{{lang 'config.ccgservers'}}
{{else}}
&nbsp;
{{/ifValue}}
</span>
</td>
<td class="spxFlexContainer" style="padding:0px; margin:0px;" >
<span class="spxConfigHead">{{@index}}</span>
<input type="text" class="bg_grey15 cfg" style="margin:0px 4px 0px 0px; width:30%;" name="casparcg[servers][{{@index}}][name]" onmouseover="tip('{{lang 'hover.ccgserver'}}');" placeholder="Server name" value="{{name}}">
<input type="text" class="bg_grey15 cfg" style="margin:0px 4px 0px 0px; width:30%;" name="casparcg[servers][{{@index}}][host]" onmouseover="tip('{{lang 'hover.ccghost'}}');" placeholder="ip" value="{{host}}">
<input type="text" class="bg_grey15 cfg" style="margin:0px 0px 0px 0px; width:30%;" name="casparcg[servers][{{@index}}][port]" onmouseover="tip('{{lang 'hover.ccgport'}}');" placeholder="port" value="{{port}}">
</td>
</tr>
{{/each}}
<tr>
<td width="40%">
&nbsp;
</td>
<td class="spxFlexContainer" style="padding:0px; margin:0px;" onmouseover="tip('{{lang 'hover.addccgserver'}}');">
<span class="spxConfigHead">+</span>
<input type="text" class="bg_grey15 cfg" style="margin:0px 0px 0px 0px; width:30%;" name="NewName" placeholder="Server name" value="">
<input type="text" class="bg_grey15 cfg" style="margin:0px 0px 0px 5px; width:30%;" name="NewHost" placeholder="ip" value="">
<input type="text" class="bg_grey15 cfg" style="margin:0px 0px 0px 5px; width:30%;" name="NewPort" placeholder="port" value="">
</td>
</tr>
<tr>
<td width="40%">
&nbsp;
</td>
<td class="spxFlexContainer" style="padding:0px; margin:0px;" onmouseover="tip('{{lang 'hover.addccgserver'}}');">
<P class="spxConfigHead"
style="white-space: normal; line-height: 100%; opacity:0.5;">
<small><br>{{lang 'config.restartinfo'}}</small>
</td>
</tr>
</table>
<BR>
<!-- /////////////// extras starts ///////////////// -->
<table class="wide" border=0>
<TR>
<td class="vmid tableheaderText">{{lang 'config.globalbuttons'}} *</td>
<td class="vmid tableheaderHelp aright" title="{{lang 'general.help'}}" onClick="help('globalextras');" onmouseover="tip('{{lang 'hover.help'}}');"><i class="far fa-question-circle"></i>&nbsp;</td>
</TR>
</table>
<hr class="h2hr"><!-- =========================================== -->
<!-- script linker -->
<table style="width: 100%;" cellspacing="5" border="0">
<tr onmouseover="tip('{{lang 'hover.confjsfile'}}');">
<td width="40%">
<span class="spxConfigHead">{{lang 'config.functionlibrary'}}</span>
</td>
<td>
<input type="text" class="wide bg_grey15 cfg" placeholder="/path/in/ASSETS/filename.js" name="globalExtras[customscript]" value="{{config.globalExtras.customscript}}">
</td>
</tr>
</table>
<table style="width: 100%;" cellspacing="5" border="0">
<tr>
<td width="40%" class="vtop">
<span class="spxConfigHead">{{lang 'config.globalbuttons'}}</span>
</td>
<td><!-- button list starts -->
{{#each config.globalExtras.CustomControls}}
<!-- each extra button -->
<div id="extra{{@index}}">
<button class="collapsible globalCollapsible bg_grey15 row_accentExtras" type="button">{{description}}</button>
<div class="collapsiblecontent spxConfigHead" >
<input type="hidden" name="globalExtras[CustomControls][{{@index}}][ftype]" value="{{ftype}}">
<table class="wide" style="border: 0px solid pink; border-spacing: 10px; border-collapse: separate;" border="0">
<tr onmouseover="tip('{{lang 'hover.buttontype'}}');">
<td><span class="spxConfigHead">{{lang 'config.buttontype'}}</span></td>
<td><span class="spxConfigHead">{{ftype}}</span></td>
</tr>
<tr onmouseover="tip('{{lang 'hover.colors'}}');">
<td width="40%"><span class="spxConfigHead">{{lang 'config.buttoncolor'}}</span></td>
<td>
<select class="wide drop bg_grey15" name="globalExtras[CustomControls][{{@index}}][bgclass]">
{{{generateButtonColorClasses bgclass}}}
</select>
</td>
</tr>
{{#ifValue ftype "button"}}
<!-- something like click here -->
<tr onmouseover="tip('{{lang 'hover.text'}}');">
<td><span class="spxConfigHead">{{lang 'config.buttontext'}}</span></td>
<td>
<input type="text" class="wide bg_grey15 cfg" placeholder="Caption" name="globalExtras[CustomControls][{{@index}}][text]" value="{{text}}">
</td>
</tr>
<tr onmouseover="tip('{{lang 'hover.fcall'}}');">
<td><span class="spxConfigHead">{{lang 'config.functionhandler'}}</span></td>
<td><input type="text" class="wide bg_grey15 cfg" placeholder="clickHandler()" name="globalExtras[CustomControls][{{@index}}][fcall]" value="{{fcall}}"></td>
</tr>
{{/ifValue}}
{{#ifValue ftype "selectbutton"}}
<!-- something like choose an item here -->
<tr onmouseover="tip('{{lang 'hover.text'}}');">
<td><span class="spxConfigHead">{{lang 'config.buttontext'}}</span></td>
<td>
<input type="text" class="wide bg_grey15 cfg" placeholder="Caption" name="globalExtras[CustomControls][{{@index}}][text]" value="{{text}}">
</td>
</tr>
<tr onmouseover="tip('{{lang 'hover.fcall'}}');">
<td><span class="spxConfigHead">{{lang 'config.functionhandler'}}</span></td>
<td><input type="text" class="wide bg_grey15 cfg" placeholder="clickHandler()" name="globalExtras[CustomControls][{{@index}}][fcall]" value="{{fcall}}"></td>
</tr>
{{/ifValue}}
{{#ifValue ftype "togglebutton"}}
<!-- something like turn it on or off -->
<tr>
<td><span class="spxConfigHead">{{lang 'config.buttontexts'}}</span></td>
<td>
<input onmouseover="tip('{{lang 'hover.text'}}');" type="text" style="width: 49%;" class="bg_grey15 cfg" placeholder="ON" name="globalExtras[CustomControls][{{@index}}][text0]" value="{{text0}}">
<input onmouseover="tip('{{lang 'hover.text1'}}');" type="text" style="width: 49%;" class="bg_grey15 cfg" placeholder="OFF" name="globalExtras[CustomControls][{{@index}}][text1]" value="{{text1}}">
</td>
</tr>
<tr onmouseover="tip('{{lang 'hover.fcall'}}');">
<td><span class="spxConfigHead">{{lang 'config.functionhandler'}}</span></td>
<td><input type="text" class="wide bg_grey15 cfg" placeholder="toggleHandler()" name="globalExtras[CustomControls][{{@index}}][fcall]" value="{{fcall}}"></td>
</tr>
{{/ifValue}}
<tr onmouseover="tip('{{lang 'hover.extradescr'}}');">
<td><span class="spxConfigHead">{{lang 'config.functiondescription'}}</span></td>
<td><input type="text" class="wide bg_grey15 cfg" placeholder="Description" name="globalExtras[CustomControls][{{@index}}][description]" value="{{description}}"></td>
</tr>
</table>
<table class="wide" style="padding: 10px; margin-bottom:10px;">
<tr>
<td width="25%">
<button type="button" onmouseover="tip('{{lang 'hover.removeglobalextra'}}');" class="wide spxFlexItem btnsmall bg_grey10 ripple black" onClick="notImplemented();">{{lang 'button.deletebutton'}}</button>
</td>
<td>&nbsp;</td>
<td width="25%" class="center">
<!-- <button type="button" class="wide spxFlexItem btnsmall bg_grey10 ripple black" onClick="alert('Not implemented. Modify config.json manually.');">{{lang 'button.save'}}</button> -->
</td>
</tr>
</table>
</form>
</div><!--ended extra item -->
</div><!-- extra index ended -->
<!-- //each extra button -->
{{/each}}
<div class="wide" style="text-align: center; padding:0.5rem;">
<button type="button" class="addbtn bg_blue ripple" onmouseover="tip('{{lang 'hover.browseglobalextras'}}');" onClick="notImplemented();">+</button>
</div>
</td><!-- button list ended -->
</tr>
</table>
<!-- /////////////// extras ended ///////////////// -->
<HR><!-- save / cancel buttons -->
<center>
<span class="spxConfigHead">* {{lang 'config.restartinfo'}}</span>
</center>
<BR>
<div class="spxFlexContainer">
<button onmouseover="tip('{{lang 'hover.saveconfig'}}');" class="wide spxFlexItem btn bg_green ripple" type="submit" form="config">{{lang 'button.save'}}</button>
<button type="button" onmouseover="tip('{{lang 'hover.cancelconfig'}}');" class="wide spxFlexItem btn bg_red ripple" onClick="location.href='/';">{{lang 'button.cancel'}}</button>
</div>
</form>
</div><!-- itemlist ended -->
</div><!-- center wrapper ended -->
</div><!-- content ended -->
{{>footer}}
</div><!-- MAINwrapper ended -->
<script>
var RendererUrl = location.protocol+'//'+location.hostname+(location.port ? ':'+location.port: '') + '/renderer/';
document.getElementById('rendererLink').value = RendererUrl;
var APIUrl = location.protocol+'//'+location.hostname+(location.port ? ':'+location.port: '') + '/api/v1/';
document.getElementById('apiLink').value = APIUrl;
// COLLAPSIPLE HANDLERS
var coll = document.getElementsByClassName("collapsible");
var i;
for (i = 0; i < coll.length; i++) {
coll[i].addEventListener("click", function() {
this.classList.toggle("active");
var content = this.nextElementSibling;
if (content.style.maxHeight){
content.style.maxHeight = null;
} else {
content.style.maxHeight = content.scrollHeight + "px";
}
});
}
function notImplemented() {
// request .....
// returns .....
// Describe the function here
alert('Not implemented yet.\n\nPlease modify config.json manually. Read help for additional information.');
} // NotImplemented ed
// See spx_gc.js
function pageInit(){
heartbeat(203); // page identifier
spxInit('');
}
</script>
</body>
</html>