UI overhaul (#383)

This commit is contained in:
Michael Green
2024-09-01 01:00:54 +10:00
committed by GitHub
parent fd7b354571
commit deef919d5b
179 changed files with 18355 additions and 8819 deletions

Binary file not shown.

View File

@@ -22,9 +22,11 @@
if (StateUrl) {
console.log('Loading saved state from: ' + StateUrl);
EJS_loadStateURL = StateUrl;
EJS_startOnLoaded = true;
}
// start the emulator automatically when loaded
EJS_startOnLoaded = true;
// Path to the data directory
EJS_pathtodata = '/emulators/EmulatorJS/data/';
@@ -42,10 +44,11 @@
EJS_Buttons = {
saveSavFiles: false,
loadSavFiles: false
loadSavFiles: false,
exitEmulation: false
}
EJS_onSaveState = function(e) {
EJS_onSaveState = function (e) {
var returnValue = {
"ScreenshotByteArrayBase64": btoa(Uint8ToString(e.screenshot)),
"StateByteArrayBase64": btoa(Uint8ToString(e.state))
@@ -72,8 +75,12 @@
returnValue = undefined;
}
EJS_onLoadState = function(e) {
showDialog('emulatorloadstate', { "romId": romId, "IsMediaGroup": IsMediaGroup });
EJS_onLoadState = function (e) {
let rompath = decodeURIComponent(getQueryString('rompath', 'string'));
rompath = rompath.substring(rompath.lastIndexOf('/') + 1);
console.log(rompath);
let stateManager = new EmulatorStateManager(romId, IsMediaGroup, getQueryString('engine', 'string'), getQueryString('core', 'string'), platformId, gameId, rompath);
stateManager.open();
}
</script>
<script src='/emulators/EmulatorJS/data/loader.js'></script>

View File

@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<svg width="800px" height="800px" viewBox="0 0 48 48" xmlns="http://www.w3.org/2000/svg">
<title>stop-warning</title>
<g id="Layer_2" data-name="Layer 2">
<g id="invisible_box" data-name="invisible box">
<rect width="48" height="48" fill="none"/>
</g>
<g id="icons_Q2" data-name="icons Q2">
<g>
<path d="M43.4,15.1,32.9,4.6A2,2,0,0,0,31.5,4h-15a2,2,0,0,0-1.4.6L4.6,15.1A2,2,0,0,0,4,16.5v15a2,2,0,0,0,.6,1.4L15.1,43.4a2,2,0,0,0,1.4.6h15a2,2,0,0,0,1.4-.6L43.4,32.9a2,2,0,0,0,.6-1.4v-15A2,2,0,0,0,43.4,15.1ZM40,30.6,30.6,40H17.4L8,30.6V17.4L17.4,8H30.6L40,17.4Z"/>
<path d="M26.8,24l5.6-5.6a2,2,0,0,0-2.8-2.8L24,21.2l-5.6-5.6a2,2,0,0,0-2.8,2.8L21.2,24l-5.6,5.6a1.9,1.9,0,0,0,0,2.8,1.9,1.9,0,0,0,2.8,0L24,26.8l5.6,5.6a1.9,1.9,0,0,0,2.8,0,1.9,1.9,0,0,0,0-2.8Z"/>
</g>
</g>
</g>

After

Width:  |  Height:  |  Size: 969 B

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 480 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 8.3 KiB

View File

@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<svg width="800px" height="800px" viewBox="0 0 48 48" xmlns="http://www.w3.org/2000/svg">
<title>warning</title>
<g id="Layer_2" data-name="Layer 2">
<g id="invisible_box" data-name="invisible box">
<rect width="48" height="48" fill="none"/>
</g>
<g id="icons_Q2" data-name="icons Q2">
<g>
<path d="M24,9,40.6,39H7.5L24,9M2.3,40A2,2,0,0,0,4,43H44a2,2,0,0,0,1.7-3L25.7,4a2,2,0,0,0-3.4,0Z"/>
<path d="M22,19v9a2,2,0,0,0,4,0V19a2,2,0,0,0-4,0Z"/>
<circle cx="24" cy="34" r="2"/>
</g>
</g>
</g>

After

Width:  |  Height:  |  Size: 695 B

View File

@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<svg fill="#000000" height="800px" width="800px" version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
viewBox="0 0 512.011 512.011" xml:space="preserve">
<g>
<g>
<path d="M505.755,123.592c-8.341-8.341-21.824-8.341-30.165,0L256.005,343.176L36.421,123.592c-8.341-8.341-21.824-8.341-30.165,0
s-8.341,21.824,0,30.165l234.667,234.667c4.16,4.16,9.621,6.251,15.083,6.251c5.462,0,10.923-2.091,15.083-6.251l234.667-234.667
C514.096,145.416,514.096,131.933,505.755,123.592z"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 684 B

View File

@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<svg fill="#000000" height="800px" width="800px" version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
viewBox="0 0 512.006 512.006" xml:space="preserve">
<g>
<g>
<path d="M388.419,475.59L168.834,256.005L388.418,36.421c8.341-8.341,8.341-21.824,0-30.165s-21.824-8.341-30.165,0
L123.586,240.923c-8.341,8.341-8.341,21.824,0,30.165l234.667,234.667c4.16,4.16,9.621,6.251,15.083,6.251
c5.461,0,10.923-2.091,15.083-6.251C396.76,497.414,396.76,483.931,388.419,475.59z"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 679 B

View File

@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<svg fill="#000000" height="800px" width="800px" version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
viewBox="0 0 512.005 512.005" xml:space="preserve">
<g>
<g>
<path d="M388.418,240.923L153.751,6.256c-8.341-8.341-21.824-8.341-30.165,0s-8.341,21.824,0,30.165L343.17,256.005
L123.586,475.589c-8.341,8.341-8.341,21.824,0,30.165c4.16,4.16,9.621,6.251,15.083,6.251c5.461,0,10.923-2.091,15.083-6.251
l234.667-234.667C396.759,262.747,396.759,249.264,388.418,240.923z"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 682 B

View File

@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<svg fill="#000000" height="800px" width="800px" version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
viewBox="0 0 512 512" xml:space="preserve">
<g>
<g>
<path d="M505.752,358.248L271.085,123.582c-8.331-8.331-21.839-8.331-30.17,0L6.248,358.248c-8.331,8.331-8.331,21.839,0,30.17
s21.839,8.331,30.17,0L256,168.837l219.582,219.582c8.331,8.331,21.839,8.331,30.17,0S514.083,366.58,505.752,358.248z"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 609 B

View File

@@ -0,0 +1,69 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
viewBox="0 0 512 512" xml:space="preserve">
<g>
<rect x="342.232" y="460.8" style="fill:#AFB6BB;" width="43.116" height="37.726"/>
<rect x="234.442" y="460.8" style="fill:#AFB6BB;" width="43.116" height="37.726"/>
<rect x="126.653" y="460.8" style="fill:#AFB6BB;" width="43.116" height="37.726"/>
<rect x="8.084" y="234.442" style="fill:#AFB6BB;" width="43.116" height="43.116"/>
<rect x="8.084" y="342.232" style="fill:#AFB6BB;" width="43.116" height="43.116"/>
<rect x="460.8" y="342.232" style="fill:#AFB6BB;" width="43.116" height="43.116"/>
<rect x="460.8" y="234.442" style="fill:#AFB6BB;" width="43.116" height="43.116"/>
<rect x="460.8" y="126.653" style="fill:#AFB6BB;" width="43.116" height="43.116"/>
<rect x="342.232" y="13.474" style="fill:#AFB6BB;" width="43.116" height="37.726"/>
<rect x="234.442" y="13.474" style="fill:#AFB6BB;" width="43.116" height="37.726"/>
<rect x="126.653" y="13.474" style="fill:#AFB6BB;" width="43.116" height="37.726"/>
<rect x="8.084" y="126.653" style="fill:#AFB6BB;" width="43.116" height="43.116"/>
</g>
<g>
<rect x="51.2" y="126.653" style="fill:#E7ECED;" width="32.337" height="43.116"/>
<rect x="51.2" y="234.442" style="fill:#E7ECED;" width="32.337" height="43.116"/>
<rect x="51.2" y="342.232" style="fill:#E7ECED;" width="32.337" height="43.116"/>
<rect x="126.653" y="428.463" style="fill:#E7ECED;" width="43.116" height="32.337"/>
<rect x="234.442" y="428.463" style="fill:#E7ECED;" width="43.116" height="32.337"/>
<rect x="342.232" y="428.463" style="fill:#E7ECED;" width="43.116" height="32.337"/>
<rect x="428.463" y="342.232" style="fill:#E7ECED;" width="32.337" height="43.116"/>
<rect x="428.463" y="234.442" style="fill:#E7ECED;" width="32.337" height="43.116"/>
<rect x="428.463" y="126.653" style="fill:#E7ECED;" width="32.337" height="43.116"/>
<rect x="342.232" y="51.2" style="fill:#E7ECED;" width="43.116" height="32.337"/>
<rect x="234.442" y="51.2" style="fill:#E7ECED;" width="43.116" height="32.337"/>
<rect x="126.653" y="51.2" style="fill:#E7ECED;" width="43.116" height="32.337"/>
</g>
<path style="fill:#595E62;" d="M428.463,385.347v32.337c0,5.928-4.851,10.779-10.779,10.779h-32.337h-43.116h-64.674h-43.116
h-64.674h-43.116H94.316c-5.928,0-10.779-4.851-10.779-10.779v-32.337v-43.116v-64.674v-43.116v-64.674v-43.116V94.316
c0-5.928,4.851-10.779,10.779-10.779h32.337h43.116h64.674h43.116h64.674h43.116h32.337c5.928,0,10.779,4.851,10.779,10.779v32.337
v43.116v64.674v43.116v64.674V385.347z M385.347,385.347V126.653H126.653v258.695H385.347z"/>
<rect x="126.653" y="126.653" style="fill:#36C63F;" width="258.695" height="258.695"/>
<path style="fill:#00AB4E;" d="M173.785,126.653h-47.132v258.695h258.695v-47.132C284.709,306.659,205.341,227.291,173.785,126.653z
"/>
<path style="fill:#44494C;" d="M126.653,385.347V126.653H256V83.537h-21.558h-64.674h-43.116H94.316
c-5.928,0-10.779,4.851-10.779,10.779v32.337v43.116v64.674v43.116v64.674v43.116v32.337c0,5.928,4.851,10.779,10.779,10.779h32.337
h43.116h64.674H256v-43.116H126.653z"/>
<g>
<rect x="180.547" y="161.684" style="fill:#FFFFFF;" width="150.905" height="16.168"/>
<rect x="180.547" y="237.137" style="fill:#FFFFFF;" width="150.905" height="16.168"/>
<rect x="180.547" y="199.411" style="fill:#FFFFFF;" width="26.947" height="16.168"/>
<rect x="180.547" y="334.147" style="fill:#FFFFFF;" width="26.947" height="16.168"/>
<rect x="223.663" y="334.147" style="fill:#FFFFFF;" width="26.947" height="16.168"/>
<rect x="299.116" y="334.147" style="fill:#FFFFFF;" width="26.947" height="16.168"/>
<rect x="239.832" y="199.411" style="fill:#FFFFFF;" width="91.621" height="16.168"/>
</g>
<path d="M118.568,393.432h274.863V118.568H118.568V393.432z M134.737,134.737h242.526v242.526H134.737V134.737z"/>
<path d="M512,177.853v-59.284h-75.453V94.316c0-10.401-8.463-18.863-18.863-18.863h-24.253V5.389h-59.284v70.063h-48.505V5.389
h-59.284v70.063h-48.505V5.389h-59.284v70.063H94.316c-10.401,0-18.863,8.463-18.863,18.863v24.253H0v59.284h75.453v48.505H0v59.284
h75.453v48.505H0v59.284h75.453v24.253c0,10.401,8.463,18.863,18.863,18.863h24.253v70.063h59.284v-70.063h48.505v70.063h59.284
v-70.063h48.505v70.063h59.284v-70.063h24.253c10.401,0,18.863-8.463,18.863-18.863v-24.253H512v-59.284h-75.453v-48.505H512
v-59.284h-75.453v-48.505H512z M436.547,134.737h16.168v26.947h-16.168V134.737z M495.832,161.684h-26.947v-26.947h26.947V161.684z
M350.316,59.284h26.947v16.168h-26.947V59.284z M377.263,21.558v21.558h-26.947V21.558H377.263z M242.526,59.284h26.947v16.168
h-26.947V59.284z M269.474,21.558v21.558h-26.947V21.558H269.474z M134.737,59.284h26.947v16.168h-26.947V59.284z M161.684,21.558
v21.558h-26.947V21.558H161.684z M75.453,161.684H59.284v-26.947h16.168V161.684z M16.168,134.737h26.947v26.947H16.168V134.737z
M75.453,269.474H59.284v-26.947h16.168V269.474z M16.168,242.526h26.947v26.947H16.168V242.526z M75.453,377.263H59.284v-26.947
h16.168V377.263z M16.168,350.316h26.947v26.947H16.168V350.316z M161.684,452.716h-26.947v-16.168h26.947V452.716z
M134.737,490.442v-21.558h26.947v21.558H134.737z M269.474,452.716h-26.947v-16.168h26.947V452.716z M242.526,490.442v-21.558
h26.947v21.558H242.526z M377.263,452.716h-26.947v-16.168h26.947V452.716z M350.316,490.442v-21.558h26.947v21.558H350.316z
M436.547,350.316h16.168v26.947h-16.168V350.316z M495.832,377.263h-26.947v-26.947h26.947V377.263z M436.547,242.526h16.168
v26.947h-16.168V242.526z M495.832,269.474h-26.947v-26.947h26.947V269.474z M420.379,417.684c0,1.461-1.234,2.695-2.695,2.695
H94.316c-1.461,0-2.695-1.234-2.695-2.695V94.316c0-1.461,1.234-2.695,2.695-2.695h323.368c1.461,0,2.695,1.234,2.695,2.695V417.684
z"/>
</svg>

After

Width:  |  Height:  |  Size: 5.8 KiB

View File

@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<svg width="800px" height="800px" viewBox="0 0 32 32" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:sketch="http://www.bohemiancoding.com/sketch/ns">
<title>cross-circle</title>
<desc>Created with Sketch Beta.</desc>
<defs>
</defs>
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" sketch:type="MSPage">
<g id="Icon-Set" sketch:type="MSLayerGroup" transform="translate(-568.000000, -1087.000000)" fill="red">
<path d="M584,1117 C576.268,1117 570,1110.73 570,1103 C570,1095.27 576.268,1089 584,1089 C591.732,1089 598,1095.27 598,1103 C598,1110.73 591.732,1117 584,1117 L584,1117 Z M584,1087 C575.163,1087 568,1094.16 568,1103 C568,1111.84 575.163,1119 584,1119 C592.837,1119 600,1111.84 600,1103 C600,1094.16 592.837,1087 584,1087 L584,1087 Z M589.717,1097.28 C589.323,1096.89 588.686,1096.89 588.292,1097.28 L583.994,1101.58 L579.758,1097.34 C579.367,1096.95 578.733,1096.95 578.344,1097.34 C577.953,1097.73 577.953,1098.37 578.344,1098.76 L582.58,1102.99 L578.314,1107.26 C577.921,1107.65 577.921,1108.29 578.314,1108.69 C578.708,1109.08 579.346,1109.08 579.74,1108.69 L584.006,1104.42 L588.242,1108.66 C588.633,1109.05 589.267,1109.05 589.657,1108.66 C590.048,1108.27 590.048,1107.63 589.657,1107.24 L585.42,1103.01 L589.717,1098.71 C590.11,1098.31 590.11,1097.68 589.717,1097.28 L589.717,1097.28 Z" id="cross-circle" sketch:type="MSShapeGroup">
</path>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?><!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<svg width="800px" height="800px" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M18.59 5.88997C17.36 5.31997 16.05 4.89997 14.67 4.65997C14.5 4.95997 14.3 5.36997 14.17 5.69997C12.71 5.47997 11.26 5.47997 9.83001 5.69997C9.69001 5.36997 9.49001 4.95997 9.32001 4.65997C7.94001 4.89997 6.63001 5.31997 5.40001 5.88997C2.92001 9.62997 2.25001 13.28 2.58001 16.87C4.23001 18.1 5.82001 18.84 7.39001 19.33C7.78001 18.8 8.12001 18.23 8.42001 17.64C7.85001 17.43 7.31001 17.16 6.80001 16.85C6.94001 16.75 7.07001 16.64 7.20001 16.54C10.33 18 13.72 18 16.81 16.54C16.94 16.65 17.07 16.75 17.21 16.85C16.7 17.16 16.15 17.42 15.59 17.64C15.89 18.23 16.23 18.8 16.62 19.33C18.19 18.84 19.79 18.1 21.43 16.87C21.82 12.7 20.76 9.08997 18.61 5.88997H18.59ZM8.84001 14.67C7.90001 14.67 7.13001 13.8 7.13001 12.73C7.13001 11.66 7.88001 10.79 8.84001 10.79C9.80001 10.79 10.56 11.66 10.55 12.73C10.55 13.79 9.80001 14.67 8.84001 14.67ZM15.15 14.67C14.21 14.67 13.44 13.8 13.44 12.73C13.44 11.66 14.19 10.79 15.15 10.79C16.11 10.79 16.87 11.66 16.86 12.73C16.86 13.79 16.11 14.67 15.15 14.67Z" fill="#000000"/>
</svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@@ -0,0 +1 @@
<svg width="98" height="96" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" clip-rule="evenodd" d="M48.854 0C21.839 0 0 22 0 49.217c0 21.756 13.993 40.172 33.405 46.69 2.427.49 3.316-1.059 3.316-2.362 0-1.141-.08-5.052-.08-9.127-13.59 2.934-16.42-5.867-16.42-5.867-2.184-5.704-5.42-7.17-5.42-7.17-4.448-3.015.324-3.015.324-3.015 4.934.326 7.523 5.052 7.523 5.052 4.367 7.496 11.404 5.378 14.235 4.074.404-3.178 1.699-5.378 3.074-6.6-10.839-1.141-22.243-5.378-22.243-24.283 0-5.378 1.94-9.778 5.014-13.2-.485-1.222-2.184-6.275.486-13.038 0 0 4.125-1.304 13.426 5.052a46.97 46.97 0 0 1 12.214-1.63c4.125 0 8.33.571 12.213 1.63 9.302-6.356 13.427-5.052 13.427-5.052 2.67 6.763.97 11.816.485 13.038 3.155 3.422 5.015 7.822 5.015 13.2 0 18.905-11.404 23.06-22.324 24.283 1.78 1.548 3.316 4.481 3.316 9.126 0 6.6-.08 11.897-.08 13.526 0 1.304.89 2.853 3.316 2.364 19.412-6.52 33.405-24.935 33.405-46.691C97.707 22 75.788 0 48.854 0z" fill="#24292f"/></svg>

After

Width:  |  Height:  |  Size: 963 B

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 567 KiB

View File

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?><!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<svg width="800px" height="800px" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M11.3103 1.77586C11.6966 1.40805 12.3034 1.40805 12.6897 1.77586L20.6897 9.39491L23.1897 11.7759C23.5896 12.1567 23.605 12.7897 23.2241 13.1897C22.8433 13.5896 22.2103 13.605 21.8103 13.2241L21 12.4524V20C21 21.1046 20.1046 22 19 22H14H10H5C3.89543 22 3 21.1046 3 20V12.4524L2.18966 13.2241C1.78972 13.605 1.15675 13.5896 0.775862 13.1897C0.394976 12.7897 0.410414 12.1567 0.810345 11.7759L3.31034 9.39491L11.3103 1.77586ZM5 10.5476V20H9V15C9 13.3431 10.3431 12 12 12C13.6569 12 15 13.3431 15 15V20H19V10.5476L12 3.88095L5 10.5476ZM13 20V15C13 14.4477 12.5523 14 12 14C11.4477 14 11 14.4477 11 15V20H13Z" fill="#000000"/>
</svg>

After

Width:  |  Height:  |  Size: 901 B

View File

@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<svg width="800px" height="800px" viewBox="0 0 14 14" xmlns="http://www.w3.org/2000/svg">
<g fill-rule="evenodd">
<path d="M0 7a7 7 0 1 1 14 0A7 7 0 0 1 0 7z"/>

After

Width:  |  Height:  |  Size: 576 B

View File

@@ -0,0 +1,54 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<svg fill="#000000" height="800px" width="800px" version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
viewBox="0 0 33.132 33.132" xml:space="preserve">
<g>
<path d="M33.132,30.941l-6.096-5.439c1.151-1.459,1.843-3.297,1.843-5.297c0-4.453-3.414-8.107-7.761-8.525
c-0.061-0.18-0.127-0.355-0.232-0.537l-0.148-0.258c0.339-0.482,0.529-0.996,0.529-1.535V6.289c0-0.416-0.116-0.838-0.347-1.256
l-0.07-0.131c0.095-0.221,0.161-0.447,0.161-0.688c0-2.472-5.35-3.81-10.379-3.81c-5.03,0-10.375,1.338-10.375,3.811
c0,0.24,0.064,0.467,0.16,0.688L0.345,5.037C0.114,5.451,0,5.873,0,6.289V9.35c0,0.539,0.188,1.053,0.528,1.535l-0.15,0.262
C0.126,11.578,0,12.019,0,12.455v3.062c0,0.525,0.179,1.029,0.502,1.502l-0.124,0.213C0.126,17.666,0,18.107,0,18.539v3.066
c0,2.721,4.669,4.85,10.632,4.85c1.221,0,2.383-0.092,3.465-0.26c-0.068-0.09-0.123-0.193-0.188-0.291
c1.571,1.762,3.846,2.881,6.389,2.881c2.076,0,3.984-0.74,5.47-1.973l5.431,5.916L33.132,30.941z M16.665,16.543
c2.088-2.074,5.455-2.061,7.523,0.02c2.073,2.086,2.059,5.459-0.024,7.525c-2.087,2.072-5.454,2.062-7.528-0.023
C14.565,21.98,14.583,18.611,16.665,16.543z M10.632,1.545c5.723,0,9.24,1.555,9.24,2.67c0,1.117-3.518,2.672-9.24,2.672
c-5.726,0-9.238-1.555-9.238-2.672C1.394,3.099,4.906,1.545,10.632,1.545z M1.14,6.802c1.705,1.445,5.66,2.193,9.492,2.193
c3.834,0,7.787-0.748,9.494-2.193v2.547c0,1.756-3.896,3.713-9.494,3.713c-5.594,0-9.492-1.957-9.492-3.713
C1.14,9.349,1.14,6.802,1.14,6.802z M1.14,12.636c1.744,1.6,5.336,2.621,9.492,2.621c0.99,0,1.926-0.078,2.829-0.191
c-0.695,0.926-1.224,1.986-1.501,3.146c-0.077,0.316-0.136,0.639-0.176,0.969c-0.382,0.018-0.754,0.049-1.152,0.049
c-5.594,0-9.492-1.957-9.492-3.713C1.14,15.517,1.14,12.636,1.14,12.636z M10.632,25.318c-5.594,0-9.492-1.957-9.492-3.713v-2.881
c1.744,1.6,5.336,2.619,9.492,2.619c0.396,0,0.779-0.025,1.164-0.049c0.133,1.045,0.447,2.029,0.922,2.918
c0.173,0.332,0.38,0.641,0.594,0.941C12.474,25.258,11.579,25.318,10.632,25.318z"/>
<path d="M24.4,19.961l0.379-1.129c-2.979-4.801-7.113-2.014-7.113-2.014C22.841,15.881,24.4,19.961,24.4,19.961z"/>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.4 KiB

View File

@@ -0,0 +1,70 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="30"
height="30"
viewBox="0 0 30 30"
version="1.1"
id="svg822"
inkscape:version="0.92.4 (f8dce91, 2019-08-02)"
sodipodi:docname="recent.svg">
<defs
id="defs816" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="17.833333"
inkscape:cx="15"
inkscape:cy="15"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="true"
units="px"
inkscape:window-width="1366"
inkscape:window-height="713"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
showguides="false">
<inkscape:grid
type="xygrid"
id="grid816" />
</sodipodi:namedview>
<metadata
id="metadata819">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title>
</dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(0,-289.0625)">
<path
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
d="M 15 3 C 8.3844276 3 3 8.38443 3 15 C 3 21.61557 8.3844276 27 15 27 C 21.615572 27 27 21.61557 27 15 C 27 8.38443 21.615572 3 15 3 z M 15 5 C 20.534692 5 25 9.46531 25 15 C 25 20.53469 20.534692 25 15 25 C 9.4653079 25 5 20.53469 5 15 C 5 9.46531 9.4653079 5 15 5 z M 15 7 C 14.446 7 14 7.446 14 8 L 14 15 C 14 15.554 14.446 16 15 16 L 22 16 C 22.554 16 23 15.554 23 15 C 23 14.446 22.554 14 22 14 L 16 14 L 16 8 C 16 7.446 15.554 7 15 7 z "
transform="translate(0,289.0625)"
id="path1099" />
</g>

After

Width:  |  Height:  |  Size: 3.5 KiB

View File

@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg fill="#000000" version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
width="800px" height="800px" viewBox="0 0 46 46" xml:space="preserve">
<g>
<g>
<path d="M20.913,34.756c-0.625,0.627-1.565,0.816-2.383,0.479c-0.818-0.336-1.352-1.135-1.352-2.02V12.784
c0-0.885,0.534-1.683,1.352-2.021c0.818-0.338,1.759-0.149,2.383,0.479l9.657,9.706c1.129,1.134,1.129,2.967,0,4.102
L20.913,34.756z"/>
<path d="M23,6c9.374,0,17,7.626,17,17s-7.626,17-17,17S6,32.374,6,23S13.626,6,23,6 M23,0C10.298,0,0,10.297,0,23s10.298,23,23,23
s23-10.297,23-23S35.702,0,23,0L23,0z"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 878 B

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?><!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<svg width="800px" height="800px" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg" version="1.1" fill="none" stroke="#000000" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5">
<path d="m14.25 8.75c-.5 2.5-2.3849 4.85363-5.03069 5.37991-2.64578.5263-5.33066-.7044-6.65903-3.0523-1.32837-2.34784-1.00043-5.28307.81336-7.27989 1.81379-1.99683 4.87636-2.54771 7.37636-1.54771"/>
<polyline points="5.75 7.75,8.25 10.25,14.25 3.75"/>
<?xml version="1.0" encoding="utf-8"?><!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<svg width="800px" height="800px" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M12 22C17.5 22 22 17.5 22 12C22 6.5 17.5 2 12 2C6.5 2 2 6.5 2 12C2 17.5 6.5 22 12 22Z" stroke="green" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M7.75 12L10.58 14.83L16.25 9.17004" stroke="green" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

Before

Width:  |  Height:  |  Size: 579 B

After

Width:  |  Height:  |  Size: 538 B

View File

@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?><!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<svg width="800px" height="800px" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M3 1C1.89543 1 1 1.89543 1 3V5C1 6.10457 1.89543 7 3 7H5C6.10457 7 7 6.10457 7 5V3C7 1.89543 6.10457 1 5 1H3ZM5 3H3L3 5H5V3Z" fill="#0F0F0F"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M3 9C1.89543 9 1 9.89543 1 11V13C1 14.1046 1.89543 15 3 15H5C6.10457 15 7 14.1046 7 13V11C7 9.89543 6.10457 9 5 9H3ZM5 11H3L3 13H5V11Z" fill="#0F0F0F"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M1 19C1 17.8954 1.89543 17 3 17H5C6.10457 17 7 17.8954 7 19V21C7 22.1046 6.10457 23 5 23H3C1.89543 23 1 22.1046 1 21V19ZM3 19H5V21H3L3 19Z" fill="#0F0F0F"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M11 1C9.89543 1 9 1.89543 9 3V5C9 6.10457 9.89543 7 11 7H13C14.1046 7 15 6.10457 15 5V3C15 1.89543 14.1046 1 13 1H11ZM13 3H11V5H13V3Z" fill="#0F0F0F"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M9 11C9 9.89543 9.89543 9 11 9H13C14.1046 9 15 9.89543 15 11V13C15 14.1046 14.1046 15 13 15H11C9.89543 15 9 14.1046 9 13V11ZM11 11H13V13H11V11Z" fill="#0F0F0F"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M11 17C9.89543 17 9 17.8954 9 19V21C9 22.1046 9.89543 23 11 23H13C14.1046 23 15 22.1046 15 21V19C15 17.8954 14.1046 17 13 17H11ZM13 19H11V21H13V19Z" fill="#0F0F0F"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M17 3C17 1.89543 17.8954 1 19 1H21C22.1046 1 23 1.89543 23 3V5C23 6.10457 22.1046 7 21 7H19C17.8954 7 17 6.10457 17 5V3ZM19 3H21V5H19V3Z" fill="#0F0F0F"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M19 9C17.8954 9 17 9.89543 17 11V13C17 14.1046 17.8954 15 19 15H21C22.1046 15 23 14.1046 23 13V11C23 9.89543 22.1046 9 21 9H19ZM21 11H19V13H21V11Z" fill="#0F0F0F"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M17 19C17 17.8954 17.8954 17 19 17H21C22.1046 17 23 17.8954 23 19V21C23 22.1046 22.1046 23 21 23H19C17.8954 23 17 22.1046 17 21V19ZM19 19H21V21H19V19Z" fill="#0F0F0F"/>
</svg>

After

Width:  |  Height:  |  Size: 2.1 KiB

View File

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<svg width="800px" height="800px" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
<g fill="#2e3436">
<path d="m 5.5 0 c -0.277344 0 -0.5 0.222656 -0.5 0.5 v 1 c 0 0.277344 0.222656 0.5 0.5 0.5 h 5 c 0.277344 0 0.5 -0.222656 0.5 -0.5 v -1 c 0 -0.277344 -0.222656 -0.5 -0.5 -0.5 z m 0 3 c -0.277344 0 -0.5 0.222656 -0.5 0.5 v 1 c 0 0.277344 0.222656 0.5 0.5 0.5 h 5 c 0.277344 0 0.5 -0.222656 0.5 -0.5 v -1 c 0 -0.277344 -0.222656 -0.5 -0.5 -0.5 z m 0 8 c -0.277344 0 -0.5 0.222656 -0.5 0.5 v 1 c 0 0.277344 0.222656 0.5 0.5 0.5 h 5 c 0.277344 0 0.5 -0.222656 0.5 -0.5 v -1 c 0 -0.277344 -0.222656 -0.5 -0.5 -0.5 z m 0 3 c -0.277344 0 -0.5 0.222656 -0.5 0.5 v 1 c 0 0.277344 0.222656 0.5 0.5 0.5 h 5 c 0.277344 0 0.5 -0.222656 0.5 -0.5 v -1 c 0 -0.277344 -0.222656 -0.5 -0.5 -0.5 z m 0 0" fill-opacity="0.34902"/>
<path d="m 15 7 h -14 v 2 h 14 z m 0 0"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1023 B

View File

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?><!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<svg width="800px" height="800px" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M9 6C9 4.34315 7.65685 3 6 3H4C2.34315 3 1 4.34315 1 6V8C1 9.65685 2.34315 11 4 11H6C7.65685 11 9 9.65685 9 8V6ZM7 6C7 5.44772 6.55228 5 6 5H4C3.44772 5 3 5.44772 3 6V8C3 8.55228 3.44772 9 4 9H6C6.55228 9 7 8.55228 7 8V6Z" fill="#0F0F0F"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M9 16C9 14.3431 7.65685 13 6 13H4C2.34315 13 1 14.3431 1 16V18C1 19.6569 2.34315 21 4 21H6C7.65685 21 9 19.6569 9 18V16ZM7 16C7 15.4477 6.55228 15 6 15H4C3.44772 15 3 15.4477 3 16V18C3 18.5523 3.44772 19 4 19H6C6.55228 19 7 18.5523 7 18V16Z" fill="#0F0F0F"/>
<path d="M11 7C11 6.44772 11.4477 6 12 6H22C22.5523 6 23 6.44772 23 7C23 7.55228 22.5523 8 22 8H12C11.4477 8 11 7.55228 11 7Z" fill="#0F0F0F"/>
<path d="M11 17C11 16.4477 11.4477 16 12 16H22C22.5523 16 23 16.4477 23 17C23 17.5523 22.5523 18 22 18H12C11.4477 18 11 17.5523 11 17Z" fill="#0F0F0F"/>
</svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<svg width="800px" height="800px" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
<g fill="#2e3436">
<path d="m 9 5.5 v -1 c 0 -0.277344 -0.222656 -0.5 -0.5 -0.5 h -3 c -0.277344 0 -0.5 0.222656 -0.5 0.5 v 1 c 0 0.277344 0.222656 0.5 0.5 0.5 h 3 c 0.277344 0 0.5 -0.222656 0.5 -0.5 z m 0 0" fill-opacity="0.34902"/>
<path d="m 4 0 c -1.644531 0 -3 1.355469 -3 3 v 7 c 0 1.644531 1.355469 3 3 3 h 6 c 1.644531 0 3 -1.355469 3 -3 v -7 c 0 -1.644531 -1.355469 -3 -3 -3 z m 0 2 h 6 c 0.570312 0 1 0.429688 1 1 v 7 c 0 0.570312 -0.429688 1 -1 1 h -6 c -0.570312 0 -1 -0.429688 -1 -1 v -7 c 0 -0.570312 0.429688 -1 1 -1 z m 11 2 c -0.550781 0 -1 0.449219 -1 1 v 8 c 0 0.550781 -0.449219 1 -1 1 h -7 c -0.550781 0 -1 0.449219 -1 1 s 0.449219 1 1 1 h 7 c 1.65625 0 3 -1.34375 3 -3 v -8 c 0 -0.550781 -0.449219 -1 -1 -1 z m 0 0"/>
<path d="m 9 8.5 v -1 c 0 -0.277344 -0.222656 -0.5 -0.5 -0.5 h -3 c -0.277344 0 -0.5 0.222656 -0.5 0.5 v 1 c 0 0.277344 0.222656 0.5 0.5 0.5 h 3 c 0.277344 0 0.5 -0.222656 0.5 -0.5 z m 0 0" fill-opacity="0.34902"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@@ -1,23 +1,9 @@
<!DOCTYPE html>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<script src="/api/v1.1/System/VersionFile"></script>
<link type="text/css" rel="stylesheet" href="/styles/style.css" dat-href="/styles/style.css" />
<link type="text/css" rel="stylesheet" href="/styles/notifications.css" dat-href="/styles/notifications.css" />
<script src="/scripts/jquery-3.6.0.min.js"></script>
<script src="/scripts/moment-with-locales.min.js"></script>
<link href="/styles/select2.min.css" rel="stylesheet" />
<link href="/styles/dropzone.min.css" rel="stylesheet" type="text/css" />
<script src="/scripts/jquery.lazy.min.js"></script>
<script src="/scripts/jquery.lazy.plugins.min.js"></script>
<script src="/scripts/select2.min.js"></script>
<script src="/scripts/dropzone.min.js"></script>
<script src="/scripts/simpleUpload.min.js"></script>
<script src="/scripts/main.js" type="text/javascript"></script>
<script src="/scripts/notifications.js" type="text/javascript"></script>
<script src="/scripts/filterformating.js" type="text/javascript"></script>
<script src="/scripts/gamesformating.js" type="text/javascript"></script>
<link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png">
<link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png">
<link rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png">
@@ -25,165 +11,138 @@
<title>Gaseous Games</title>
<script type="text/javascript">
var head = document.getElementsByTagName('head')[0];
// update src links to ensure the latest versions are always loaded.
// update links
var headLinks = document.getElementsByTagName('link');
for (var i = 0; i < headLinks.length; i++) {
if (headLinks[i].getAttribute('dat-href') && headLinks[i].rel == "stylesheet") {
var newLink = document.createElement('link');
newLink.rel = "stylesheet";
newLink.href = headLinks[i].getAttribute('dat-href') + '?v=' + AppVersion;
newLink.type = "text/css";
let styleSheets = [
"/styles/select2.min.css",
"/styles/stylevars.css",
"/styles/style.css",
"/styles/notifications.css"
];
headLinks[i].parentElement.removeChild(headLinks[i]);
head.appendChild(newLink);
}
let scriptLinks = [
"/scripts/jquery-3.6.0.min.js",
"/scripts/jquery.lazy.min.js",
"/scripts/jquery.lazy.plugins.min.js",
"/scripts/moment-with-locales.min.js",
"/scripts/select2.min.js",
"/scripts/modals.js",
"/scripts/preferences.js",
"/scripts/account.js",
"/scripts/libraries.js",
"/scripts/notifications.js",
"/scripts/rominfo.js",
"/scripts/uploadrom.js",
"/scripts/filterformating.js",
"/scripts/gamesformating.js",
"/scripts/main.js"
];
let head = document.getElementsByTagName('head')[0];
// placeholder for global userProfile variable
var userProfile;
// update script links
for (let i = 0; i < scriptLinks.length; i++) {
let newScript = document.createElement('script');
newScript.src = scriptLinks[i] + '?v=' + AppVersion;
newScript.type = "text/javascript";
newScript.async = false;
head.appendChild(newScript);
}
var userProfile;
// update stylesheet links
for (let i = 0; i < styleSheets.length; i++) {
let newLink = document.createElement('link');
newLink.rel = "stylesheet";
newLink.href = styleSheets[i] + '?v=' + AppVersion;
newLink.type = "text/css";
head.appendChild(newLink);
}
async function LoadPageContent(page, targetDiv) {
if (targetDiv == undefined || targetDiv == null || targetDiv == '') {
targetDiv = 'content';
}
// load page content
let pageContentResponse = await fetch('/pages/' + page + '.html' + '?v=' + AppVersion);
let pageContentContent = await pageContentResponse.text();
document.getElementById(targetDiv).innerHTML = pageContentContent;
// load page script
let pageScriptLink = '/pages/' + page + '.js';
let script = document.createElement('script');
script.type = 'text/javascript';
script.src = pageScriptLink + '?v=' + AppVersion;
script.async = false;
document.head.appendChild(script);
backgroundImageHandler = new BackgroundImageRotator();
}
</script>
</head>
<body>
<!-- Background Images -->
<div id="bgImages"></div>
<div id="bgImage_Opacity"></div>
<!-- Notifications -->
<div id="notifications_target"></div>
<div id="banner_icon" onclick="window.location.href = '/index.html';">
<img src="/images/logo.png" alt="Gaseous" id="banner_icon_image" />
</div>
<div id="banner_header">
<div id="bannerButtons">
<div id="banner_user" onclick="showMenu();" class="banner_button dropdown dropbtn">
<img src="/images/user.svg" alt="Account" title="Account" id="banner_user_image" class="banner_button_image" style="position: relative; top: 10px; right: 0px; pointer-events: none;" onclick="showMenu();" />
<div id="myDropdown" class="dropdown-content">
<div id="banner_user_roles"></div>
<a href="#" onclick="showDialog('userprofile');">Profile</a>
<a href="#" onclick="userLogoff();">Sign Out</a>
</div>
</div>
<div id="banner_cog" onclick="window.location.href = '/index.html?page=settings';" class="banner_button">
<img src="/images/settings.svg" alt="Settings" title="Settings" id="banner_system_image" class="banner_button_image" />
<span id="banner_system_label">Settings</span>
</div>
<div id="banner_upload" onclick="showDialog('upload');" class="banner_button">
<img src="/images/upload.svg" alt="Upload" title="Upload" id="banner_upload_image" class="banner_button_image" />
<span id="banner_upload_label">Upload</span>
</div>
<!-- Page Banner -->
<div id="banner_target"></div>
<div id="banner_collections" onclick="window.location.href = '/index.html?page=collections';" class="banner_button">
<img src="/images/collections.svg" alt="Collections" title="Collections" id="banner_collections_image" class="banner_button_image" />
<span id="banner_collections_label">Collections</span>
</div>
<div id="banner_library" onclick="window.location.href = '/index.html';" class="banner_button">
<img src="/images/library.svg" alt="Library" title="Library" id="banner_library_image" class="banner_button_image" />
<span id="banner_library_label">Library</span>
</div>
</div>
<div id="banner_header_label" onclick="window.location.href = '/index.html';">Gaseous Games</div>
</div>
<div id="content">
</div>
<!-- The Modal -->
<div id="myModal" class="modal">
<!-- Modal content -->
<div class="modal-content">
<span class="close">&times;</span>
<div><h1 id="modal-heading">Modal heading</h1></div>
<div id="modal-content">Some text in the Modal..</div>
</div>
</div>
<!-- The Modal -->
<div id="myModalSub" class="modal">
<!-- Modal content -->
<div class="modal-content-sub">
<span id="modal-close-sub" class="close">&times;</span>
<div id="modal-content-sub">Some text in the Modal..</div>
</div>
</div>
<!-- Page Content -->
<div id="content"></div>
<script type="text/javascript">
var modalVariables = null;
// start the application
let backgroundImageHandler = undefined;
console.log("Starting Gaseous Games");
console.log("App Version: " + AppVersion);
console.log("First Run Status: " + FirstRunStatus);
switch (FirstRunStatus) {
case 0:
case "0":
// first run - load first run wizard
LoadPageContent('first', 'content');
break;
// redirect if first run status = 0
if (FirstRunStatus == 0) {
window.location.replace("/pages/first.html");
}
default:
// first run - load login page or redirect if user already logged in
// redirect if not logged in
ajaxCall(
'/api/v1.1/Account/Profile/Basic',
'GET',
function(result) {
console.log("User is logged in");
userProfile = result;
fetch('/api/v1.1/Account/Profile/Basic')
.then(async response => {
if (response.ok) {
// user is signed in - start setting up the application
console.log("User is logged in");
userProfile = await response.json();
loadAvatar(userProfile.avatar);
// load page banner
LoadPageContent('banner', 'banner_target');
// hide the upload button if it's not permitted
var uploadButton = document.getElementById('banner_upload');
if (!userProfile.roles.includes("Admin") && !userProfile.roles.includes("Gamer")) {
uploadButton.style.display = 'none';
}
// populate page
var myParam = getQueryString('page', 'string');
// load page content
let pageSelection = getQueryString('page', 'string');
if (!myParam) {
myParam = 'home';
}
$('#content').load('/pages/' + myParam + '.html?v=' + AppVersion);
},
function(error) {
window.location.replace("/pages/login.html");
}
);
/* When the user clicks on the button,
toggle between hiding and showing the dropdown content */
function showMenu() {
document.getElementById("myDropdown").classList.toggle("show");
}
// Close the dropdown menu if the user clicks outside of it
window.onclick = function(event) {
if (!event.target.matches('.dropbtn')) {
var dropdowns = document.getElementsByClassName("dropdown-content");
var i;
for (i = 0; i < dropdowns.length; i++) {
var openDropdown = dropdowns[i];
if (openDropdown.classList.contains('show')) {
openDropdown.classList.remove('show');
}
}
}
}
function userLogoff() {
ajaxCall(
'/api/v1.1/Account/LogOff',
'POST',
function (result) {
location.replace("/index.html");
},
function (error) {
location.replace("/index.html");
}
);
if (!pageSelection) {
pageSelection = GetPreference("DefaultHomePage", 'home');
}
LoadPageContent(pageSelection, 'content');
} else {
// user is not signed in - load login page
LoadPageContent('login');
}
})
.catch((error) => {
console.log(error);
LoadPageContent('login');
});
break;
}
</script>
</body>
</html>
</body>

View File

@@ -0,0 +1,53 @@
<div id="banner_icon" onclick="window.location.href = '/index.html';">
<img src="/images/logo.png" alt="Gaseous" id="banner_icon_image" />
</div>
<div id="banner_header">
<div id="bannerButtons">
<div id="banner_user" class="banner_button dropdown dropbtn">
<div id="banner_user_image_box"></div>
<div id="myDropdown" class="dropdown-content">
<div id="banner_user_profilecard"></div>
<a href="#" id="dropdown-menu-account">Profile and Account</a>
<a href="#" id="dropdown-menu-preferences">Preferences</a>
<div class="dropdown-menu-separator"></div>
<a id="banner_user_logoff" href="#">Sign Out</a>
</div>
</div>
<div id="banner_cog" class="banner_button">
<img src="/images/settings.svg" alt="Settings" title="Settings" id="banner_system_image"
class="banner_button_image" />
<span id="banner_system_label">Settings</span>
</div>
<div id="banner_upload" class="banner_button">
<img src="/images/upload.svg" alt="Upload" title="Upload" id="banner_upload_image"
class="banner_button_image" />
<span id="banner_upload_label">Upload</span>
</div>
<div id="banner_collections" class="banner_button">
<img src="/images/collections.svg" alt="Collections" title="Collections" id="banner_collections_image"
class="banner_button_image" />
<span id="banner_collections_label">Collections</span>
</div>
<div id="banner_library" class="banner_button">
<img src="/images/library.svg" alt="Library" title="Library" id="banner_library_image"
class="banner_button_image" />
<span id="banner_library_label">Library</span>
</div>
<div id="banner_home" class="banner_button">
<img src="/images/home.svg" alt="Home" title="Home" id="banner_home_image" class="banner_button_image" />
<span id="banner_home_label">Home</span>
</div>
</div>
<div id="banner_header_label" onclick="window.location.href = '/index.html';">Gaseous Games</div>
</div>
<!-- page code -->
<script type="text/javascript">
setupBanner();
</script>

View File

@@ -0,0 +1,103 @@
function setupBanner() {
// attach event listeners to the banner elements
let userMenu = document.getElementById("banner_user");
if (userMenu) {
userMenu.addEventListener('click', () => {
document.getElementById("myDropdown").classList.toggle("show");
});
}
let userMenuLogoff = document.getElementById("banner_user_logoff");
if (userMenuLogoff) {
userMenuLogoff.addEventListener('click', () => {
ajaxCall(
'/api/v1.1/Account/LogOff',
'POST',
function (result) {
location.replace("/index.html");
},
function (error) {
location.replace("/index.html");
}
);
});
}
let bannerCog = document.getElementById("banner_cog");
if (bannerCog) {
bannerCog.addEventListener('click', () => {
window.location.href = '/index.html?page=settings';
});
}
let bannerUpload = document.getElementById("banner_upload");
if (bannerUpload) {
bannerUpload.addEventListener('click', () => {
const uploadDialog = new UploadRom();
uploadDialog.open();
});
}
let bannerCollection = document.getElementById("banner_collections");
if (bannerCollection) {
bannerCollection.addEventListener('click', () => {
window.location.href = '/index.html?page=collections';
});
}
let bannerLibrary = document.getElementById("banner_library");
if (bannerLibrary) {
bannerLibrary.addEventListener('click', () => {
window.location.href = '/index.html?page=library';
});
}
let bannerHome = document.getElementById("banner_home");
if (bannerHome) {
bannerHome.addEventListener('click', () => {
window.location.href = '/index.html?page=home';
});
}
// set avatar
let avatarBox = document.getElementById('banner_user_image_box');
let avatar = new Avatar(userProfile.profileId, 30, 30);
avatarBox.style = 'pointer-events: none;';
avatar.setAttribute('style', 'margin-top: 5px; pointer-events: none; width: 30px; height: 30px;');
avatarBox.appendChild(avatar);
// set profile card in drop down
let profileCard = document.getElementById('banner_user_profilecard');
let profileCardContent = new ProfileCard(userProfile.profileId, true);
profileCard.appendChild(profileCardContent);
// hide the upload button if it's not permitted
let uploadButton = document.getElementById('banner_upload');
if (!userProfile.roles.includes("Admin") && !userProfile.roles.includes("Gamer")) {
uploadButton.style.display = 'none';
}
// Close the dropdown menu if the user clicks outside of it
window.onclick = function (event) {
if (!event.target.matches('.dropbtn')) {
let dropdowns = document.getElementsByClassName("dropdown-content");
for (let i = 0; i < dropdowns.length; i++) {
let openDropdown = dropdowns[i];
if (openDropdown.classList.contains('show')) {
openDropdown.classList.remove('show');
}
}
}
}
// event for preferences drop down item
document.getElementById('dropdown-menu-preferences').addEventListener('click', function () {
const prefsDialog = new PreferencesWindow();
prefsDialog.open();
});
// event for account drop down item
document.getElementById('dropdown-menu-account').addEventListener('click', function () {
const accountDialog = new AccountWindow(); accountDialog.open();
});
}
setupBanner();

View File

@@ -1,4 +1,5 @@
<div id="bgImage" style="background-image: url('/images/CollectionsWallpaper.jpg'); background-position: center; background-repeat: no-repeat; background-size: cover; filter: blur(10px); -webkit-filter: blur(10px);">
<div id="bgImage"
style="background-image: url('/images/CollectionsWallpaper.jpg'); background-position: center; background-repeat: no-repeat; background-size: cover; filter: blur(10px); -webkit-filter: blur(10px);">
<div id="bgImage_Opacity"></div>
</div>
@@ -12,88 +13,12 @@
</div>
</div>
<div id="settings_photocredit">
Wallpaper by <a href="https://wallpapercave.com/u/andrea16" class="romlink">andrea16</a> / <a href="https://wallpapercave.com/w/wp5206111" class="romlink">Wallpaper Cave</a>
</div>
<!-- <div id="settings_photocredit">
Wallpaper by <a href="https://wallpapercave.com/u/andrea16" class="romlink">andrea16</a> / <a
href="https://wallpapercave.com/w/wp5206111" class="romlink">Wallpaper Cave</a>
</div> -->
<script type="text/javascript">
var newCollectionButton = document.getElementById('collection_new');
if (userProfile.roles.includes("Admin") || userProfile.roles.includes("Gamer")) {
newCollectionButton.style.display = '';
} else {
newCollectionButton.style.display = 'none';
}
GetCollections();
function GetCollections() {
ajaxCall('/api/v1.1/Collections', 'GET', function (result) {
if (result) {
var targetDiv = document.getElementById('collection_table_location');
targetDiv.innerHTML = '';
var newTable = document.createElement('table');
newTable.id = 'romtable';
newTable.className = 'romtable';
newTable.setAttribute('cellspacing', 0);
newTable.appendChild(createTableRow(true, [ 'Name', 'Description', 'Download Status', 'Size', '' ]));
for (var i = 0; i < result.length; i++) {
var statusText = result[i].buildStatus;
var downloadLink = '';
var packageSize = '-';
var inProgress = false;
switch (result[i].buildStatus) {
case 'NoStatus':
statusText = '-';
break;
case "WaitingForBuild":
statusText = 'Build pending';
inProgress = true;
break;
case "Building":
statusText = 'Building';
inProgress = true;
break;
case "Completed":
statusText = 'Available';
downloadLink = '<a href="/api/v1.1/Collections/' + result[i].id + '/Roms/Zip" class="romlink"><img src="/images/download.svg" class="banner_button_image" alt="Download" title="Download" /></a>';
packageSize = formatBytes(result[i].collectionBuiltSizeBytes);
break;
case "Failed":
statusText = 'Build error';
break;
default:
statusText = result[i].buildStatus;
break;
}
if (inProgress == true) {
setTimeout(GetCollections, 10000);
}
var editButton = '';
var deleteButton = '';
if (userProfile.roles.includes("Admin") || userProfile.roles.includes("Gamer")) {
editButton = '<a href="#" onclick="showDialog(\'collectionedit\', ' + result[i].id + ');" class="romlink"><img src="/images/edit.svg" class="banner_button_image" alt="Edit" title="Edit" /></a>';
deleteButton = '<a href="#" onclick="showSubDialog(\'collectiondelete\', ' + result[i].id + ');" class="romlink"><img src="/images/delete.svg" class="banner_button_image" alt="Delete" title="Delete" /></a>';
}
var newRow = [
result[i].name,
result[i].description,
statusText,
packageSize,
'<div style="text-align: right;">' + downloadLink + editButton + deleteButton + '</div>'
];
newTable.appendChild(createTableRow(false, newRow, 'romrow', 'romcell'));
}
targetDiv.appendChild(newTable);
}
});
}
// set up the page
SetupPage();
</script>

View File

@@ -0,0 +1,85 @@
function SetupPage() {
backgroundImageHandler = new BackgroundImageRotator(['/images/CollectionsWallpaper.jpg']);
var newCollectionButton = document.getElementById('collection_new');
if (userProfile.roles.includes("Admin") || userProfile.roles.includes("Gamer")) {
newCollectionButton.style.display = '';
} else {
newCollectionButton.style.display = 'none';
}
GetCollections();
}
function GetCollections() {
ajaxCall('/api/v1.1/Collections', 'GET', function (result) {
if (result) {
var targetDiv = document.getElementById('collection_table_location');
targetDiv.innerHTML = '';
var newTable = document.createElement('table');
newTable.id = 'romtable';
newTable.className = 'romtable';
newTable.setAttribute('cellspacing', 0);
newTable.appendChild(createTableRow(true, ['Name', 'Description', 'Download Status', 'Size', '']));
for (var i = 0; i < result.length; i++) {
var statusText = result[i].buildStatus;
var downloadLink = '';
var packageSize = '-';
var inProgress = false;
switch (result[i].buildStatus) {
case 'NoStatus':
statusText = '-';
break;
case "WaitingForBuild":
statusText = 'Build pending';
inProgress = true;
break;
case "Building":
statusText = 'Building';
inProgress = true;
break;
case "Completed":
statusText = 'Available';
downloadLink = '<a href="/api/v1.1/Collections/' + result[i].id + '/Roms/Zip" class="romlink"><img src="/images/download.svg" class="banner_button_image" alt="Download" title="Download" /></a>';
packageSize = formatBytes(result[i].collectionBuiltSizeBytes);
break;
case "Failed":
statusText = 'Build error';
break;
default:
statusText = result[i].buildStatus;
break;
}
if (inProgress == true) {
setTimeout(GetCollections, 10000);
}
var editButton = '';
var deleteButton = '';
if (userProfile.roles.includes("Admin") || userProfile.roles.includes("Gamer")) {
editButton = '<a href="#" onclick="showDialog(\'collectionedit\', ' + result[i].id + ');" class="romlink"><img src="/images/edit.svg" class="banner_button_image" alt="Edit" title="Edit" /></a>';
deleteButton = '<a href="#" onclick="showSubDialog(\'collectiondelete\', ' + result[i].id + ');" class="romlink"><img src="/images/delete.svg" class="banner_button_image" alt="Delete" title="Delete" /></a>';
}
var newRow = [
result[i].name,
result[i].description,
statusText,
packageSize,
'<div style="text-align: right;">' + downloadLink + editButton + deleteButton + '</div>'
];
newTable.appendChild(createTableRow(false, newRow, 'romrow', 'romcell'));
}
targetDiv.appendChild(newTable);
}
});
}
SetupPage();

View File

@@ -10,7 +10,8 @@
</td>
</tr>
</table>
<div id="collection_filter_box" style="position: absolute; top: 40px; left: 0px; bottom: 5px; width: 40%; max-width: 40%; overflow-x: scroll;">
<div id="collection_filter_box"
style="position: absolute; top: 40px; left: 0px; bottom: 5px; width: 40%; max-width: 40%; overflow-x: scroll;">
<table style="width: 100%;">
<tr>
<th style="width: 25%;">Platforms</th>
@@ -26,7 +27,8 @@
</tr>
<tr>
<th>Player Perspectives</th>
<td><select id="collection_playerperspectives" style="width: 100%;" multiple="multiple"></select></td>
<td><select id="collection_playerperspectives" style="width: 100%;" multiple="multiple"></select>
</td>
</tr>
<tr>
<th>Themes</th>
@@ -50,17 +52,24 @@
</tr>
<tr>
<th>Maximum size per platform (bytes)</th>
<td><input id="collection_maxplatformsize" type="number" placeholder="0" step="1048576" oninput="DisplayFormattedBytes('collection_maxplatformsize', 'maxplatformsize_label');"><span id="maxplatformsize_label" style="margin-left: 10px;"></span></td>
<td><input id="collection_maxplatformsize" type="number" placeholder="0" step="1048576"
oninput="DisplayFormattedBytes('collection_maxplatformsize', 'maxplatformsize_label');"><span
id="maxplatformsize_label" style="margin-left: 10px;"></span></td>
</tr>
<tr>
<th>Maximum collection size (bytes)</th>
<td><input id="collection_maxcollectionsize" type="number" placeholder="0" step="1048576" oninput="DisplayFormattedBytes('collection_maxcollectionsize', 'maxcollectionsize_label');"><span id="maxcollectionsize_label" style="margin-left: 10px;"></span></td></td>
<td><input id="collection_maxcollectionsize" type="number" placeholder="0" step="1048576"
oninput="DisplayFormattedBytes('collection_maxcollectionsize', 'maxcollectionsize_label');"><span
id="maxcollectionsize_label" style="margin-left: 10px;"></span></td>
</td>
</tr>
<tr>
<th>Directory Layout</th>
<td>
<select id="collection_directorylayout" style="width: 100%;" data-minimum-results-for-search="Infinity" onchange="DisplayDirectoryLabel();">
<option id="collection_directorylayout_gaseous" selected="selected" value="Gaseous">Standard</option>
<select id="collection_directorylayout" style="width: 100%;"
data-minimum-results-for-search="Infinity" onchange="DisplayDirectoryLabel();">
<option id="collection_directorylayout_gaseous" selected="selected" value="Gaseous">Standard
</option>
<option id="collection_directorylayout_retropie" value="RetroPie">RetroPie</option>
</select>
</td>
@@ -74,7 +83,8 @@
<p>Standard layout: /&lt;IGDB Platform Slug&gt;/&lt;IGDB Game Slug&gt;/Game ROMs</p>
<p>Example: /genesis-slash-megadrive/sonic-the-hedgehog/Sonic the Hedgehog.smd</p>
</span>
<span id="collection_directorylayout_retropie_label" style="display: none;" name="collection_directorylayout_label">
<span id="collection_directorylayout_retropie_label" style="display: none;"
name="collection_directorylayout_label">
<p>RetroPie layout: /roms/&lt;RetroPie Platform Label&gt;/Game ROMs</p>
<p>Example: /roms/megadrive/Sonic the Hedgehog.smd</p>
</span>
@@ -85,7 +95,8 @@
Include BIOS files (if available)
</th>
<td>
<select id="collection_includebios" style="width: 100%;" data-minimum-results-for-search="Infinity">
<select id="collection_includebios" style="width: 100%;"
data-minimum-results-for-search="Infinity">
<option id="collection_includebios_yes" selected="selected" value="true">Yes</option>
<option id="collection_includebios_no" value="false">No</option>
</select>
@@ -118,15 +129,18 @@
</td>
</tr>
</table>
<div id="collectionedit_previewbox" style="position: absolute; top: 40px; right: 0px; bottom: 60px; width: 60%; overflow-x: scroll;">
<div id="collectionedit_previewbox"
style="position: absolute; top: 40px; right: 0px; bottom: 60px; width: 60%; overflow-x: scroll;">
<div id="collectionedit_previewbox_content" style="margin: 5px;">
</div>
</div>
<div id="collectionedit_previewbox_size" style="position: absolute; right: 10px; bottom: 30px; width: 60%; height: 20px; text-align: right;">
<div id="collectionedit_previewbox_size"
style="position: absolute; right: 10px; bottom: 30px; width: 60%; height: 20px; text-align: right;">
</div>
<div id="collectionedit_previewbox_controls" style="position: absolute; right: 10px; bottom: 0px; width: 60%; height: 25px; text-align: right;">
<div id="collectionedit_previewbox_controls"
style="position: absolute; right: 10px; bottom: 0px; width: 60%; height: 25px; text-align: right;">
<button id="collectionedit_preview" onclick="GetPreview();">Preview</button>
<button id="collectionedit_cancel" onclick="closeDialog();">Cancel</button>
<button id="collectionedit_ok" onclick="SaveCollection();">Ok</button>
@@ -151,9 +165,9 @@
url: '/api/v1.1/Filter',
processResults: function (data) {
var filter = data['platforms'];
var arr = [];
for (var i = 0; i < filter.length; i++) {
arr.push({
id: filter[i].id,
@@ -272,7 +286,7 @@
ajaxCall(
'/api/v1.1/Collections/' + modalVariables,
'GET',
function(result) {
function (result) {
if (result.name) { document.getElementById('collection_name').value = result.name; }
if (result.description) { document.getElementById('collection_description').value = result.description; }
if (result.minimumRating != -1) { document.getElementById('collection_userrating_min').value = result.minimumRating; }
@@ -358,10 +372,10 @@
ajaxCall(
'/api/v1.1/Collections/' + modalVariables,
'PATCH',
function(result) {
function (result) {
location.reload();
},
function(error) {
function (error) {
alert(error);
},
JSON.stringify(item)
@@ -371,10 +385,10 @@
ajaxCall(
'/api/v1.1/Collections',
'POST',
function(result) {
function (result) {
location.reload();
},
function(error) {
function (error) {
alert(error);
},
JSON.stringify(item)
@@ -440,10 +454,10 @@
ajaxCall(
'/api/v1.1/Collections/Preview',
'POST',
function(result) {
function (result) {
DisplayPreview(result, 'collectionedit_previewbox_content');
},
function(error) {
function (error) {
console.log(JSON.stringify(error));
},
JSON.stringify(item)
@@ -531,12 +545,12 @@
var gameItemRow = document.createElement('tr');
gameItemRow.className = bgalt;
// game title
var gameTitleCell = document.createElement('th');
gameTitleCell.setAttribute('colspan', 2);
gameTitleCell.className = 'collections_preview_gametitlecell';
// game always include popup
var gameTitleInclusion = document.createElement('select');
gameTitleInclusion.id = 'collections_preview_always_' + platformItem.id + '_' + gameItem.id;
@@ -584,15 +598,15 @@
// game cover
var gameDetailRow = document.createElement('tr');
gameDetailRow.className = bgalt;
var gameCoverCell = document.createElement('td');
gameCoverCell.className = 'collections_preview_gamecovercell';
var gameImage = document.createElement('img');
gameImage.className = 'game_tile_image game_tile_image_small lazy';
gameImage.src = '/images/unknowngame.png';
if (gameItem.cover) {
gameImage.setAttribute('data-src', '/api/v1.1/Games/' + gameItem.id + '/cover/image/cover_small/' + gameItem.coverItem.imageId + '.jpg');
gameImage.setAttribute('data-src', '/api/v1.1/Games/' + gameItem.id + '/cover/' + gameItem.cover.id + '/image/cover_small/' + gameItem.coverItem.imageId + '.jpg');
} else {
gameImage.className = 'game_tile_image game_tile_image_small unknown';
}
@@ -603,7 +617,7 @@
// game detail
var gameDetailCell = document.createElement('td');
gameDetailCell.className = 'collections_preview_gamedetailcell';
// loop roms
for (var r = 0; r < gameItem.roms.length; r++) {
var romItem = gameItem.roms[r];
@@ -658,7 +672,7 @@
var labelToDisplay = '';
if (directoryLayoutMode) {
switch(directoryLayoutMode) {
switch (directoryLayoutMode) {
case "Gaseous":
// standard mode
labelToDisplay = 'collection_directorylayout_gaseous_label';
@@ -669,7 +683,7 @@
break;
}
document.getElementById(labelToDisplay).style.display = '';
}
}

View File

@@ -1,159 +0,0 @@
<div id="saved_states">
</div>
<script text="text/javascript">
document.getElementById('modal-heading').innerHTML = "Load saved state";
console.log(modalVariables);
var statesUrl = '/api/v1.1/StateManager/' + modalVariables.romId + '?IsMediaGroup=' + modalVariables.IsMediaGroup;
console.log(statesUrl);
function LoadStates() {
ajaxCall(
statesUrl,
'GET',
function(result) {
var statesBox = document.getElementById('saved_states');
statesBox.innerHTML = '';
for (var i = 0; i < result.length; i++) {
var stateBox = document.createElement('div');
stateBox.id = 'stateBox_' + result[i].id;
stateBox.className = 'saved_state_box';
// screenshot panel
var stateImageBox = document.createElement('div');
stateImageBox.id = 'stateImageBox_' + result[i].id;
stateImageBox.className = 'saved_state_image_box';
if (result[i].hasScreenshot == true) {
var stateImage = document.createElement('img');
stateImage.className = 'saved_state_image_image';
stateImage.src = '/api/v1.1/StateManager/' + modalVariables.romId + '/' + result[i].id + '/Screenshot/image.png?IsMediaGroup=' + modalVariables.IsMediaGroup;
stateImageBox.appendChild(stateImage);
}
stateBox.appendChild(stateImageBox);
// main panel
var stateMainPanel = document.createElement('div');
stateMainPanel.id = 'stateMainPanel_' + result[i].id;
stateMainPanel.className = 'saved_state_main_box';
var stateName = document.createElement('input');
stateName.id = 'stateName_' + result[i].id;
stateName.type = 'text';
stateName.className = 'saved_state_name';
stateName.setAttribute('onblur', 'UpdateStateSave(' + result[i].id + ', ' + modalVariables.IsMediaGroup + ');');
if (result[i].name) {
stateName.value = result[i].name;
} else {
stateName.setAttribute('placeholder', "Untitled");
}
stateMainPanel.appendChild(stateName);
var stateTime = document.createElement('div');
stateTime.id = 'stateTime_' + result[i].id;
stateTime.className = 'saved_state_date';
stateTime.innerHTML = moment(result[i].saveTime).format("YYYY-MM-DD h:mm:ss a");
stateMainPanel.appendChild(stateTime);
var stateControls = document.createElement('div');
stateControls.id = 'stateControls_' + result[i].id;
stateControls.className = 'saved_state_controls';
var stateControlsLaunch= document.createElement('span');
stateControlsLaunch.id = 'stateControlsLaunch_' + result[i].id;
stateControlsLaunch.className = 'romstart';
var emulatorTarget = '/index.html?page=emulator&engine=@engine&core=@core&platformid=@platformid&gameid=@gameid&romid=@romid&mediagroup=@mediagroup&rompath=@rompath&stateid=' + result[i].id;
switch (getQueryString('page', 'string')) {
case 'emulator':
var mediagroupint = 0;
if (modalVariables.IsMediaGroup == true) {
mediagroupint = 1;
}
emulatorTarget = emulatorTarget.replaceAll('@engine', getQueryString('engine', 'string'));
emulatorTarget = emulatorTarget.replaceAll('@core', getQueryString('core', 'string'));
emulatorTarget = emulatorTarget.replaceAll('@platformid', getQueryString('platformid', 'string'));
emulatorTarget = emulatorTarget.replaceAll('@gameid', getQueryString('gameid', 'string'));
emulatorTarget = emulatorTarget.replaceAll('@romid', getQueryString('romid', 'string'));
emulatorTarget = emulatorTarget.replaceAll('@mediagroup', mediagroupint);
emulatorTarget = emulatorTarget.replaceAll('@rompath', getQueryString('rompath', 'string'));
stateControlsLaunch.setAttribute("onclick", 'window.location.replace("' + emulatorTarget + '")');
break;
case 'game':
console.log(modalVariables);
emulatorTarget = emulatorTarget.replaceAll('@engine', modalVariables.engine);
emulatorTarget = emulatorTarget.replaceAll('@core', modalVariables.core);
emulatorTarget = emulatorTarget.replaceAll('@platformid', modalVariables.platformid);
emulatorTarget = emulatorTarget.replaceAll('@gameid', modalVariables.gameid);
emulatorTarget = emulatorTarget.replaceAll('@romid', modalVariables.romId);
emulatorTarget = emulatorTarget.replaceAll('@mediagroup', modalVariables.mediagroup);
emulatorTarget = emulatorTarget.replaceAll('@rompath', modalVariables.rompath);
stateControlsLaunch.setAttribute("onclick", 'window.location.href = "' + emulatorTarget + '"');
break;
}
stateControlsLaunch.innerHTML = 'Launch';
stateControlsLaunch.style.float = 'right';
stateControls.appendChild(stateControlsLaunch);
var stateControlsDownload = document.createElement('a');
stateControlsDownload.id = 'stateControlsDownload_' + result[i].id;
stateControlsDownload.className = 'saved_state_buttonlink';
stateControlsDownload.href = '/api/v1.1/StateManager/' + modalVariables.romId + '/' + result[i].id + '/State/savestate.state?IsMediaGroup=' + modalVariables.IsMediaGroup;
stateControlsDownload.innerHTML = '<img src="/images/download.svg" class="banner_button_image" alt="Download" title="Download" />';
stateControls.appendChild(stateControlsDownload);
var stateControlsDelete = document.createElement('span');
stateControlsDelete.id = 'stateControlsDelete_' + result[i].id;
stateControlsDelete.className = 'saved_state_buttonlink';
stateControlsDelete.setAttribute('onclick', 'DeleteStateSave(' + result[i].id + ', ' + modalVariables.IsMediaGroup + ');');
stateControlsDelete.innerHTML = '<img src="/images/delete.svg" class="banner_button_image" alt="Delete" title="Delete" />';
stateControls.appendChild(stateControlsDelete);
stateMainPanel.appendChild(stateControls);
stateBox.appendChild(stateMainPanel);
statesBox.appendChild(stateBox);
}
}
);
}
LoadStates();
function DeleteStateSave(StateId, IsMediaGroup) {
ajaxCall(
'/api/v1.1/StateManager/' + modalVariables.romId + '/' + StateId + '?IsMediaGroup=' + IsMediaGroup,
'DELETE',
function(success) {
LoadStates();
},
function (error) {
LoadStates();
}
);
}
function UpdateStateSave(StateId, IsMediaGroup) {
var stateName = document.getElementById('stateName_' + StateId);
var model = {
"name": stateName.value
};
ajaxCall(
'/api/v1.1/StateManager/' + modalVariables.romId + '/' + StateId + '?IsMediaGroup=' + IsMediaGroup,
'PUT',
function(success) {
LoadStates();
},
function (error) {
LoadStates();
},
JSON.stringify(model)
);
}
</script>

View File

@@ -1,27 +0,0 @@
<p>Are you sure you want to delete this library?</p>
<p><strong>Warning:</strong> This cannot be undone!</p>
<div style="width: 100%; text-align: center;">
<div style="display: inline-block; margin-right: 20px;">
<button class="redbutton" value="Delete" onclick="deleteLibrary();">Delete</button>
</div>
<div style="display: inline-block; margin-left: 20px;">
<button value="Cancel" onclick="closeSubDialog();">Cancel</button>
</div>
</div>
<script type="text/javascript">
function deleteLibrary() {
ajaxCall(
'/api/v1.1/Library/' + subModalVariables,
'DELETE',
function (result) {
drawLibrary();
closeSubDialog();
},
function (error) {
drawLibrary();
closeSubDialog();
}
);
}
</script>

View File

@@ -1,87 +0,0 @@
<table style="width: 98%; margin-top: 15px; margin-bottom: 15px;">
<tr>
<th style="width: 20%;">Name</th>
<td style="width: 80%;"><input type="text" id="newlibrary_name" style="width: 98%;" /></td>
</tr>
<tr>
<th>Default Platform</th>
<td><select id="newlibrary_defaultplatform" style="width: 100%;"></select></td>
</tr>
<tr>
<th>Path</th>
<td><input type="text" id="newlibrary_path" style="width: 98%;" /></td>
</tr>
</table>
<div style="width: 100%; text-align: right; margin-top: 160px;">
<div style="display: inline-block; margin-right: 20px;">
<button value="OK" onclick="newLibrary();">OK</button>
</div>
<div style="display: inline-block;">
<button value="Cancel" onclick="closeDialog();">Cancel</button>
</div>
</div>
<script type="text/javascript">
document.getElementById('modal-heading').innerHTML = "New Library";
$('#newlibrary_defaultplatform').select2({
minimumInputLength: 3,
ajax: {
url: '/api/v1.1/Search/Platform',
data: function (params) {
var query = {
SearchString: params.term
}
// Query parameters will be ?SearchString=[term]
return query;
},
processResults: function (data) {
var arr = [];
arr.push({
id: 0,
text: 'Any'
});
for (var i = 0; i < data.length; i++) {
arr.push({
id: data[i].id,
text: data[i].name
});
}
return {
results: arr
};
}
}
});
document.getElementById('newlibrary_defaultplatform').innerHTML = "<option value='" + 0 + "' selected='selected'>Any</option>";
function newLibrary() {
var libName = document.getElementById('newlibrary_name').value;
var libPlatform = $('#newlibrary_defaultplatform').select2('data');
var libPath = document.getElementById('newlibrary_path').value;
if (libName.length == 0) {
alert("A library name must be provided.")
} else if (libPath.length == 0) {
alert("A path must be provided.");
} else {
ajaxCall(
'/api/v1.1/Library?Name=' + encodeURIComponent(libName) + '&DefaultPlatformId=' + libPlatform[0].id + '&Path=' + encodeURIComponent(libPath),
'POST',
function (result) {
drawLibrary();
closeDialog();
},
function (error) {
alert('An error occurred while creating the library:\n\n' + JSON.stringify(error.responseText));
}
);
}
}
</script>

View File

@@ -1,29 +0,0 @@
<p>Are you sure you want to delete this media group and all associated saved states?</p>
<p><strong>Warning:</strong> This cannot be undone!</p>
<div style="width: 100%; text-align: center;">
<div style="display: inline-block; margin-right: 20px;">
<button class="redbutton" value="Delete" onclick="deleteCollection();">Delete</button>
</div>
<div style="display: inline-block; margin-left: 20px;">
<button value="Cancel" onclick="closeSubDialog();">Cancel</button>
</div>
</div>
<script type="text/javascript">
function deleteCollection() {
ajaxCall(
'/api/v1.1/Games/' + gameData.id + '/romgroup/' + subModalVariables,
'DELETE',
function (result) {
loadRoms();
loadMediaGroups();
closeSubDialog();
},
function (error) {
loadRoms();
loadMediaGroups();
closeSubDialog();
}
);
}
</script>

View File

@@ -1,391 +0,0 @@
<div style="position: absolute; top: 60px; left: 10px; right: 10px; bottom: 40px; overflow-x: scroll;">
<div style="width: 985px;">
<h3>Title Matching</h3>
<table style="width: 100%;">
<tr>
<td style="width: 25%; vertical-align: top;">
<h4>Alternative Names</h4>
</td>
<td>
<select id="mapping_edit_alternativenames" multiple="multiple" style="width: 100%;"></select>
</td>
</tr>
<tr>
<td style="width: 25%; vertical-align: top;">
<h4>Supported File Extensions</h4>
</td>
<td>
<select id="mapping_edit_supportedfileextensions" multiple="multiple" style="width: 100%;"></select>
</td>
</tr>
</table>
<h3>Collections</h3>
<table style="width: 100%;">
<tr>
<td style="width: 25%;">
<h4>Standard Directory Naming</h4>
</td>
<td style="text-align: right;">
<input id="mapping_edit_igdbslug" readonly="readonly" type="text" style="width: 98%;"/>
</td>
</tr>
<tr>
<td colspan="2"><strong>Note</strong>: Standard directory naming uses the IGDB slug for the platform and is not editable.</td>
</tr>
<tr>
<td>
<h4>RetroPie Directory Naming</h4>
</td>
<td style="text-align: right;">
<input id="mapping_edit_retropie" type="text" style="width: 98%;"/>
</td>
</tr>
</table>
<h3>Web Emulator</h3>
<table style="width: 100%;">
<tr>
<td style="width: 25%;">
<h4>Web Emulator</h4>
</td>
<td>
<input id="mapping_edit_enablewebemulator" type="checkbox"><label for="mapping_edit_enablewebemulator" style="margin-left: 5px;">Enabled</label>
</td>
</tr>
<tr name="mapping_edit_webemulator">
<td style="width: 25%;">
<h4>Engine</h4>
</td>
<td>
<select id="mapping_edit_webemulatorengine" data-minimum-results-for-search="Infinity" style="width: 100%;">
</select>
</td>
</tr>
<tr name="mapping_edit_webemulator">
<td style="width: 25%;">
<h4>Core</h4>
</td>
<td>
<select id="mapping_edit_webemulatorcore" data-minimum-results-for-search="Infinity" style="width: 100%;">
</select>
</td>
</tr>
<tr name="mapping_edit_webemulator">
<td style="width: 25%;">
</td>
<td id="mapping_edit_webemulatorhelp">
</td>
</tr>
</table>
<h3>BIOS/Firmware</h3>
<div id="mapping_edit_bios"></div>
</div>
</div>
<div style="position: absolute; height: 35px; left: 10px; right: 10px; bottom: 0px; text-align: right;">
<button value="Ok" onclick="SubmitMappingItem();">Ok</button>
</div>
<script type="text/javascript">
var modalContent = document.getElementsByClassName('modal-content');
if (!modalContent[0].classList.contains('collections_modal')) {
modalContent[0].classList.add('collections_modal');
}
var availableWebEmulators = [];
DisplayWebEmulatorContent(false);
ajaxCall(
'/api/v1.1/PlatformMaps/' + modalVariables,
'GET',
function (result) {
// set heading
document.getElementById('modal-heading').innerHTML = result.igdbName;
// populate page
$('#mapping_edit_alternativenames').select2 ({
tags: true,
tokenSeparators: [',']
});
AddTokensFromList('#mapping_edit_alternativenames', result.alternateNames);
$('#mapping_edit_supportedfileextensions').select2 ({
tags: true,
tokenSeparators: [','],
createTag: function (params) {
if (params.term.indexOf('.') === -1) {
// Return null to disable tag creation
return null;
}
return {
id: params.term.toUpperCase(),
text: params.term.toUpperCase()
}
}
});
AddTokensFromList('#mapping_edit_supportedfileextensions', result.extensions.supportedFileExtensions);
document.getElementById('mapping_edit_igdbslug').value = result.igdbSlug;
document.getElementById('mapping_edit_retropie').value = result.retroPieDirectoryName;
// set up web emulator drop downs
$('#mapping_edit_webemulatorengine').select2();
$('#mapping_edit_webemulatorcore').select2();
// start populating drop downs
if (result.webEmulator) {
if (result.webEmulator.availableWebEmulators) {
if (result.webEmulator.availableWebEmulators.length > 0) {
availableWebEmulators = result.webEmulator.availableWebEmulators;
var offOption = new Option("-", "", false, false);
$('#mapping_edit_webemulatorengine').append(offOption).trigger('change');
for (var e = 0; e < result.webEmulator.availableWebEmulators.length; e++) {
var newOption = new Option(result.webEmulator.availableWebEmulators[e].emulatorType, result.webEmulator.availableWebEmulators[e].emulatorType, false, false);
$('#mapping_edit_webemulatorengine').append(newOption).trigger('change');
}
$('#mapping_edit_webemulatorengine').val(result.webEmulator.type);
$('#mapping_edit_webemulatorengine').trigger('change');
// select cores
RenderWebEmulatorCores(result.webEmulator.core);
if (result.webEmulator.type.length > 0) {
document.getElementById('mapping_edit_enablewebemulator').checked = true;
}
DisplayWebEmulatorHelp(result.webEmulator.type);
$('#mapping_edit_webemulatorengine').on('change', function(e) {
RenderWebEmulatorCores();
});
if (result.webEmulator.type.length > 0) {
DisplayWebEmulatorContent(true);
} else {
DisplayWebEmulatorContent(false);
}
} else {
// no emulators available
DisplayWebEmulatorContent(false);
}
} else {
// no emulators available
DisplayWebEmulatorContent(false);
}
} else {
// no emulators available
DisplayWebEmulatorContent(false);
}
var biosTableHeaders = [
{
"name": "filename",
"label": "Filename"
},
{
"name": "description",
"label": "Description"
},
{
"name": "hash",
"label": "MD5 Hash"
}
];
document.getElementById('mapping_edit_bios').appendChild(
CreateEditableTable(
'bios',
biosTableHeaders
)
);
LoadEditableTableData('bios', biosTableHeaders, result.bios);
}
);
function RenderWebEmulatorCores(preSelectCore) {
var selectedEngine = document.getElementById('mapping_edit_webemulatorengine').value;
console.log("Engine: " + selectedEngine);
console.log("Preselect: " + preSelectCore);
console.log(JSON.stringify(availableWebEmulators));
$('#mapping_edit_webemulatorcore').empty().trigger("change");
// get cores for currently selected emulator
if (availableWebEmulators && (selectedEngine != undefined && selectedEngine != "")) {
if (availableWebEmulators.length > 0) {
var emuFound = false;
for (var e = 0; e < availableWebEmulators.length; e++) {
if (availableWebEmulators[e].emulatorType == selectedEngine) {
emuFound = true;
for (var c = 0; c < availableWebEmulators[e].availableWebEmulatorCores.length; c++) {
var coreName = availableWebEmulators[e].availableWebEmulatorCores[c].core;
if (availableWebEmulators[e].availableWebEmulatorCores[c].alternateCoreName) {
coreName += " (Maps to core: " + availableWebEmulators[e].availableWebEmulatorCores[c].alternateCoreName + ")";
}
if (availableWebEmulators[e].availableWebEmulatorCores[c].default == true) {
coreName += " (Default)";
}
console.log(coreName);
var newOption;
if (availableWebEmulators[e].availableWebEmulatorCores[c].core == preSelectCore) {
newOption = new Option(coreName, availableWebEmulators[e].availableWebEmulatorCores[c].core, true, true);
} else {
newOption = new Option(coreName, availableWebEmulators[e].availableWebEmulatorCores[c].core, false, false);
}
$('#mapping_edit_webemulatorcore').append(newOption).trigger('change');
}
}
}
if (emuFound == false) {
var newOption = new Option("-", "", true, true);
$('#mapping_edit_webemulatorcore').append(newOption).trigger('change');
}
} else {
var newOption = new Option("-", "", true, true);
$('#mapping_edit_webemulatorcore').append(newOption).trigger('change');
}
} else {
var newOption = new Option("-", "", true, true);
$('#mapping_edit_webemulatorcore').append(newOption).trigger('change');
}
}
function AddTokensFromList(selectObj, tagList) {
for (var i = 0; i < tagList.length; i++) {
var data = {
id: tagList[i],
text: tagList[i]
}
var newOption = new Option(data.text, data.id, true, true);
$(selectObj).append(newOption).trigger('change');
}
}
function SubmitMappingItem() {
var alternateNames = $('#mapping_edit_alternativenames').val();
var knownExtensions = $('#mapping_edit_supportedfileextensions').val();
var extensions = {
"IGDBId": modalVariables,
"supportedFileExtensions": knownExtensions,
"uniqueFileExtensions": knownExtensions
};
var emulator = null;
if (document.getElementById('mapping_edit_enablewebemulator').checked == true) {
emulator = {
"type": document.getElementById('mapping_edit_webemulatorengine').value,
"core": document.getElementById('mapping_edit_webemulatorcore').value
};
}
var bios = [];
var biosTable = document.getElementById('EditableTable_bios');
if (biosTable) {
// get rows
for (var i = 0; i < biosTable.childNodes.length; i++) {
var rowObj = biosTable.childNodes[i];
var biosObj = {};
var addBiosObj = false;
// get cells
for (var v = 0; v < rowObj.childNodes.length; v++) {
var cell = rowObj.childNodes[v];
if (cell.tagName.toLowerCase() != 'th') {
// get input boxes
for (var c = 0; c < cell.childNodes.length; c++) {
var element = cell.childNodes[c];
if (element) {
if (element.getAttribute('data-cell')) {
var nodeName = element.getAttribute('data-cell');
biosObj[nodeName] = element.value;
addBiosObj = true;
break;
}
}
}
}
}
if (addBiosObj == true) {
bios.push(biosObj);
}
}
}
var item = {
"igdbId": Number(modalVariables),
"igdbName": document.getElementById('modal-heading').innerHTML,
"igdbSlug": document.getElementById('mapping_edit_igdbslug').value,
"alternateNames": alternateNames,
"extensions": extensions,
"retroPieDirectoryName": document.getElementById('mapping_edit_retropie').value,
"webEmulator": emulator,
"bios": bios
};
console.log(JSON.stringify(item));
ajaxCall(
'/api/v1.1/PlatformMaps/' + modalVariables,
'PATCH',
function (result) {
loadPlatformMapping();
closeDialog();
},
function (error) {
console.error(JSON.stringify(error));
},
JSON.stringify(item)
);
}
$('#mapping_edit_webemulatorengine').on('select2:select', function (e) {
DisplayWebEmulatorHelp(e.params.data.id);
});
function DisplayWebEmulatorHelp(Emulator) {
var helpCell = document.getElementById('mapping_edit_webemulatorhelp');
switch (Emulator) {
case 'EmulatorJS':
helpCell.innerHTML = '<img src="/images/help.svg" class="banner_button_image banner_button_image_smaller" alt="Help" title="Help" /> See <a href="https://emulatorjs.org/docs4devs/Cores.html" target="_blank" class="romlink">https://emulatorjs.org/docs4devs/Cores.html</a> for more information regarding EmulatorJS cores.';
break;
default:
helpCell.innerHTML = '';
break;
}
}
$('#mapping_edit_enablewebemulator').change(function() {
DisplayWebEmulatorContent(this.checked);
});
function DisplayWebEmulatorContent(showContent) {
console.log(showContent);
var webEmulatorRows = document.getElementsByName('mapping_edit_webemulator');
for (var i = 0; i < webEmulatorRows.length; i++) {
if (showContent == true) {
webEmulatorRows[i].style.display = '';
} else {
webEmulatorRows[i].style.display = 'none';
}
}
}
</script>

View File

@@ -1,18 +0,0 @@
<p>Are you sure you want to delete this ROM and all associated saved states?</p>
<p><strong>Warning:</strong> This cannot be undone!</p>
<div style="width: 100%; text-align: center;">
<div style="display: inline-block; margin-right: 20px;">
<button class="redbutton" value="Delete" onclick="deleteRom();">Delete</button>
</div>
<div style="display: inline-block; margin-left: 20px;">
<button value="Cancel" onclick="closeSubDialog();">Cancel</button>
</div>
</div>
<script type="text/javascript">
function deleteRom() {
ajaxCall('/api/v1.1/Games/' + gameId + '/roms/' + modalVariables, 'DELETE', function (result) {
window.location.reload();
});
}
</script>

View File

@@ -1,396 +0,0 @@
<div id="properties_toc">
<div id="properties_toc_general" name="properties_toc_item" onclick="SelectTab('general');">General</div>
<div id="properties_toc_archive" name="properties_toc_item" onclick="SelectTab('archive');" style="display: none;">
Archive Contents</div>
<div id="properties_toc_attributes" name="properties_toc_item" onclick="SelectTab('attributes');"
style="display: none;">Attributes</div>
<div id="properties_toc_match" name="properties_toc_item" onclick="SelectTab('match');">Title Match</div>
<!--<div id="properties_toc_manage" name="properties_toc_item" onclick="SelectTab('manage');">Manage</div>-->
</div>
<div id="properties_bodypanel">
<div id="properties_bodypanel_general" name="properties_tab" style="display: none;">
<table cellspacing="0" style="width: 100%;">
<tr>
<th>Library</th>
<td id="rominfo_library"></td>
</tr>
<tr>
<th>Platform</th>
<td id="rominfo_platform"></td>
</tr>
<tr>
<th>Size</th>
<td id="rominfo_size"></td>
</tr>
<tr>
<th>ROM Type</th>
<td id="rominfo_type"></td>
</tr>
<tr>
<th>Media Type</th>
<td id="rominfo_mediatype"></td>
</tr>
<tr>
<th>Media Label</th>
<td id="rominfo_medialabel"></td>
</tr>
<tr>
<th>MD5</th>
<td id="rominfo_md5"></td>
</tr>
<tr>
<th>SHA1</th>
<td id="rominfo_sha1"></td>
</tr>
<tr>
<th>Signature Matched From</th>
<td id="rominfo_signaturematch"></td>
</tr>
<tr>
<th>Signature Game Title</th>
<td id="rominfo_signaturetitle"></td>
</tr>
<tr>
<td colspan="2" style="text-align: right;"><button id="romDelete" class="redbutton">Delete</button></td>
</tr>
</table>
</div>
<div id="properties_bodypanel_archive" name="properties_tab" style="display: none;">
<div id="properties_bodypanel_archive_content" style="height: 315px; overflow-x: scroll;"></div>
</div>
<div id="properties_bodypanel_attributes" name="properties_tab" style="display: none;">
</div>
<div id="properties_bodypanel_match" name="properties_tab" style="display: none;">
<table style="width: 100%;">
<tr>
<th colspan="2">Fix Match</th>
</tr>
<tr>
<th style="width: 25%;">Platform</th>
<td style="width: 75%;">
<select id="properties_fixplatform" style="width: 100%;"></select>
</td>
</tr>
<tr>
<th style="width: 25%;">Game</th>
<td style="width: 75%;"><select id="properties_fixgame" style="width: 100%;"></select></td>
</tr>
<tr>
<td colspan="2" style="text-align: right;"><button id="properties_fixclear" value="Clear Match"
onclick="ClearFixedGame();">Clear Match</button><button id="properties_fixsave"
value="Save Match" onclick="SaveFixedGame();">Save Match</button></td>
</tr>
</table>
</div>
<div id="properties_bodypanel_manage" name="properties_tab" style="display: none;">
</div>
</div>
<script type="text/javascript">
document.getElementById('modal-heading').innerHTML = "Properties";
var gameId = getQueryString('id', 'int');
var romData;
function getRomType(typeId) {
switch (typeId) {
case 1:
return "Optical media";
break;
case 2:
return "Magnetic media";
break;
case 3:
return "Individual files";
break;
case 4:
return "Individual pars";
break;
case 5:
return "Tape based media";
break;
case 6:
return "Side of the media";
break;
case 0:
default:
return "Media type is unknown";
break;
}
}
ajaxCall('/api/v1.1/Games/' + gameId + '/roms/' + modalVariables, 'GET', function (result) {
romData = result;
document.getElementById('modal-heading').innerHTML = result.name;
document.getElementById('rominfo_library').innerHTML = result.library.name;
document.getElementById('rominfo_platform').innerHTML = result.platform;
document.getElementById('rominfo_size').innerHTML = formatBytes(result.size, 2);
document.getElementById('rominfo_type').innerHTML = getRomType(result.romType);
document.getElementById('rominfo_mediatype').innerHTML = result.romTypeMedia;
document.getElementById('rominfo_medialabel').innerHTML = result.mediaLabel;
document.getElementById('rominfo_md5').innerHTML = result.md5;
document.getElementById('rominfo_sha1').innerHTML = result.sha1;
document.getElementById('rominfo_signaturematch').innerHTML = result.signatureSource;
document.getElementById('rominfo_signaturetitle').innerHTML = result.signatureSourceGameTitle;
document.getElementById('properties_fixplatform').innerHTML = "<option value='" + result.platformId + "' selected='selected'>" + result.platform + "</option>";
document.getElementById('properties_fixgame').innerHTML = "<option value='" + gameData.id + "' selected='selected'>" + gameData.name + "</option>";
if (result.library.isDefaultLibrary == false) {
document.getElementById('romDelete').style.display = 'none';
}
if (result.attributes) {
document.getElementById('properties_bodypanel_attributes').appendChild(BuildAttributesTable(result.attributes, result.source));
document.getElementById('properties_bodypanel_archive_content').appendChild(BuildArchiveTable(result.attributes, result.source));
}
});
function SelectTab(TabName) {
var tabs = document.getElementsByName('properties_tab');
for (var i = 0; i < tabs.length; i++) {
if ((tabs[i].id) == ("properties_bodypanel_" + TabName)) {
tabs[i].style.display = '';
} else {
tabs[i].style.display = 'none';
}
}
var tocs = document.getElementsByName('properties_toc_item');
for (var i = 0; i < tocs.length; i++) {
if ((tocs[i].id) == ("properties_toc_" + TabName)) {
tocs[i].className = "properties_toc_item_selected";
} else {
tocs[i].className = '';
}
}
}
$('#properties_fixplatform').select2({
minimumInputLength: 3,
ajax: {
url: '/api/v1.1/Search/Platform',
data: function (params) {
var query = {
SearchString: params.term
}
// Query parameters will be ?SearchString=[term]
return query;
},
processResults: function (data) {
var arr = [];
for (var i = 0; i < data.length; i++) {
arr.push({
id: data[i].id,
text: data[i].name
});
}
return {
results: arr
};
}
}
});
$('#properties_fixplatform').on('select2:select', function (e) {
var platformData = e.params.data;
var gameValue = $('#properties_fixgame').select2('data');
if (gameValue) {
setFixGameDropDown();
}
});
function setFixGameDropDown() {
$('#properties_fixgame').empty().select2({
minimumInputLength: 3,
placeholder: 'Game',
templateResult: DropDownRenderGameOption,
ajax: {
url: '/api/v1.1/Search/Game',
data: function (params) {
fixplatform = $('#properties_fixplatform').select2('data');
var query = {
PlatformId: fixplatform[0].id,
SearchString: params.term
}
// Query parameters will be ?SearchString=[term]
return query;
},
processResults: function (data) {
var arr = [];
for (var i = 0; i < data.length; i++) {
arr.push({
id: data[i].id,
text: data[i].name,
cover: data[i].cover,
releaseDate: data[i].firstReleaseDate
});
}
return {
results: arr
};
}
}
});
}
setFixGameDropDown();
function SaveFixedGame() {
var fixplatform = $('#properties_fixplatform').select2('data');
var fixgame = $('#properties_fixgame').select2('data');
document.getElementById('properties_fixclear').setAttribute("disabled", "disabled");
document.getElementById('properties_fixsave').setAttribute("disabled", "disabled");
ajaxCall('/api/v1.1/Games/' + gameId + '/roms/' + modalVariables + '?NewPlatformId=' + fixplatform[0].id + '&NewGameId=' + fixgame[0].id, 'PATCH', function (result) {
window.location.reload();
});
}
function ClearFixedGame() {
var fixplatform = 0;
var fixgame = 0;
document.getElementById('properties_fixclear').setAttribute("disabled", "disabled");
document.getElementById('properties_fixsave').setAttribute("disabled", "disabled");
ajaxCall('/api/v1.1/Games/' + gameId + '/roms/' + modalVariables + '?NewPlatformId=' + fixplatform + '&NewGameId=' + fixgame, 'PATCH', function (result) {
window.location.reload();
});
}
function BuildAttributesTable(attributes, sourceName) {
var aTable = document.createElement('table');
aTable.style.width = '100%';
for (const [key, value] of Object.entries(attributes)) {
if (key != "ZipContents") {
// show attributes button
document.getElementById('properties_toc_attributes').style.display = '';
var aRow = document.createElement('tr');
var aTitleCell = document.createElement('th');
aTitleCell.width = "25%";
if (sourceName == "TOSEC") {
aTitleCell.innerHTML = ConvertTOSECAttributeName(key);
} else {
aTitleCell.innerHTML = key;
}
aRow.appendChild(aTitleCell);
var aValueCell = document.createElement('td');
aValueCell.width = "75%";
aValueCell.innerHTML = value;
aRow.appendChild(aValueCell);
aTable.appendChild(aRow);
}
}
return aTable;
}
function BuildArchiveTable(attributes, sourceName) {
for (const [key, value] of Object.entries(attributes)) {
if (key == "ZipContents") {
var archiveContent = JSON.parse(value);
// show archive button
document.getElementById('properties_toc_archive').style.display = '';
var aTable = document.createElement('table');
aTable.className = 'romtable';
aTable.setAttribute('cellspacing', 0);
aTable.style.width = '100%';
for (var r = 0; r < archiveContent.length; r++) {
var aBody = document.createElement('tbody');
aBody.className = 'romrow';
var aRow = document.createElement('tr');
var aNameCell = document.createElement('th');
aNameCell.className = 'romcell';
aNameCell.innerHTML = archiveContent[r].FilePath + '/' + archiveContent[r].FileName;
aRow.appendChild(aNameCell);
var aSizeCell = document.createElement('td');
aSizeCell.className = 'romcell';
aSizeCell.innerHTML = formatBytes(archiveContent[r].Size);
aRow.appendChild(aSizeCell);
aBody.appendChild(aRow);
var hRow = document.createElement('tr');
var aHashCell = document.createElement('td');
aHashCell.setAttribute('colspan', 2);
aHashCell.style.paddingLeft = '20px';
aHashCell.innerHTML = "MD5: " + archiveContent[r].MD5 + "<br />SHA1: " + archiveContent[r].SHA1;
hRow.appendChild(aHashCell);
aBody.appendChild(hRow);
if (archiveContent[r].isSignatureSelector == true) {
var sigRow = document.createElement('tr');
var sigCell = document.createElement('td');
sigCell.setAttribute('colspan', 2);
sigCell.style.paddingLeft = '20px';
sigCell.innerHTML = "Hash used to identify this archive";
sigRow.appendChild(sigCell);
aBody.appendChild(sigRow);
}
aTable.appendChild(aBody);
}
}
}
return aTable;
}
function ConvertTOSECAttributeName(attributeName) {
var tosecAttributeNames = {
"cr": "Cracked",
"f": "Fixed",
"h": "Hacked",
"m": "Modified",
"p": "Pirated",
"t": "Trained",
"tr": "Translated",
"o": "Over Dump",
"u": "Under Dump",
"v": "Virus",
"b": "Bad Dump",
"a": "Alternate",
"!": "Known Verified Dump"
};
if (attributeName in tosecAttributeNames) {
return tosecAttributeNames[attributeName];
} else {
return attributeName;
}
}
SelectTab('general');
document.getElementById('romDelete').setAttribute("onclick", "showSubDialog('romdelete', " + modalVariables + ");");
</script>

View File

@@ -1,10 +0,0 @@
<p>Are you sure you want to delete the selected ROMs and any associated saved states?</p>
<p><strong>Warning:</strong> This cannot be undone!</p>
<div style="width: 100%; text-align: center;">
<div style="display: inline-block; margin-right: 20px;">
<button class="redbutton" value="Delete" onclick="deleteGameRomsCallback(); closeSubDialog();">Delete</button>
</div>
<div style="display: inline-block; margin-left: 20px;">
<button value="Cancel" onclick="closeSubDialog();">Cancel</button>
</div>
</div>

View File

@@ -1,29 +0,0 @@
<p>Are you sure you want to delete the selected user?</p>
<p><strong>Warning:</strong> This cannot be undone!</p>
<div style="width: 100%; text-align: center;">
<div style="display: inline-block; margin-right: 20px;">
<button class="redbutton" value="Delete" onclick="deleteUserCallback();">Delete</button>
</div>
<div style="display: inline-block; margin-left: 20px;">
<button value="Cancel" onclick="closeSubDialog();">Cancel</button>
</div>
</div>
<script type="text/javascript">
function deleteUserCallback() {
ajaxCall(
'/api/v1.1/Account/Users/' + subModalVariables,
'DELETE',
function(result) {
console.log('Deleted user');
GetUsers();
closeSubDialog();
},
function(error) {
console.log(JSON.stringify(error));
GetUsers();
closeSubDialog();
}
);
}
</script>

View File

@@ -1,392 +0,0 @@
<div id="properties_toc">
<div id="properties_user_toc_password" name="properties_user_toc_item" onclick="UserSelectTab('password');">Password</div>
<div id="properties_user_toc_role" name="properties_user_toc_item" onclick="UserSelectTab('role');">Role</div>
<div id="properties_user_toc_age" name="properties_user_toc_item" onclick="UserSelectTab('age');">Content Restrictions</div>
<!--<div id="properties_toc_manage" name="properties_toc_item" onclick="SelectTab('manage');">Manage</div>-->
</div>
<div id="properties_bodypanel" style="height: 450px; overflow-y: scroll;">
<div id="properties_bodypanel_password" name="properties_user_tab" style="display: none;">
<table style="width: 100%;">
<tr>
<th>
Password
</th>
<td>
<input type="password" id="settings_users_edit_password" style="width: 95%;" onkeyup="checkPasswordsMatch();" />
</td>
</tr>
<tr>
<th>
Confirm password
</th>
<td>
<input type="password" id="settings_users_edit_confirmpassword" style="width: 95%;" onkeyup="checkPasswordsMatch();" />
</td>
</tr>
<tr>
<td colspan="2" id="settings_users_edit_label"></td>
</tr>
<tr>
<td colspan="2" id="settings_users_edit_errorlabel" style="color: red;"></td>
</tr>
</table>
</div>
<div id="properties_bodypanel_role" name="properties_user_tab" style="display: none;">
<table style="width: 100%;" class="romtable">
<tr>
<th>
</th>
<th>
<input type="radio" name="settings_user_role" id="settings_user_role_player" value="Player"> <label for="settings_user_role_player">Player</label>
</th>
<th>
<input type="radio" name="settings_user_role" id="settings_user_role_gamer" value="Gamer"> <label for="settings_user_role_gamer">Gamer</label>
</th>
<th>
<input type="radio" name="settings_user_role" id="settings_user_role_admin" value="Admin"> <label for="settings_user_role_admin">Administrator</label>
</th>
</tr>
<tr>
<th colspan="4"><h3>Games and ROMs</h3></td>
</tr>
<tr class="romrow">
<td class="romcell">Play games</td>
<td class="romcell"><img src="/images/tick.svg" class="banner_button_image" /></td>
<td class="romcell"><img src="/images/tick.svg" class="banner_button_image" /></td>
<td class="romcell"><img src="/images/tick.svg" class="banner_button_image" /></td>
</tr>
<tr class="romrow">
<td class="romcell">Download ROM images</td>
<td class="romcell"><img src="/images/tick.svg" class="banner_button_image" /></td>
<td class="romcell"><img src="/images/tick.svg" class="banner_button_image" /></td>
<td class="romcell"><img src="/images/tick.svg" class="banner_button_image" /></td>
</tr>
<tr class="romrow">
<td class="romcell">Upload ROM images</td>
<td class="romcell"></td>
<td class="romcell"><img src="/images/tick.svg" class="banner_button_image" /></td>
<td class="romcell"><img src="/images/tick.svg" class="banner_button_image" /></td>
</tr>
<tr class="romrow">
<td class="romcell">Create and delete multidisk packages</td>
<td class="romcell"></td>
<td class="romcell"><img src="/images/tick.svg" class="banner_button_image" /></td>
<td class="romcell"><img src="/images/tick.svg" class="banner_button_image" /></td>
</tr>
<tr class="romrow">
<td class="romcell">Delete ROM images</td>
<td class="romcell"></td>
<td class="romcell"><img src="/images/tick.svg" class="banner_button_image" /></td>
<td class="romcell"><img src="/images/tick.svg" class="banner_button_image" /></td>
</tr>
<tr class="romrow">
<td class="romcell">Fix ROM image matches</td>
<td class="romcell"></td>
<td class="romcell"><img src="/images/tick.svg" class="banner_button_image" /></td>
<td class="romcell"><img src="/images/tick.svg" class="banner_button_image" /></td>
</tr>
<tr>
<th colspan="4"><h3>Collections</h3></td>
</tr>
<tr class="romrow">
<td class="romcell">Download packages</td>
<td class="romcell"><img src="/images/tick.svg" class="banner_button_image" /></td>
<td class="romcell"><img src="/images/tick.svg" class="banner_button_image" /></td>
<td class="romcell"><img src="/images/tick.svg" class="banner_button_image" /></td>
</tr>
<tr class="romrow">
<td class="romcell">Create packages</td>
<td class="romcell"></td>
<td class="romcell"><img src="/images/tick.svg" class="banner_button_image" /></td>
<td class="romcell"><img src="/images/tick.svg" class="banner_button_image" /></td>
</tr>
<tr class="romrow">
<td class="romcell">Edit packages</td>
<td class="romcell"></td>
<td class="romcell"><img src="/images/tick.svg" class="banner_button_image" /></td>
<td class="romcell"><img src="/images/tick.svg" class="banner_button_image" /></td>
</tr>
<tr class="romrow">
<td class="romcell">Delete packages</td>
<td class="romcell"></td>
<td class="romcell"><img src="/images/tick.svg" class="banner_button_image" /></td>
<td class="romcell"><img src="/images/tick.svg" class="banner_button_image" /></td>
</tr>
<tr>
<th colspan="4"><h3>Settings</h3></td>
</tr>
<tr class="romrow">
<td class="romcell">Download firmware</td>
<td class="romcell"><img src="/images/tick.svg" class="banner_button_image" /></td>
<td class="romcell"><img src="/images/tick.svg" class="banner_button_image" /></td>
<td class="romcell"><img src="/images/tick.svg" class="banner_button_image" /></td>
</tr>
<tr class="romrow">
<td class="romcell">View background tasks</td>
<td class="romcell"><img src="/images/tick.svg" class="banner_button_image" /></td>
<td class="romcell"><img src="/images/tick.svg" class="banner_button_image" /></td>
<td class="romcell"><img src="/images/tick.svg" class="banner_button_image" /></td>
</tr>
<tr class="romrow">
<td class="romcell">View platform mapping</td>
<td class="romcell"><img src="/images/tick.svg" class="banner_button_image" /></td>
<td class="romcell"><img src="/images/tick.svg" class="banner_button_image" /></td>
<td class="romcell"><img src="/images/tick.svg" class="banner_button_image" /></td>
</tr>
<tr class="romrow">
<td class="romcell">Modify platform mapping</td>
<td class="romcell"></td>
<td class="romcell"></td>
<td class="romcell"><img src="/images/tick.svg" class="banner_button_image" /></td>
</tr>
<tr class="romrow">
<td class="romcell">Manually start background tasks</td>
<td class="romcell"></td>
<td class="romcell"></td>
<td class="romcell"><img src="/images/tick.svg" class="banner_button_image" /></td>
</tr>
<tr class="romrow">
<td class="romcell">View logs</td>
<td class="romcell"></td>
<td class="romcell"></td>
<td class="romcell"><img src="/images/tick.svg" class="banner_button_image" /></td>
</tr>
<tr class="romrow">
<td class="romcell">Manage user accounts</td>
<td class="romcell"></td>
<td class="romcell"></td>
<td class="romcell"><img src="/images/tick.svg" class="banner_button_image" /></td>
</tr>
</table>
</div>
<div id="properties_bodypanel_age" name="properties_user_tab" style="display: none;">
<h3>Classification Restrictions</h3>
<div id="properties_bodypanel_age_classification">
</div>
<input type="checkbox" id="properties_bodypanel_age_includeunclassified"> <label for="properties_bodypanel_age_includeunclassified">Include unclassified titles</label>
</div>
</div>
<div style="width: 100%; padding-top: 10px; text-align: right;">
<button id="settings_users_edit_okbutton" value="OK" onclick="saveProperties();">OK</button>
</div>
<script type="text/javascript">
ajaxCall(
'/api/v1.1/Account/users/' + modalVariables,
'GET',
function(result) {
document.getElementById('modal-heading').innerHTML = result.emailAddress;
// role page
document.getElementById('settings_user_role_' + result.highestRole.toLowerCase()).checked = true;
// age restriction page
var ageRatingsContainer = document.getElementById('properties_bodypanel_age_classification');
var ageRatingsTable = document.createElement('table');
ageRatingsTable.style.width = '100%';
ageRatingsTable.cellSpacing = 0;
ageRatingsTable.appendChild(
createTableRow(
true,
[
'Highest Allowed Rating',
'Included Ratings'
],
'',
''
)
);
for (var ageGroup in AgeRatingGroups) {
if (AgeRatingGroups.hasOwnProperty(ageGroup)) {
var ratingsValues = '';
var classBoards = AgeRatingGroups[ageGroup];
for (var classBoard in classBoards) {
for (var rating in classBoards[classBoard]) {
ratingsValues += "<img src='/images/Ratings/" + classBoard + "/" + AgeRatingStrings[classBoards[classBoard][rating]] + ".svg' class='rating_image_mini' />";
}
}
var radioCheckedState = '';
if (result.securityProfile.ageRestrictionPolicy.maximumAgeRestriction.toLowerCase() == ageGroup.toLocaleLowerCase()) {
radioCheckedState = "checked='checked'";
}
ageRatingsTable.appendChild(
createTableRow(
false,
[
"<input type='radio' id='properties_bodypanel_age_classification_" + ageGroup + "' name='classification_group' " + radioCheckedState + " value='" + ageGroup + "' /> <label for='properties_bodypanel_age_classification_" + ageGroup + "'>" + ageGroup + "</label>",
ratingsValues
],
'romrow',
'romcell'
)
);
}
}
ageRatingsContainer.appendChild(ageRatingsTable);
document.getElementById('properties_bodypanel_age_includeunclassified').checked = result.securityProfile.ageRestrictionPolicy.includeUnrated;
},
function(error) {
closeDialog();
}
);
function UserSelectTab(TabName) {
var tabs = document.getElementsByName('properties_user_tab');
for (var i = 0; i < tabs.length; i++) {
if ((tabs[i].id) == ("properties_bodypanel_" + TabName)) {
tabs[i].style.display = '';
} else {
tabs[i].style.display = 'none';
}
}
var tocs = document.getElementsByName('properties_user_toc_item');
for (var i = 0; i < tocs.length; i++) {
if ((tocs[i].id) == ("properties_user_toc_" + TabName)) {
tocs[i].className = "properties_toc_item_selected";
} else {
tocs[i].className = '';
}
}
}
function checkPasswordsMatch() {
var newPassword = document.getElementById('settings_users_edit_password').value;
var conPassword = document.getElementById('settings_users_edit_confirmpassword').value;
var errorLabel = document.getElementById('settings_users_edit_label');
var submitButton = document.getElementById('settings_users_edit_okbutton');
if (newPassword.length > 0) {
if (newPassword == conPassword) {
// check if password meets requirements
if (newPassword.length >= 10) {
errorLabel.innerHTML = "";
submitButton.removeAttribute('disabled');
return true;
} else {
errorLabel.innerHTML = "Password should be at least 10 characters long";
submitButton.setAttribute('disabled', 'disabled');
return false;
}
} else {
errorLabel.innerHTML = "New and confirmed passwords do not match";
submitButton.setAttribute('disabled', 'disabled');
return false;
}
} else {
errorLabel.innerHTML = "Password will not be changed";
submitButton.removeAttribute('disabled');
return true;
}
}
function saveProperties() {
saveRole();
}
function saveRole() {
if (checkPasswordsMatch() == true) {
// process role
var selectedRole = $("input[type='radio'][name='settings_user_role']:checked").val();
ajaxCall(
'/api/v1.1/Account/users/' + modalVariables + '/Roles?RoleName=' + selectedRole,
'POST',
function(result) {
saveSecurityProfile();
},
function(error) {
saveSecurityProfile();
}
);
}
}
function saveSecurityProfile() {
if (checkPasswordsMatch() == true) {
// process security profile
var securityProfile = {
"ageRestrictionPolicy": {
"maximumAgeRestriction": $("input[type='radio'][name='classification_group']:checked").val(),
"includeUnrated": document.getElementById('properties_bodypanel_age_includeunclassified').checked
}
};
ajaxCall(
'/api/v1.1/Account/users/' + modalVariables + '/SecurityProfile',
'POST',
function(result) {
savePassword();
},
function(error) {
savePassword();
},
JSON.stringify(securityProfile)
);
}
}
function savePassword() {
console.log("Save Password");
if (checkPasswordsMatch() == true) {
console.log("Passwords match");
var newPassword = document.getElementById('settings_users_edit_password').value;
if (newPassword.length > 0) {
console.log("New password value is long enough to commit to database");
var model = {
"newPassword": newPassword,
"confirmPassword": newPassword
}
ajaxCall(
'/api/v1.1/Account/Users/' + modalVariables + '/Password',
'POST',
function(result) {
savePasswordsCallback(result);
},
function(error) {
savePasswordsCallback(error);
},
JSON.stringify(model)
);
} else {
console.log("Password not long enough to change");
savePropertiesCallback();
}
} else {
console.log("Passwords don't match");
}
}
function savePasswordsCallback(result) {
console.log(result);
if (result.succeeded == true) {
savePropertiesCallback();
} else {
var errorBox = document.getElementById('settings_users_edit_errorlabel');
errorBox.innerHTML = '';
for (var i = 0; i < result.errors.length; i++) {
var errorMessage = document.createElement('p');
errorMessage.innerHTML = result.errors[i].description;
errorBox.appendChild(errorMessage);
}
}
}
function savePropertiesCallback() {
GetUsers();
closeDialog();
}
UserSelectTab('password');
</script>

View File

@@ -1,104 +0,0 @@
<h3>New User</h3>
<table style="width: 100%;">
<tr>
<th>
Email
</th>
<td>
<input type="text" id="settings_users_new_username" style="width: 95%;" onkeyup="checkPasswordsMatch();" />
</td>
</tr>
<tr>
<th>
Password
</th>
<td>
<input type="password" id="settings_users_new_password" style="width: 95%;" onkeyup="checkPasswordsMatch();" />
</td>
</tr>
<tr>
<th>
Confirm password
</th>
<td>
<input type="password" id="settings_users_new_confirmpassword" style="width: 95%;" onkeyup="checkPasswordsMatch();" />
</td>
</tr>
<tr>
<td colspan="2" id="settings_users_new_label"></td>
</tr>
<tr>
<td colspan="2" id="settings_users_new_errors" style="color: red;"></td>
</tr>
<tr>
<td colspan="2" style="text-align: right; padding-top: 10px;">
<button value="OK" id="settings_users_new_okbutton" disabled="disabled" onclick="createUser();">OK</button><button value="Cancel" onclick="closeSubDialog();">Cancel</button>
</td>
</tr>
</table>
<script type="text/javascript">
function checkPasswordsMatch() {
var userNameVal = document.getElementById('settings_users_new_username').value;
var newPassword = document.getElementById('settings_users_new_password').value;
var conPassword = document.getElementById('settings_users_new_confirmpassword').value;
var errorLabel = document.getElementById('settings_users_new_label');
var submitButton = document.getElementById('settings_users_new_okbutton');
if (userNameVal.includes("@")) {
if (newPassword == conPassword) {
// check if password meets requirements
if (newPassword.length >= 10) {
errorLabel.innerHTML = "";
submitButton.removeAttribute('disabled');
} else {
errorLabel.innerHTML = "Password should be at least 10 characters long";
submitButton.setAttribute('disabled', 'disabled');
}
} else {
errorLabel.innerHTML = "New and confirmed passwords do not match";
submitButton.setAttribute('disabled', 'disabled');
}
} else {
errorLabel.innerHTML = "Email address is invalid";
submitButton.setAttribute('disabled', 'disabled');
}
}
function createUser() {
var model = {
"userName": document.getElementById('settings_users_new_username').value,
"email": document.getElementById('settings_users_new_username').value,
"password": document.getElementById('settings_users_new_password').value,
"confirmPassword": document.getElementById('settings_users_new_confirmpassword').value
}
ajaxCall(
'/api/v1.1/Account/Users',
'POST',
function(result) {
createUserCallback(result);
},
function(error) {
createUserCallback(result);
},
JSON.stringify(model)
);
}
function createUserCallback(result) {
if (result.succeeded == true) {
GetUsers();
closeSubDialog();
} else {
var errorBox = document.getElementById('settings_users_new_errors');
errorBox.innerHTML = '';
for (var i = 0; i < result.errors.length; i++) {
var errorMessage = document.createElement('p');
errorMessage.innerHTML = result.errors[i].description;
errorBox.appendChild(errorMessage);
}
}
}
</script>

View File

@@ -1,130 +0,0 @@
<!-- The Modal -->
<div id="myModalSub" class="modal">
<!-- Modal content -->
<div class="modal-content-sub">
<span id="modal-close-sub" class="close">&times;</span>
<div id="modal-content-sub">Some text in the Modal..</div>
</div>
</div>
<div>
<div id="upload_target" class="dropzone"></div>
</div>
<table style="width: 100%;">
<tr>
<th style="width: 40%;">
Override automatic platform detection:
</th>
<td style="width: 60%;">
<select id="upload_platformoverride" style="width: 100%;"></select>
</td>
</tr>
</table>
<script type="text/javascript">
document.getElementById('modal-heading').innerHTML = "Upload";
document.getElementById('upload_platformoverride').innerHTML = "<option value='0' selected='selected'>Automatic Platform</option>";
var myDropzone = new Dropzone("div#upload_target", {
url: "/api/v1.1/Roms",
autoProcessQueue: true,
uploadMultiple: true,
paramName: myParamName,
maxFilesize: 60000,
createImageThumbnails: false,
disablePreviews: false
});
function myParamName() {
return "files";
}
function showSubDialog(dialogPage, variables) {
// Get the modal
var submodal = document.getElementById("myModalSub");
// Get the modal content
var subModalContent = document.getElementById("modal-content-sub");
// Get the button that opens the modal
var subbtn = document.getElementById("romDelete");
// Get the <span> element that closes the modal
var subspan = document.getElementById("modal-close-sub");
// When the user clicks on the button, open the modal
submodal.style.display = "block";
// When the user clicks on <span> (x), close the modal
subspan.onclick = function () {
submodal.style.display = "none";
subModalContent.innerHTML = "";
subModalVariables = null;
}
subModalVariables = modalVariables;
$('#modal-content-sub').load('/pages/dialogs/' + dialogPage + '.html?v=' + AppVersion);
}
function closeSubDialog() {
// Get the modal
var submodal = document.getElementById("myModalSub");
// Get the modal content
var subModalContent = document.getElementById("modal-content-sub");
submodal.style.display = "none";
subModalContent.innerHTML = "";
subModalVariables = null;
}
$('#upload_platformoverride').select2({
minimumInputLength: 3,
ajax: {
url: '/api/v1.1/Search/Platform',
data: function (params) {
var query = {
SearchString: params.term
}
// Query parameters will be ?SearchString=[term]
return query;
},
processResults: function (data) {
var arr = [];
// insert automatic detection item
arr.push({
id: 0,
text: "Automatic Platform"
});
for (var i = 0; i < data.length; i++) {
arr.push({
id: data[i].id,
text: data[i].name
});
}
return {
results: arr
};
}
}
});
$('#upload_platformoverride').on('select2:select', function (e) {
var platformOverride = $('#upload_platformoverride').select2('data');
var queryString = '';
if (Number(platformOverride[0].id) != 0) {
queryString = "?OverridePlatformId=" + platformOverride[0].id;
}
console.log(queryString);
myDropzone.options.url = "/api/v1.1/Roms" + queryString;
});
</script>

View File

@@ -1,449 +0,0 @@
<div id="properties_toc">
<div id="properties_profile_toc_general" name="properties_profile_toc_item" onclick="ProfileSelectTab('general');">Preferences</div>
<div id="properties_profile_toc_avatar" name="properties_profile_toc_item" onclick="ProfileSelectTab('avatar');">Avatar</div>
<div id="properties_profile_toc_account" name="properties_profile_toc_item" onclick="ProfileSelectTab('account');">Account</div>
</div>
<div id="properties_bodypanel">
<div id="properties_bodypanel_general" name="properties_profile_tab" style="display: none;">
<h3>Game Library</h3>
<table style="width: 100%;">
<tr>
<th>
Library
</th>
</tr>
<tr>
<td>
Pagination mode:
</td>
</tr>
<tr>
<td>
<select id="profile_pref-LibraryPagination" data-pref="LibraryPagination" data-minimum-results-for-search="Infinity">
<option value="paged">Paged</option>
<option value="infinite">Infinite scrolling</option>
</select>
</td>
</tr>
<tr>
<td></td>
</tr>
<tr>
<th>
Game Icons
</th>
</tr>
<tr>
<td>
<input type="checkbox" id="profile_pref_LibraryShowGameTitle" data-pref="LibraryShowGameTitle"><label for="profile_pref_LibraryShowGameTitle"> Show title</label>
</td>
</tr>
<tr>
<td>
<input type="checkbox" id="profile_pref_LibraryShowGameRating" data-pref="LibraryShowGameRating"><label for="profile_pref_LibraryShowGameRating"> Show rating</label>
</td>
</tr>
<tr>
<td>
<input type="checkbox" id="profile_pref_LibraryShowGameClassification" data-pref="LibraryShowGameClassification"><label for="profile_pref_LibraryShowGameClassification"> Show age classification badges</label>
</td>
</tr>
<tr>
<td>
<table id="profile_pref_LibraryClassificationBadgeSelect">
<tr>
<td>Use classification badges from:</td>
</tr>
<tr>
<td>
<select id="profile_pref_LibraryPrimaryClassificationBadge" data-primary="primary" data-minimum-results-for-search="Infinity" onchange="SavePrefValue_ClassBadge(this);">
</select>
</td>
</tr>
<tr>
<td>Fallback to classification badges from:</td>
</tr>
<tr>
<td>
<select id="profile_pref_LibraryFallbackClassificationBadge" onchange="SavePrefValue_ClassBadge(this);" data-minimum-results-for-search="Infinity">
</select>
</td>
</tr>
</table>
</td>
</tr>
<tr>
<td>
<strong>Note</strong>: The page will need to be reloaded for changes to take effect.
</td>
</tr>
<tr>
<td style="text-align: right;">
<button id="profile_pref_ok" value="OK" onclick="SavePrefs();">OK</button>
</td>
</tr>
</table>
</div>
<div id="properties_bodypanel_avatar" name="properties_profile_tab" style="display: none;">
<h3>Avatar</h3>
<div style="width: 100%; text-align: center;">
<div>
<img id="properties_bodypanel_avatar_image" style="width: 200px; height: 200px;" src="/images/user.svg"/>
</div>
<form id="properties_bodypanel_avatar_form" onsubmit="return false">
<input type="file" name="file" id="properties_bodypanel_avatar_upload" accept="image/*" /><button value="Save" onclick="SaveAvatar();">Save</button><button value="Delete" onclick="SaveAvatar(true);">Delete</button>
</form>
</div>
</div>
<div id="properties_bodypanel_account" name="properties_profile_tab" style="display: none;">
<h3>Reset Password</h3>
<table style="width: 100%;">
<tr>
<th>Old Password</th>
<td><input type="password" id="profile_oldpassword" style="width: 95%;" /></td>
</tr>
<tr>
<th>New Password</th>
<td><input type="password" id="profile_newpassword" style="width: 95%;" onkeyup="checkPasswordsMatch();" /></td>
</tr>
<tr>
<th>Confirm Password</th>
<td><input type="password" id="profile_confirmpassword" style="width: 95%;" onkeyup="checkPasswordsMatch();" /></td>
</tr>
<tr>
<td colspan="2" id="profile_passwordnotice"></td>
</tr>
<tr>
<td colspan="2" id="profile_passworderrors" style="color: red;"></td>
</tr>
<tr>
<td colspan="2" style="text-align: right;">
<button id="profile_resetpassword" value="Reset Password" disabled="disabled" onclick="ResetPassword();">Reset Password</button>
</td>
</tr>
</table>
</div>
</div>
<script type="text/javascript">
document.getElementById('modal-heading').innerHTML = userProfile.emailAddress;
function ProfileSelectTab(TabName) {
var tabs = document.getElementsByName('properties_profile_tab');
for (var i = 0; i < tabs.length; i++) {
if ((tabs[i].id) == ("properties_bodypanel_" + TabName)) {
tabs[i].style.display = '';
} else {
tabs[i].style.display = 'none';
}
}
var tocs = document.getElementsByName('properties_profile_toc_item');
for (var i = 0; i < tocs.length; i++) {
if ((tocs[i].id) == ("properties_profile_toc_" + TabName)) {
tocs[i].className = "properties_toc_item_selected";
} else {
tocs[i].className = '';
}
}
}
function GetPrefInitialValues() {
var paginationMode = document.getElementById('profile_pref-LibraryPagination');
paginationMode.value = GetPreference('LibraryPagination', 'paged');
ConfigurePrefInitialValue_Checkbox("LibraryShowGameTitle", GetPreference("LibraryShowGameTitle", true));
ConfigurePrefInitialValue_Checkbox("LibraryShowGameRating", GetPreference("LibraryShowGameRating", true));
ConfigurePrefInitialValue_Checkbox("LibraryShowGameClassification", GetPreference("LibraryShowGameClassification", true));
var primary = document.getElementById('profile_pref_LibraryPrimaryClassificationBadge');
var secondary = document.getElementById('profile_pref_LibraryFallbackClassificationBadge');
PopulateClassificationMenus(primary);
PopulateClassificationMenus(secondary, true);
var classificationOrder = JSON.parse(GetPreference("LibraryGameClassificationDisplayOrder", JSON.stringify([ "ESRB" ])));
primary.value = classificationOrder[0];
if (classificationOrder[1]) {
secondary.value = classificationOrder[1];
}
for (var i = 0; i < secondary.childNodes.length; i++) {
if (secondary.childNodes[i].value == primary.value) {
secondary.childNodes[i].setAttribute('disabled', 'disabled');
} else {
secondary.childNodes[i].removeAttribute('disabled');
}
}
}
function PopulateClassificationMenus(targetSelector, IsSecondary) {
targetSelector.innerHTML = '';
if (IsSecondary == true) {
var defaultOpt = document.createElement('option');
defaultOpt.value = '-';
defaultOpt.innerHTML = 'None';
targetSelector.appendChild(defaultOpt);
}
for (const [key, value] of Object.entries(ClassificationBoards)) {
var opt = document.createElement('option');
opt.value = key;
opt.innerHTML = value;
targetSelector.appendChild(opt);
}
}
function ConfigurePrefInitialValue_Checkbox(ValueName, ValueSetting) {
var valueCheckbox = document.getElementById("profile_pref_" + ValueName);
if (ValueSetting == "true" || ValueSetting == true) {
valueCheckbox.checked = true;
updateDisplay(ValueName, true);
} else {
valueCheckbox.checked = false;
updateDisplay(ValueName, false);
}
}
function SavePrefs() {
var model = [];
model.push(SavePrefValue_Checkbox(document.getElementById('profile_pref_LibraryShowGameTitle')));
model.push(SavePrefValue_Checkbox(document.getElementById('profile_pref_LibraryShowGameRating')));
model.push(SavePrefValue_Checkbox(document.getElementById('profile_pref_LibraryShowGameClassification')));
model.push(SavePrefValue_Value(document.getElementById('profile_pref-LibraryPagination')));
model.push(
{
"setting": "LibraryGameClassificationDisplayOrder",
"value": JSON.stringify(SavePrefValue_ClassBadge(document.getElementById('profile_pref_LibraryPrimaryClassificationBadge')))
}
);
SetPreference_Batch(model);
if (getQueryString('page', 'string') == 'home' || getQueryString('page', 'string') == undefined) {
setCookie('games_library_last_page', 1);
//location.reload();
}
closeDialog();
}
function SavePrefValue_Checkbox(e) {
var ValueName = e.getAttribute("data-pref");
return { "setting": ValueName, "value": e.checked.toString() };
}
function SavePrefValue_Value(e) {
var ValueName = e.getAttribute("data-pref");
return { "setting": ValueName, "value": e.value };
}
function updateDisplay(ValueName, ValueSetting) {
switch(ValueName) {
case "LibraryShowGameClassification":
// var badgeSelector = document.getElementById("profile_pref_LibraryClassificationBadgeSelect");
// if (ValueSetting == true || ValueSetting == "true") {
// badgeSelector.style.display = '';
// } else {
// badgeSelector.style.display = 'none';
// }
break;
}
}
function SavePrefValue_ClassBadge(e) {
var primary = document.getElementById('profile_pref_LibraryPrimaryClassificationBadge');
var secondary = document.getElementById('profile_pref_LibraryFallbackClassificationBadge');
if (e.getAttribute('data-primary') == 'primary') {
// reset secondary to "none" if the same board is selected in both
if (primary.value == secondary.value) {
secondary.value = '-';
}
// disable in secondary board selected in primary
for (var i = 0; i < secondary.childNodes.length; i++) {
if (secondary.childNodes[i].value == primary.value) {
secondary.childNodes[i].setAttribute('disabled', 'disabled');
} else {
secondary.childNodes[i].removeAttribute('disabled');
}
}
}
// save values
var model = [];
if (secondary.value == '-') {
model = [ primary.value ];
} else {
model = [ primary.value, secondary.value ];
}
return model;
}
function checkPasswordsMatch() {
var oldPassword = document.getElementById('profile_oldpassword').value;
var newPassword = document.getElementById('profile_newpassword').value;
var conPassword = document.getElementById('profile_confirmpassword').value;
var errorLabel = document.getElementById('profile_passwordnotice');
var submitButton = document.getElementById('profile_resetpassword');
// make sure the new password is not the same as the old one
if (newPassword == oldPassword) {
errorLabel.innerHTML = "New password should not match the old password";
submitButton.setAttribute('disabled', 'disabled');
} else {
if (newPassword == conPassword) {
// check if password meets requirements
if (newPassword.length >= 10) {
errorLabel.innerHTML = "";
submitButton.removeAttribute('disabled');
} else {
errorLabel.innerHTML = "Password should be at least 10 characters long";
submitButton.setAttribute('disabled', 'disabled');
}
} else {
errorLabel.innerHTML = "New and confirmed passwords do not match";
submitButton.setAttribute('disabled', 'disabled');
}
}
}
function ResetPassword() {
var oldPassword = document.getElementById('profile_oldpassword').value;
var newPassword = document.getElementById('profile_newpassword').value;
var conPassword = document.getElementById('profile_confirmpassword').value;
var model = {
"OldPassword": oldPassword,
"NewPassword": newPassword,
"ConfirmPassword": conPassword
}
ajaxCall(
'/api/v1.1/Account/ChangePassword',
'POST',
function(result) {
ResetPasswordCallback(result);
},
function(error) {
ResetPasswordCallback(error);
},
JSON.stringify(model)
);
}
function ResetPasswordCallback(result) {
var errorLabel = document.getElementById('profile_passwordnotice');
var errorBox = document.getElementById('profile_passworderrors');
errorBox.innerHTML = '';
console.log(result);
if (result.responseJSON.succeeded == false) {
for (var i = 0; i < result.responseJSON.errors.length; i++) {
var errorMessage = document.createElement('p');
errorMessage.innerHTML = result.responseJSON.errors[i].description;
errorBox.appendChild(errorMessage);
}
} else {
document.getElementById('profile_oldpassword').value = '';
document.getElementById('profile_newpassword').value = '';
document.getElementById('profile_confirmpassword').value = '';
document.getElementById('profile_resetpassword').setAttribute('disabled', 'disabled');
errorLabel.innerHTML = "Password changed.";
}
}
function SaveAvatar(DeleteExisting) {
if (DeleteExisting == true) {
ajaxCall(
'/api/v1.1/Account/Avatar/' + userProfile.avatar + '.jpg',
'DELETE',
function (success) {
userProfile.avatar = "00000000-0000-0000-0000-000000000000";
loadAvatar(userProfile.avatar);
displayAvatarPreview("/images/user.svg");
},
function (error) {
userProfile.avatar = "00000000-0000-0000-0000-000000000000";
loadAvatar(userProfile.avatar);
displayAvatarPreview("/images/user.svg");
}
);
} else {
var form = $('#properties_bodypanel_avatar_form')[0];
var formData = new FormData(form);
formData.append("file", document.getElementById("properties_bodypanel_avatar_upload").files[0]);
$.ajax({
// Our sample url to make request
url:
'/api/v1.1/Account/Avatar',
// Type of Request
type: 'POST',
// data to send to the server
data: formData,
contentType: false,
processData: false,
// Function to call when to
// request is ok
success: function (data) {
var x = JSON.stringify(data);
console.log(x);
loadAvatar(data);
userProfile.avatar = data;
displayAvatarPreview("/api/v1.1/Account/Avatar/" + data + ".jpg");
},
// Error handling
error: function (error) {
console.log(`Error ${JSON.stringify(error)}`);
}
});
}
}
function displayAvatarPreview(previewImg) {
var previewPath;
if (previewImg) {
previewPath = previewImg;
} else {
if (userProfile.avatar == "00000000-0000-0000-0000-000000000000") {
previewPath = "/images/user.svg";
} else {
previewPath = "/api/v1.1/Account/Avatar/" + userProfile.avatar + ".jpg";
}
}
var previewElement = document.getElementById('properties_bodypanel_avatar_image')
previewElement.setAttribute("src", previewPath);
if (previewPath != "/images/user.svg") {
previewElement.style.filter = "";
} else {
previewElement.style.filter = "invert(100%)";
}
}
ProfileSelectTab('general');
GetPrefInitialValues();
displayAvatarPreview();
$('#profile_pref-LibraryPagination').select2();
$('#profile_pref_LibraryPrimaryClassificationBadge').select2();
$('#profile_pref_LibraryFallbackClassificationBadge').select2();
</script>

View File

@@ -5,101 +5,6 @@
<div id="emulator" class="emulator_fullscreen"></div>
<script type="text/javascript">
var gameId = getQueryString('gameid', 'int');
var romId = getQueryString('romid', 'int');
var platformId = getQueryString('platformid', 'int');
var IsMediaGroupInt = getQueryString('mediagroup', 'int');
var IsMediaGroup = false;
if (IsMediaGroupInt == 1) { IsMediaGroup = true; }
var StateUrl = undefined;
if (getQueryString('stateid', 'int')) {
StateUrl = '/api/v1.1/StateManager/' + romId + '/' + getQueryString('stateid', 'int') + '/State/savestate.state?IsMediaGroup=' + IsMediaGroup;
}
var gameData;
var artworks = null;
var artworksPosition = 0;
var emuGameTitle = '';
var emuBios = '';
var emuBackground = '';
console.log("Loading rom url: " + decodeURIComponent(getQueryString('rompath', 'string')));
ajaxCall('/api/v1.1/Games/' + gameId, 'GET', function (result) {
gameData = result;
// load artwork
if (result.artworks) {
artworks = result.artworks.ids;
var startPos = randomIntFromInterval(0, result.artworks.ids.length);
artworksPosition = startPos;
rotateBackground();
} else {
if (result.cover) {
var bg = document.getElementById('bgImage');
bg.setAttribute('style', 'background-image: url("/api/v1.1/Games/' + gameId + '/cover/image/original/' + result.cover.imageId + '.jpg"); background-position: center; background-repeat: no-repeat; background-size: cover; filter: blur(10px); -webkit-filter: blur(10px);');
}
}
if (result.cover) {
emuBackground = '/api/v1.1/Games/' + gameId + '/cover/image/original/' + result.cover.imageId + '.jpg';
}
emuGameTitle = gameData.name;
});
ajaxCall('/api/v1.1/Bios/' + platformId, 'GET', function (result) {
if (result.length == 0) {
emuBios = '';
} else {
emuBios = '/api/v1.1/Bios/zip/' + platformId;
console.log("Using BIOS link: " + emuBios);
}
switch (getQueryString('engine', 'string')) {
case 'EmulatorJS':
console.log("Emulator: " + getQueryString('engine', 'string'));
console.log("Core: " + getQueryString('core', 'string'));
$('#emulator').load('/emulators/EmulatorJS.html?v=' + AppVersion);
break;
}
});
function rotateBackground() {
if (artworks) {
artworksPosition += 1;
if (artworks[artworksPosition] == null) {
artworksPosition = 0;
}
var bg = document.getElementById('bgImage');
bg.setAttribute('style', 'background-image: url("/api/v1.1/Games/' + gameId + '/artwork/' + artworks[artworksPosition] + '/image/original/' + artworks[artworksPosition] + '.jpg"); background-position: center; background-repeat: no-repeat; background-size: cover; filter: blur(10px); -webkit-filter: blur(10px);');
}
}
// statistics
var SessionId = undefined;
function SaveStatistics() {
var model;
if (SessionId == undefined) {
ajaxCall(
'/api/v1.1/Statistics/Games/' + gameId,
'POST',
function (success) {
SessionId = success.sessionId;
}
);
} else {
ajaxCall(
'/api/v1.1/Statistics/Games/' + gameId + '/' + SessionId,
'PUT',
function (success) {
}
);
}
}
setInterval(SaveStatistics, 60000);
</script>
// setup the page
SetupPage();
</script>

View File

@@ -0,0 +1,91 @@
var gameId = getQueryString('gameid', 'int');
var romId = getQueryString('romid', 'int');
var platformId = getQueryString('platformid', 'int');
var IsMediaGroupInt = getQueryString('mediagroup', 'int');
var IsMediaGroup = false;
var StateUrl = undefined;
var gameData;
var artworks = null;
var artworksPosition = 0;
var emuGameTitle = '';
var emuBios = '';
var emuBackground = '';
// statistics
var SessionId = undefined;
function SetupPage() {
if (IsMediaGroupInt == 1) { IsMediaGroup = true; }
if (getQueryString('stateid', 'int')) {
StateUrl = '/api/v1.1/StateManager/' + romId + '/' + getQueryString('stateid', 'int') + '/State/savestate.state?StateOnly=true&IsMediaGroup=' + IsMediaGroup;
}
console.log("Loading rom url: " + decodeURIComponent(getQueryString('rompath', 'string')));
ajaxCall('/api/v1.1/Games/' + gameId, 'GET', function (result) {
gameData = result;
if (result.cover) {
emuBackground = '/api/v1.1/Games/' + gameId + '/cover/' + result.cover.id + '/image/original/' + result.cover.imageId + '.jpg';
}
emuGameTitle = gameData.name;
});
ajaxCall('/api/v1.1/Bios/' + platformId, 'GET', function (result) {
if (result.length == 0) {
emuBios = '';
} else {
emuBios = '/api/v1.1/Bios/zip/' + platformId + '/' + gameId + '?filtered=true';
console.log("Using BIOS link: " + emuBios);
}
switch (getQueryString('engine', 'string')) {
case 'EmulatorJS':
console.log("Emulator: " + getQueryString('engine', 'string'));
console.log("Core: " + getQueryString('core', 'string'));
$('#emulator').load('/emulators/EmulatorJS.html?v=' + AppVersion);
break;
}
});
setInterval(SaveStatistics, 60000);
}
function rotateBackground() {
if (artworks) {
artworksPosition += 1;
if (artworks[artworksPosition] == null) {
artworksPosition = 0;
}
var bg = document.getElementById('bgImage');
bg.setAttribute('style', 'background-image: url("/api/v1.1/Games/' + gameId + '/artwork/' + artworks[artworksPosition] + '/image/original/' + artworks[artworksPosition] + '.jpg"); background-position: center; background-repeat: no-repeat; background-size: cover; filter: blur(10px); -webkit-filter: blur(10px);');
}
}
function SaveStatistics() {
var model;
if (SessionId == undefined) {
ajaxCall(
'/api/v1.1/Statistics/Games/' + gameId + '/' + platformId + '/' + romId + '?IsMediaGroup=' + IsMediaGroup,
'POST',
function (success) {
SessionId = success.sessionId;
}
);
} else {
ajaxCall(
'/api/v1.1/Statistics/Games/' + gameId + '/' + platformId + '/' + romId + '/' + SessionId + '?IsMediaGroup=' + IsMediaGroup,
'PUT',
function (success) {
}
);
}
}
SetupPage();

View File

@@ -1,176 +1,107 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<script src="/api/v1.1/System/VersionFile"></script>
<link type="text/css" rel="stylesheet" dat-href="/styles/style.css" />
<script src="/scripts/jquery-3.6.0.min.js"></script>
<script src="/scripts/moment.js"></script>
<link href="/styles/select2.min.css" rel="stylesheet" />
<link href="/styles/dropzone.min.css" rel="stylesheet" type="text/css" />
<script src="/scripts/jquery.lazy.min.js"></script>
<script src="/scripts/jquery.lazy.plugins.min.js"></script>
<script src="/scripts/select2.min.js"></script>
<script src="/scripts/dropzone.min.js"></script>
<script src="/scripts/simpleUpload.min.js"></script>
<script src="/scripts/main.js" type="text/javascript"></script>
<script src="/scripts/filterformating.js" type="text/javascript"></script>
<script src="/scripts/gamesformating.js" type="text/javascript"></script>
<link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png">
<link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png">
<link rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png">
<link rel="manifest" href="/site.webmanifest">
<title>Gaseous Games</title>
<!-- welcome screen -->
<div class="modal-background">
<div id="first_welcome" class="modal-window"
style="width: 315px; height: 315px; min-height: unset; min-width: unset; max-height: unset; max-width: unset;">
<div id="welcomeform" class="loginwindow-content">
<div class="loginwindow-logospace">
<div class="loginwindow-logospace-banner loginwindow-logospace-banner-top">
<!-- <img src="/images/logo.png" style="display: block; margin: 20px auto; width: 100px;" /> -->
<div class="loginwindow-logospace-logo">&nbsp;</div>
<script type="text/javascript">
var head = document.getElementsByTagName('head')[0];
<div id="loginwindow_header_label" class="loginwindow-logospace-label">Gaseous Games</div>
// update links
var headLinks = document.getElementsByTagName('link');
for (var i = 0; i < headLinks.length; i++) {
if (headLinks[i].getAttribute('dat-href') && headLinks[i].rel == "stylesheet") {
var newLink = document.createElement('link');
newLink.rel = "stylesheet";
newLink.href = headLinks[i].getAttribute('dat-href') + '?v=' + AppVersion;
newLink.type = "text/css";
<div style="height: 20px;">&nbsp;</div>
headLinks[i].parentElement.removeChild(headLinks[i]);
head.appendChild(newLink);
}
}
</script>
</head>
<body>
<div id="bgImage" style="background-image: url('/images/LoginWallpaper.jpg'); background-position: center; background-repeat: no-repeat; background-size: cover; filter: blur(10px); -webkit-filter: blur(10px);">
<div id="bgImage_Opacity"></div>
</div>
<div id="content">
<div class="loginwindow" id="first_welcome">
<div id="welcomeform" class="loginwindow-content">
<img src="/images/logo.png" style="display: block; margin: 20px auto; width: 100px;" />
<div id="loginwindow_header_label" style="display: block; text-align: center;">Gaseous Games</div>
<button type="button" value="Get Started" onclick="document.getElementById('first_welcome').style.display = 'none'; document.getElementById('first_newadmin').style.display = '';" class="bigbutton">Get Started</button>
<button type="button" value="Get Started"
onclick="document.getElementById('first_welcome').style.display = 'none'; document.getElementById('first_newadmin').style.display = '';"
class="bigbutton">Get Started</button>
</div>
</div>
</div>
<div class="loginwindow" id="first_newadmin" style="display: none;">
<div id="loginform" class="loginwindow-content">
<img src="/images/logo.png" style="display: block; margin: 20px auto; width: 100px;" />
</div>
<div id="loginwindow_header_label" style="display: block; text-align: center;">Gaseous Games</div>
<!-- first login -->
<div class="modal-window" id="first_newadmin"
style="width: 600px; height: 550px; min-height: unset; min-width: unset; max-height: unset; max-width: unset; display: none;">
<div id="loginform" class="loginwindow-content">
<div class="loginwindow-logospace">
<div class="loginwindow-logospace-banner loginwindow-logospace-banner-top">
<div class="loginwindow-logospace-logo">&nbsp;</div>
<div class="loginwindow-logospace-label">
<div>
Gaseous Games
</div>
</div>
</div>
<div class="loginwindow-logospace-banner loginwindow-logospace-banner-bottom">
<div class="loginwindow-logospace-linktable">
<div class="loginwindow-logospace-linktable-link">
<a href="https://github.com/gaseous-project/gaseous-server"
class="romlink romlink-nounderline">
<img src="/images/github-mark.svg" class="banner_button_image" />
GitHub
</a>
</div>
<div class="loginwindow-logospace-linktable-link">
<a href="https://discord.gg/Nhu7wpT3k4" class="romlink romlink-nounderline">
<img src="/images/discord.svg" class="banner_button_image" />
Discord
</a>
</div>
</div>
</div>
</div>
<table style="width: 100%; margin-top: 20px;" cellpadding="5px">
<div class="loginwindow_loginspace">
<table class="loginwindow_loginspace_controls">
<tr>
<td colspan="2" style="font-size: 18px;">Create your administrator account.</td>
<td colspan="2">
<h2>Create your administrator account</h2>
</td>
</tr>
<tr>
<th>Email</th>
<td><input type="email" id="login_email" style="width: 95%;" onkeyup="checkPasswordsMatch();" /></td>
<!-- <td>Email</td> -->
<td colspan="2"><input type="email" id="login_email" style="width: 95%;" placeholder="Email" />
</td>
</tr>
<tr>
<th>New Password</th>
<td><input type="password" id="login_password" style="width: 95%;" onkeyup="checkPasswordsMatch();" /></td>
<!-- <td>New Password</td> -->
<td colspan="2"><input type="password" id="login_password" style="width: 95%;"
placeholder="New Password" />
</td>
</tr>
<tr>
<th>Confirm Password</th>
<td><input type="password" id="login_confirmpassword" style="width: 95%;" onkeyup="checkPasswordsMatch();" /></td>
<!-- <td>Confirm Password</td> -->
<td colspan="2"><input type="password" id="login_confirmpassword" style="width: 95%;"
placeholder="Confirm Password" /></td>
</tr>
<tr>
<td colspan="2" id="login_passwordnotice">&nbsp;</td>
</tr>
<tr>
<td colspan="2" id="login_passworderrors" style="color: red;"></td>
<td colspan="2">
<p>Email requirements:</p>
<div id="email-error"></div>
<p>Password requirements:</p>
<div id="password-error"></div>
</td>
</tr>
<tr>
<td colspan="2" style="padding-top: 20px;">
<button id="login_createaccount" type="button" value="Create Account" onclick="registerAccount();" disabled="disabled" class="bigbutton">Create Account</button>
<button id="login_createaccount" type="submit" value="Create Account"
onclick="registerAccount();" disabled="disabled" class="bigbutton">Create
Account</button>
</td>
</tr>
</table>
</div>
</div>
</div>
</div>
<div id="settings_photocredit">
Wallpaper by <a href="https://unsplash.com/@spideyjoey" class="romlink">Joey Kwok</a> / <a href="https://unsplash.com/photos/a-room-filled-with-arcade-machines-and-neon-lights-jbIsTd7rdd8" class="romlink">Unsplash</a>
</div>
<!-- <div id="settings_photocredit">
Wallpaper by <a href="https://unsplash.com/@spideyjoey" class="romlink">Joey Kwok</a> / <a
href="https://unsplash.com/photos/a-room-filled-with-arcade-machines-and-neon-lights-jbIsTd7rdd8"
class="romlink">Unsplash</a>
</div> -->
<script type="text/javascript">
// redirect if first run status != 0 as 0 indicates that first run needs to be run
if (FirstRunStatus != 0) {
window.location.replace("/");
}
<script type="text/javascript">
function checkPasswordsMatch() {
var emailAddress = document.getElementById('login_email').value;
var newPassword = document.getElementById('login_password').value;
var conPassword = document.getElementById('login_confirmpassword').value;
var errorLabel = document.getElementById('login_passwordnotice');
var submitButton = document.getElementById('login_createaccount');
// make sure email address is valid
if (!emailAddress.includes("@")) {
errorLabel.innerHTML = "Please enter a valid email address";
submitButton.setAttribute('disabled', 'disabled');
} else {
if (newPassword == conPassword) {
// check if password meets requirements
if (newPassword.length >= 10) {
errorLabel.innerHTML = "&nbsp;";
submitButton.removeAttribute('disabled');
} else {
errorLabel.innerHTML = "Password should be at least 10 characters long";
submitButton.setAttribute('disabled', 'disabled');
}
} else {
errorLabel.innerHTML = "New and confirmed passwords do not match";
submitButton.setAttribute('disabled', 'disabled');
}
}
}
function registerAccount() {
var emailAddress = document.getElementById('login_email').value;
var newPassword = document.getElementById('login_password').value;
var conPassword = document.getElementById('login_confirmpassword').value;
var model = {
"userName": emailAddress,
"email": emailAddress,
"password": newPassword,
"confirmPassword": conPassword
};
ajaxCall(
'/api/v1.1/FirstSetup/0',
'POST',
function(result){
loginCallback(result);
},
function(error){
loginCallback(error);
},
JSON.stringify(model)
);
}
function loginCallback(result) {
var errorLabel = document.getElementById('login_passwordnotice');
var errorBox = document.getElementById('login_passworderrors');
errorBox.innerHTML = '';
console.log(result);
if (result.succeeded == false) {
for (var i = 0; i < result.errors.length; i++) {
var errorMessage = document.createElement('p');
errorMessage.innerHTML = result.errors[i].description;
errorBox.appendChild(errorMessage);
}
} else {
window.location.replace('/index.html');
}
}
</script>
</body>
</script>

View File

@@ -0,0 +1,81 @@
// Purpose: javascript for the first setup page
var EmailChecker;
var PasswordChecker;
function SetupPage() {
let emailInput = document.getElementById('login_email');
let emailError = document.getElementById('email-error');
let passwordInput = document.getElementById('login_password');
let confirmPasswordInput = document.getElementById('login_confirmpassword');
let passwordError = document.getElementById('password-error');
let submitButton = document.getElementById('login_createaccount');
EmailChecker = new EmailCheck(emailInput, emailError, true);
PasswordChecker = new PasswordCheck(passwordInput, confirmPasswordInput, passwordError);
emailInput.addEventListener('input', function () {
ValidateForm();
});
passwordInput.addEventListener('input', function () {
ValidateForm();
});
confirmPasswordInput.addEventListener('input', function () {
ValidateForm();
});
submitButton.addEventListener('click', async function () {
let model = {
"userName": emailInput.value,
"email": emailInput.value,
"password": passwordInput.value,
"confirmPassword": confirmPasswordInput.value
};
await fetch('/api/v1.1/FirstSetup/0', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(model)
}).then(response => {
if (response.ok) {
window.location.replace('/index.html');
} else {
response.json().then(data => {
passwordError.innerHTML = '';
data.errors.forEach(error => {
let errorMessage = document.createElement('p');
errorMessage.innerHTML = error.description;
passwordError.appendChild(errorMessage);
});
});
}
});
});
}
async function ValidateForm() {
let submitButton = document.getElementById('login_createaccount');
if (
await EmailCheck.CheckEmail(EmailChecker, EmailChecker.EmailElement) === true &&
PasswordCheck.CheckPasswords(PasswordChecker, PasswordChecker.NewPasswordElement, PasswordChecker.ConfirmPasswordElement) === true
) {
submitButton.removeAttribute('disabled');
} else {
submitButton.setAttribute('disabled', 'disabled');
}
}
SetupPage();
// load background images
backgroundImageHandler = new BackgroundImageRotator([
'/images/LoginWallpaper.jpg',
'/images/SettingsWallpaper.jpg',
'/images/CollectionsWallpaper.jpg',
'/images/gamebg1.jpg',
'/images/gamebg2.jpg',
'/images/gamebg3.jpg'
], 'bgImage_LessBlur', true);

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,51 +1,10 @@
<div id="bgImage" style="background-image: url('/images/librarybg.jpg'); background-position: center; background-repeat: no-repeat; background-size: cover; filter: blur(10px); -webkit-filter: blur(10px);">
<div id="bgImage_Opacity"></div>
</div>
<div id="gamepage">
<div style="padding-top: 20px;">
<div id="gamehome" style="display: inline-block; max-width: 820px; margin-right: 20px; vertical-align: top;">
<div id="games_filter_scroller">
</div>
<div id="games_home">
<div id="games_home_box">
<div id="games_library_controls">
<div class="games_library_controlblock">
<span class="games_library_label">Order by: </span>
</div>
<div id="games_library_orderby" class="games_library_controlblock" style="text-align: left;">
<select id="games_library_orderby_select" data-minimum-results-for-search="Infinity" onchange="executeFilter1_1(1);">
<option selected="selected" value="NameThe">Name, The</option>
<option value="Name">Name</option>
<option value="Rating">User Rating</option>
<option value="RatingCount">User Rating Count</option>
</select>
<select id="games_library_orderby_direction_select" data-minimum-results-for-search="Infinity" onchange="executeFilter1_1(1);">
<option selected="selected" value="Ascending">Ascending</option>
<option value="Descending">Descending</option>
</select>
</div>
<div class="games_library_controlblock">
<span id="games_library_recordcount" class="games_library_label"></span>
</div>
</div>
<div id="games_library"></div>
<div id="games_library_alpha_box">
<div id="games_library_alpha_pager"></div>
<div id="gameprofile" style="display: inline-block; width: 250px;">
</div>
<div id="games_library_pagerstore" style="display: none;">0</div>
</div>
</div>
<div id="games_pager" style="display: none;">
&lt; 1 2 3 4 5 &gt;
</div>
<script type="text/javascript">
ajaxCall('/api/v1.1/Filter', 'GET', function (result) {
var scrollerElement = document.getElementById('games_filter_scroller');
formatFilterPanel(scrollerElement, result);
//executeFilter1_1();
});
$('#games_library_orderby_select').select2();
$('#games_library_orderby_direction_select').select2();
</script>
</div>

View File

@@ -0,0 +1,204 @@
class HomePageGameRow {
constructor(title, searchModel) {
this.title = title;
this.searchModel = searchModel;
// Create the row
this.row = document.createElement("div");
this.row.classList.add("section");
let titleHeader = document.createElement("div");
titleHeader.classList.add("section-header");
titleHeader.textContent = this.title;
this.row.appendChild(titleHeader);
this.games = document.createElement("div");
this.games.classList.add("section-body");
this.games.innerHTML = "<p>Loading...</p>";
this.row.appendChild(this.games);
// this.populate();
}
async populate() {
// get preferences
let showRatings = GetPreference("LibraryShowGameRating", true);
let showClassification = GetPreference("LibraryShowGameClassification", true);
let classificationDisplayOrder = GetRatingsBoards();
if (showRatings == "true") { showRatings = true; } else { showRatings = false; }
if (showClassification == "true") { showClassification = true; } else { showClassification = false; }
showRatings = false;
showClassification = false;
// get the games
let gamesCallURL = '/api/v1.1/Games?pageNumber=1&pageSize=20';
await fetch(gamesCallURL, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(this.searchModel)
})
.then(response => response.json())
.then(data => {
this.games.innerHTML = "";
this.gamesResponse = data;
if (data.games.length == 0) {
this.games.innerHTML = "<p>No games found</p>";
} else {
let scroller = document.createElement("ul");
scroller.classList.add("homegame-scroller");
for (let game of data.games) {
let gameItem = document.createElement("li");
gameItem.classList.add("homegame-item");
let gameIcon = renderGameIcon(game, true, showRatings, showClassification, classificationDisplayOrder, true, false);
gameItem.appendChild(gameIcon);
scroller.appendChild(gameItem);
}
this.games.appendChild(scroller);
$('.lazy').Lazy({
effect: 'fadeIn',
effectTime: 500,
visibleOnly: true,
defaultImage: '/images/unknowngame.png',
delay: 250,
enableThrottle: true,
throttle: 250,
afterLoad: function (element) {
//console.log(element[0].getAttribute('data-id'));
}
});
}
});
}
}
let targetDiv = document.getElementById("gamehome");
let gameRows = [];
gameRows.push(new HomePageGameRow("Favourites",
{
"Name": "",
"HasSavedGame": false,
"isFavourite": true,
"Platform": [],
"Genre": [],
"GameMode": [],
"PlayerPerspective": [],
"Theme": [],
"MinimumReleaseYear": -1,
"MaximumReleaseYear": -1,
"GameRating": {
"MinimumRating": -1,
"MinimumRatingCount": -1,
"MaximumRating": -1,
"MaximumRatingCount": -1,
"IncludeUnrated": false
},
"GameAgeRating": {
"AgeGroupings": [],
"IncludeUnrated": false
},
"Sorting": {
"SortBy": "NameThe",
"SortAscending": true
}
}
));
gameRows.push(new HomePageGameRow("Saved Games",
{
"Name": "",
"HasSavedGame": true,
"isFavourite": false,
"Platform": [],
"Genre": [],
"GameMode": [],
"PlayerPerspective": [],
"Theme": [],
"MinimumReleaseYear": -1,
"MaximumReleaseYear": -1,
"GameRating": {
"MinimumRating": -1,
"MinimumRatingCount": -1,
"MaximumRating": -1,
"MaximumRatingCount": -1,
"IncludeUnrated": false
},
"GameAgeRating": {
"AgeGroupings": [],
"IncludeUnrated": false
},
"Sorting": {
"SortBy": "NameThe",
"SortAscending": true
}
}
));
gameRows.push(new HomePageGameRow("Top Rated Games",
{
"Name": "",
"HasSavedGame": false,
"isFavourite": false,
"Platform": [],
"Genre": [],
"GameMode": [],
"PlayerPerspective": [],
"Theme": [],
"MinimumReleaseYear": -1,
"MaximumReleaseYear": -1,
"GameRating": {
"MinimumRating": -1,
"MinimumRatingCount": -1,
"MaximumRating": -1,
"MaximumRatingCount": -1,
"IncludeUnrated": false
},
"GameAgeRating": {
"AgeGroupings": [],
"IncludeUnrated": false
},
"Sorting": {
"SortBy": "Rating",
"SortAscending": false
}
}
));
async function populateRows() {
// start populating the rows
let coverURLList = [];
for (let row of gameRows) {
targetDiv.appendChild(row.row);
await row.populate();
console.log(row.gamesResponse);
// collect the cover URLs
for (let game of row.gamesResponse.games) {
if (game.cover) {
if (game.cover.id) {
let coverUrl = '/api/v1.1/Games/' + game.id + '/cover/' + game.cover.id + '/image/cover_big/' + game.cover.id + '.jpg';
if (!coverURLList.includes(coverUrl)) {
coverURLList.push(coverUrl);
}
}
}
}
}
backgroundImageHandler = new BackgroundImageRotator(coverURLList, null, true);
}
populateRows();
let profileDiv = document.getElementById("gameprofile");
profileDiv.innerHTML = "";
let profileCardContent = new ProfileCard(userProfile.profileId, false);
profileDiv.appendChild(profileCardContent);

View File

@@ -0,0 +1,81 @@
<div id="games_filter_scroller">
</div>
<div id="games_home">
<div id="games_home_box">
<div id="games_library_controls">
<div id="games_library_button_pagedview" class="games_library_button"
onclick="document.getElementById('games_library').innerHTML = ''; SetPreference('LibraryPagination', 'paged', executeFilter1_1(1));">
<img src="/images/viewpaged.svg" alt="Paged View" title="Paged View"
class="games_library_button_icon" />
</div>
<div id="games_library_button_infiniteview" class="games_library_button"
onclick="document.getElementById('games_library').innerHTML = ''; SetPreference('LibraryPagination', 'infinite', executeFilter1_1(1));">
<img src="/images/viewinfinite.svg" alt="Continuous View" title="Continuous View"
class="games_library_button_icon" />
</div>
<!-- list or icon view - true for list view, false for icon view -->
<div id="games_library_button_iconview" class="games_library_button"
onclick="document.getElementById('games_library').innerHTML = ''; SetPreference('LibraryListView', false, executeFilter1_1(1));">
<img src="/images/viewicon.svg" alt="Cover View" title="Cover View" class="games_library_button_icon" />
</div>
<div id="games_library_button_listview" class="games_library_button"
onclick="document.getElementById('games_library').innerHTML = ''; SetPreference('LibraryListView', true, executeFilter1_1(1));">
<img src="/images/viewlist.svg" alt="List View" title="List View" class="games_library_button_icon" />
</div>
<div class="games_library_controlblock">
<span class="games_library_label">Page size: </span>
</div>
<div id="games_library_pagesize" class="games_library_controlblock" style="text-align: left;">
<select id="games_library_pagesize_select" data-minimum-results-for-search="Infinity"
onchange="document.getElementById('games_library').innerHTML = ''; SetPreference('LibraryPageSize', $(this).val(), executeFilter1_1(1));">
<option selected="selected" value="20">20</option>
<option value="30">30</option>
<option value="40">40</option>
<option value="50">50</option>
<option value="60">60</option>
<option value="70">70</option>
<option value="80">80</option>
<option value="90">90</option>
<option value="100">100</option>
</select>
</div>
<div class="games_library_controlblock">
<span class="games_library_label">Order by: </span>
</div>
<div id="games_library_orderby" class="games_library_controlblock" style="text-align: left;">
<select id="games_library_orderby_select" data-minimum-results-for-search="Infinity"
onchange="document.getElementById('games_library').innerHTML = ''; SetPreference('LibraryOrderBy', $(this).val(), executeFilter1_1(1));">
<option selected="selected" value="NameThe">Name, The</option>
<option value="Name">Name</option>
<option value="Rating">User Rating</option>
<option value="RatingCount">User Rating Count</option>
</select>
<select id="games_library_orderby_direction_select" data-minimum-results-for-search="Infinity"
onchange="document.getElementById('games_library').innerHTML = ''; SetPreference('LibraryOrderByDirection', $(this).val(), executeFilter1_1(1));">
<option selected="selected" value="Ascending">Ascending</option>
<option value="Descending">Descending</option>
</select>
</div>
<div class="games_library_controlblock">
<span id="games_library_recordcount" class="games_library_label"></span>
</div>
</div>
<div id="games_library"></div>
<div id="games_library_alpha_box">
<div id="games_library_alpha_pager"></div>
</div>
<div id="games_library_pagerstore" style="display: none;">0</div>
</div>
</div>
<div id="games_pager" style="display: none;">
&lt; 1 2 3 4 5 &gt;
</div>
<script type="text/javascript">
// Setup the page
SetupPage();
</script>

View File

@@ -0,0 +1,19 @@
function SetupPage() {
// setup view controls
$('#games_library_pagesize_select').select2();
$('#games_library_orderby_select').select2();
$('#games_library_orderby_direction_select').select2();
// setup scroll event
$(window).scroll(IsInView);
// setup filter panel
ajaxCall('/api/v1.1/Filter', 'GET', function (result) {
var scrollerElement = document.getElementById('games_filter_scroller');
formatFilterPanel(scrollerElement, result);
//executeFilter1_1();
});
}
SetupPage();

View File

@@ -1,132 +1,83 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<script src="/api/v1.1/System/VersionFile"></script>
<link type="text/css" rel="stylesheet" dat-href="/styles/style.css" />
<script src="/scripts/jquery-3.6.0.min.js"></script>
<script src="/scripts/moment.js"></script>
<link href="/styles/select2.min.css" rel="stylesheet" />
<link href="/styles/dropzone.min.css" rel="stylesheet" type="text/css" />
<script src="/scripts/jquery.lazy.min.js"></script>
<script src="/scripts/jquery.lazy.plugins.min.js"></script>
<script src="/scripts/select2.min.js"></script>
<script src="/scripts/dropzone.min.js"></script>
<script src="/scripts/simpleUpload.min.js"></script>
<script src="/scripts/main.js" type="text/javascript"></script>
<script src="/scripts/filterformating.js" type="text/javascript"></script>
<script src="/scripts/gamesformating.js" type="text/javascript"></script>
<link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png">
<link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png">
<link rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png">
<link rel="manifest" href="/site.webmanifest">
<title>Gaseous Games</title>
<div class="modal-background">
<div class="modal-window"
style="width: 600px; height: 300px; min-height: unset; min-width: unset; max-height: unset; max-width: unset;">
<div id="loginform" class="loginwindow-content">
<div class="loginwindow-logospace">
<div class="loginwindow-logospace-banner loginwindow-logospace-banner-top">
<div class="loginwindow-logospace-logo">&nbsp;</div>
<div class="loginwindow-logospace-label">
<div>
Gaseous Games
</div>
</div>
</div>
<div class="loginwindow-logospace-banner loginwindow-logospace-banner-bottom">
<div class="loginwindow-logospace-linktable">
<div class="loginwindow-logospace-linktable-link">
<a href="https://github.com/gaseous-project/gaseous-server"
class="romlink romlink-nounderline">
<img src="/images/github-mark.svg" class="banner_button_image" />
GitHub
</a>
</div>
<div class="loginwindow-logospace-linktable-link">
<a href="https://discord.gg/Nhu7wpT3k4" class="romlink romlink-nounderline">
<img src="/images/discord.svg" class="banner_button_image" />
Discord
</a>
</div>
</div>
</div>
</div>
<script type="text/javascript">
var head = document.getElementsByTagName('head')[0];
// update links
var headLinks = document.getElementsByTagName('link');
for (var i = 0; i < headLinks.length; i++) {
if (headLinks[i].getAttribute('dat-href') && headLinks[i].rel == "stylesheet") {
var newLink = document.createElement('link');
newLink.rel = "stylesheet";
newLink.href = headLinks[i].getAttribute('dat-href') + '?v=' + AppVersion;
newLink.type = "text/css";
headLinks[i].parentElement.removeChild(headLinks[i]);
head.appendChild(newLink);
}
}
</script>
</head>
<body>
<div id="bgImage" style="background-image: url('/images/LoginWallpaper.jpg'); background-position: center; background-repeat: no-repeat; background-size: cover; filter: blur(10px); -webkit-filter: blur(10px);">
<div id="bgImage_Opacity"></div>
</div>
<div id="content">
<div class="loginwindow">
<div id="loginform" class="loginwindow-content">
<img src="/images/logo.png" style="display: block; margin: 20px auto; width: 100px;" />
<div id="loginwindow_header_label" style="display: block; text-align: center;">Gaseous Games</div>
<table style="width: 100%; margin-top: 20px;" cellpadding="5px">
<tr>
<th>Email</th>
<td><input type="email" id="login_email" style="width: 95%;" /></td>
</tr>
<tr>
<th>Password</th>
<td><input type="password" id="login_password" style="width: 95%;" /></td>
</tr>
<tr>
<td colspan="2">
<input type="checkbox" id="login_rememberme"> <label for="login_rememberme">Remember Me</label>
</td>
</tr>
<tr>
<td colspan="2" id="login_errorlabel" style="color: red;"></td>
</tr>
<tr>
<td colspan="2" style="padding-top: 20px;">
<button type="button" value="Sign In" onclick="UserLogin();" class="bigbutton">Sign In</button>
</td>
</tr>
</table>
<div class="loginwindow_loginspace">
<form id="loginform" action="javascript:void;" onsubmit="UserLogin();">
<table class="loginwindow_loginspace_controls">
<tr>
<td colspan="2" style="text-align: center;">
<h2>Sign In</h2>
</td>
</tr>
<tr>
<!-- <td>Email</td> -->
<td colspan="2"><input type="email" id="login_email" style="width: 95%;"
placeholder="Email" />
</td>
</tr>
<tr>
<!-- <td>Password</td> -->
<td colspan="2"><input type="password" id="login_password" style="width: 95%;"
placeholder="Password" /></td>
</tr>
<!-- <tr>
<td colspan="2">
<input type="checkbox" id="login_rememberme"> <label for="login_rememberme">Remember
Me</label>
</td>
</tr> -->
<tr id="login_errorrow" style="display: none;">
<td colspan="2" id="login_errorlabel" style="color: red;"></td>
</tr>
<tr>
<td colspan="2">
<button type="submit" value="Sign In" onclick="UserLogin();" name="submit"
class="bigbutton">Sign
In</button>
</td>
</tr>
</table>
</form>
</div>
</div>
</div>
</div>
<!--
<div id="settings_photocredit">
Wallpaper by <a href="https://unsplash.com/@spideyjoey" class="romlink">Joey Kwok</a> / <a
href="https://unsplash.com/photos/a-room-filled-with-arcade-machines-and-neon-lights-jbIsTd7rdd8"
class="romlink">Unsplash</a>
</div> -->
<div id="settings_photocredit">
Wallpaper by <a href="https://unsplash.com/@spideyjoey" class="romlink">Joey Kwok</a> / <a href="https://unsplash.com/photos/a-room-filled-with-arcade-machines-and-neon-lights-jbIsTd7rdd8" class="romlink">Unsplash</a>
</div>
<script type="text/javascript">
<script type="text/javascript">
// redirect if logged in
ajaxCall(
'/api/v1.1/Account/Profile/Basic',
'GET',
function(result) {
// user is signed in - redirect to main page
window.location.replace("/");
},
function(error) {
// user is not signed in - do nothing
}
);
function UserLogin() {
var loginObj = {
"email": document.getElementById('login_email').value,
"password": document.getElementById('login_password').value,
"rememberMe": document.getElementById('login_rememberme').checked
}
ajaxCall(
'/api/v1.1/Account/Login',
'POST',
function(result) {
loginCallback(result);
},
function(error) {
loginCallback(error);
},
JSON.stringify(loginObj)
);
function loginCallback(result) {
switch(result.status) {
case 200:
window.location.replace('/index.html');
break;
default:
// login failed
document.getElementById('login_errorlabel').innerHTML = 'Incorrect password';
break;
}
}
}
</script>
</body>
</script>

View File

@@ -0,0 +1,47 @@
function UserLogin() {
// let loginObj = {
// "email": document.getElementById('login_email').value,
// "password": document.getElementById('login_password').value,
// "rememberMe": document.getElementById('login_rememberme').checked
// }
let loginObj = {
"email": document.getElementById('login_email').value,
"password": document.getElementById('login_password').value,
"rememberMe": true
}
ajaxCall(
'/api/v1.1/Account/Login',
'POST',
function (result) {
loginCallback(result);
},
function (error) {
loginCallback(error);
},
JSON.stringify(loginObj)
);
function loginCallback(result) {
switch (result.status) {
case 200:
window.location.replace('/index.html');
break;
default:
// login failed
document.getElementById('login_errorrow').style.display = '';
document.getElementById('login_errorlabel').innerHTML = 'Incorrect password';
break;
}
}
}
// load background images
backgroundImageHandler = new BackgroundImageRotator([
'/images/LoginWallpaper.jpg',
'/images/SettingsWallpaper.jpg',
'/images/CollectionsWallpaper.jpg',
'/images/gamebg1.jpg',
'/images/gamebg2.jpg',
'/images/gamebg3.jpg'
], 'bgImage_LessBlur', true);

View File

@@ -0,0 +1,64 @@
<div id="tab1" name="modalTab" data-tabname="Profile">
<div style=" display: flex; gap: 10px;">
<div style="flex-grow:1">
<div class="section">
<div class="section-header">Avatar</div>
<div class="section-body" style="text-align: center;">
<div id="avatar-preview" class="avatar"
style="width: 100px; height: 100px; border-radius: 50%; background-size: cover; background-position: center; margin: auto; font-size: 3vmax; display: flex; justify-content: center; align-items: center; margin-bottom: 10px;">
</div>
<input type="file" id="avatar-upload" name="avatar" accept="image/*" />
<button id="avatar-upload-clear" class="button">Clear</button>
</div>
</div>
<div class="section">
<div class="section-header">Background</div>
<div class="section-body" style="text-align: center;">
<div id="background-preview" class="profile-card-background-image"
style="width: 300px; margin: auto; border-radius: var(--standard-radius); margin-bottom: 10px;">
</div>
<input type="file" id="background-upload" name="background" accept="image/*" />
<button id="background-upload-clear" class="button">Clear</button>
</div>
</div>
</div>
<div style="flex-grow:1">
<div class="section">
<div class="section-header">Name</div>
<div class="section-body">
<div>Display Name</div>
<input type="text" id="display-name" name="name" style="width: 90%;"
class="inputWithVerticalLabel" />
<div>Quip</div>
<textarea id="quip" class="inputWithVerticalLabel" name="quip" style="width: 90%;"></textarea>
</div>
</div>
</div>
</div>
</div>
<div id="tab2" name="modalTab" data-tabname="Password">
<div class="section">
<div class="section-header">Change Password</div>
<div class="section-body">
<div style="display: flex; gap: 10px;">
<div style="flex-grow:1">
<div>Current Password</div>
<input type="password" id="current-password" name="current-password" style="width: 95%;"
class="inputWithVerticalLabel" />
<div>New Password</div>
<input type="password" id="new-password" name="new-password" style="width: 95%;"
class="inputWithVerticalLabel" />
<div>Confirm New Password</div>
<input type="password" id="confirm-new-password" name="confirm-new-password" style="width: 95%;"
class="inputWithVerticalLabel" />
</div>
<div style="flex-grow:1">
<p>Password requirements:</p>
<div id="password-error"></div>
</div>
</div>
</div>
</div>
</div>

View File

@@ -0,0 +1,2 @@
<div id="bios_editor"></div>
<button id="mapping_edit_bios_add" class="button">Add BIOS/Firmware</button>

View File

@@ -0,0 +1,14 @@
<div style="display: flex; gap: 10px;">
<div class="section" style="flex-grow: 1;">
<div class="section-header">Saved States</div>
<div id="saved_states" class="section-body">
</div>
</div>
<div class="section" style="flex-grow: 0; width: 25%;">
<div class="section-header">Upload State</div>
<div class="section-body">
<input type="file" id="stateFile" />
</div>
</div>
</div>

View File

@@ -0,0 +1,6 @@
<ul id="fileSelector">
</ul>
<div id="selectedPath">
</div>

View File

@@ -0,0 +1,39 @@
<div id="gamesummarymediagroups" class="section" style="display: none;">
<div class="section-header">Media Groups</div>
<div id="gamesummarymediagroupscontent" class="section-body"></div>
</div>
<div id="gamesummaryroms" class="section">
<span id="rom_edit" class="romlink">Edit</span>
<div class="section-header">ROMs/Images</div>
<div class="section-body">
<div id="rom_edit_panel" style="display: none;">
<div id="rom_edit_panel_center">
<button id="rom_edit_delete" class="redbutton">Delete</button>
<select id="rom_edit_fixplatform" style="width: 150px;"></select>
<select id="rom_edit_fixgame" style="width: 300px;"></select>
<button id="rom_edit_update">Update</button>
<button id="rom_edit_creategroup" disabled="disabled">Create
Media
Group</button>
</div>
</div>
<div id="rom_library_controls">
<div class="games_library_controlblock">
<input id="name_filter" type="text" placeholder="Name Search">
</div>
<div class="games_library_controlblock">
<button id="games_library_search" value="Search">Search</button>
</div>
<div class="games_library_controlblock">
<span id="games_roms_count" class="games_library_label">0 ROMs</span>
</div>
</div>
<div id="gamesummaryromscontent"></div>
</div>
</div>
<div class="section" id="rom_no_roms" style="display: none;">
<div class="section-body">
There are no ROMs associated with this game and platform.
</div>
</div>

View File

@@ -0,0 +1,67 @@
<div id="tab1" name="modalTab" data-tabname="General">
<div class="section">
<div class="section-header">Title Matching</div>
<div class="section-body">
<table style="width: 100%;">
<tr>
<td style="width: 25%; vertical-align: top;">
<h4>Alternative Names</h4>
</td>
<td>
<select id="mapping_edit_alternativenames" multiple="multiple" style="width: 100%;"></select>
</td>
</tr>
<tr>
<td style="width: 25%; vertical-align: top;">
<h4>Supported File Extensions</h4>
</td>
<td>
<select id="mapping_edit_supportedfileextensions" multiple="multiple"
style="width: 100%;"></select>
</td>
</tr>
</table>
</div>
</div>
<div class="section">
<div class="section-header">Collections</div>
<div class="section-body">
<table style="width: 100%;">
<tr>
<td style="width: 25%;">
<h4>Standard Directory Naming</h4>
</td>
<td style="text-align: right;">
<input id="mapping_edit_igdbslug" readonly="readonly" type="text" style="width: 98%;" />
</td>
</tr>
<tr>
<td></td>
<td><strong>Note</strong>: Standard directory naming uses the IGDB slug for the platform
and is not
editable.</td>
</tr>
<tr>
<td>
<h4>RetroPie Directory Naming</h4>
</td>
<td style="text-align: right;">
<input id="mapping_edit_retropie" type="text" style="width: 98%;" />
</td>
</tr>
</table>
</div>
</div>
</div>
<div id="mapping_edit_webemulator" name="modalTab" data-tabname="Emulator">
</div>
<!-- <div id="tab3" name="modalTab" data-tabname="BIOS/Firmware">
<div id="webemulator_bios_editor">
</div>
<button id="mapping_edit_bios_add" class="button">Add BIOS/Firmware</button>
</div> -->

View File

@@ -0,0 +1 @@
<span id="messageText"></span>

View File

@@ -0,0 +1,19 @@
<div id="modal-header" class="modal-window-header">
<span id="modal-close-button" class="modal-window-close">&times;</span>
<span id="modal-header-text">The quick brown fox jumped over the lazy dog and impaled himself on a rusty
spoon</span>
</div>
<div id="modal-footer" class="modal-window-footer">
</div>
<div class="modal-window-inner-content">
<div id="modal-tabs" class="modal-window-tabs">
</div>
<div id="modal-body" class="modal-window-body">
<div id="modal-window-content" class="modal-window-content"></div>
</div>
</div>

View File

@@ -0,0 +1,28 @@
<table style="width: 100%;">
<tr>
<td style="width: 25%;">
Name:
</td>
<td>
<input type="text" id="librarynew_name" style="width: 98%;" />
</td>
</tr>
<tr>
<td>
Path:
</td>
<td>
<input type="text" id="librarynew_path" style="width: 80%;" /><button id="librarynew_pathSelect"
style="margin-left: 15px;">...</button>
</td>
</tr>
<tr>
<td>
Default Platform:
</td>
<td>
<select id="librarynew_defaultPlatformId" style="width: 100%;">
</select>
</td>
</tr>
</table>

View File

@@ -0,0 +1,112 @@
<div id="tab1" name="modalTab" data-tabname="General">
<div class="section">
<div class="section-header">General</div>
<div class="section-body">
<table style="width: 100%;">
<tr>
<td style="width: 25%;">
Default home page:
</td>
<td>
<select id="profile_pref_DefaultHomePage" data-pref="DefaultHomePage"
data-minimum-results-for-search="Infinity">
<option value="home">Home</option>
<option value="library">Library</option>
</select>
</td>
</tr>
</table>
</div>
</div>
<div class="section">
<div class="section-header">Library</div>
<div class="section-body">
<table style="width: 100%;">
<tr>
<td style="width: 25%;">
Pagination mode:
</td>
<td>
<select id="profile_pref-LibraryPagination" data-pref="LibraryPagination"
data-minimum-results-for-search="Infinity">
<option value="paged">Paged</option>
<option value="infinite">Infinite scrolling</option>
</select>
</td>
</tr>
<tr>
<td>
View mode:
</td>
<td>
<select id="profile_pref-LibraryListView" data-pref="LibraryListView"
data-minimum-results-for-search="Infinity">
<option value="false">Icon</option>
<option value="true">List</option>
</select>
</td>
</tr>
</table>
</div>
</div>
<div class="section">
<div class="section-header">Game Icons</div>
<div class="section-body">
<table style="width: 100%;">
<tr>
<td>
<input type="checkbox" id="profile_pref_LibraryShowGameTitle"
data-pref="LibraryShowGameTitle"><label for="profile_pref_LibraryShowGameTitle"> Show
title</label>
</td>
</tr>
<tr>
<td>
<input type="checkbox" id="profile_pref_LibraryShowGameRating"
data-pref="LibraryShowGameRating"><label for="profile_pref_LibraryShowGameRating"> Show
rating</label>
</td>
</tr>
<tr>
<td>
<input type="checkbox" id="profile_pref_LibraryShowGameClassification"
data-pref="LibraryShowGameClassification"><label
for="profile_pref_LibraryShowGameClassification">
Show
age classification badges</label>
</td>
</tr>
</table>
</div>
</div>
</div>
<div id="tab2" name="modalTab" data-tabname="Localisation">
<div class="section">
<div class="section-header">Age Classification</div>
<div class="section-body">
<table id="profile_pref_LibraryClassificationBadgeSelect" style="width: 100%;">
<tr>
<td>Classification badge fallback order:</td>
</tr>
<tr>
<td>
<div id="classificationBoardSelector" class="listboxselector">
</div>
</td>
</tr>
<tr>
<td style="text-align: right;">
<div id="classificationBoardSelector-Up" class="listboxselector-arrow">
<img src="/images/arrow-up.svg" class="gamescreenshots_arrow_image">
</div>
<div id="classificationBoardSelector-Down" class="listboxselector-arrow">
<img src="/images/arrow-down.svg" class="gamescreenshots_arrow_image">
</div>
</td>
</tr>
</table>
</div>
</div>
</div>

View File

@@ -0,0 +1,134 @@
<div id="tab1" name="modalTab" data-tabname="ROM Info">
<table cellspacing="0" style="width: 100%;">
<tr class="romrow">
<th class="romcell">Library</td>
<td id="rominfo_library" class="romcell"></td>
</tr>
<tr class="romrow">
<th class="romcell">Platform</td>
<td id="rominfo_platform" class="romcell"></td>
</tr>
<tr class="romrow">
<th class="romcell">Size</td>
<td id="rominfo_size" class="romcell"></td>
</tr>
<tr class="romrow">
<th class="romcell">ROM Type</td>
<td id="rominfo_type" class="romcell"></td>
</tr>
<tr class="romrow">
<th class="romcell">Media Type</td>
<td id="rominfo_mediatype" class="romcell"></td>
</tr>
<tr class="romrow">
<th class="romcell">Media Label</td>
<td id="rominfo_medialabel" class="romcell"></td>
</tr>
<tr class="romrow">
<th class="romcell">MD5</td>
<td id="rominfo_md5" class="romcell"></td>
</tr>
<tr class="romrow">
<th class="romcell">SHA1</td>
<td id="rominfo_sha1" class="romcell"></td>
</tr>
<tr class="romrow">
<th class="romcell">Signature Matched From</td>
<td id="rominfo_signaturematch" class="romcell"></td>
</tr>
<tr class="romrow">
<th class="romcell">Signature Game Title</td>
<td id="rominfo_signaturetitle" class="romcell"></td>
</tr>
<tr class="romrow">
<th class="romcell">ROM Attributes</td>
<td id="rominfo_signatureattributes" class="romcell"></td>
</table>
</div>
<div id="tab2" name="modalTab" data-tabname="Archive Content">
</div>
<div id="tab3" name="modalTab" data-tabname="Title Matching">
<table cellspacing="0" style="width: 100%;">
<!-- <tbody class="romrow">
<tr>
<th class="romcell" style="width: 25%;">Signature Match</th>
<td class="romcell"></td>
</tr>
</tbody> -->
<tbody class="romrow">
<tr>
<th class="romcell">Preferred Metadata Source</th>
<td class="romcell">
<table cellspacing="0" style="display: 100%;">
<tr>
<td style="width: 30px;">
<input type="radio" id="rominfo_metadata_source_none" name="rominfo_metadata_source"
value="0" disabled="disabled">
</td>
<td>
<label for="rominfo_metadata_source_none">None</label>
</td>
</tr>
<tr>
<td style="width: 30px;">
<input type="radio" id="rominfo_metadata_source_igdb" name="rominfo_metadata_source"
value="1" checked="checked">
</td>
<td>
<label for="rominfo_metadata_source_igdb">IGDB</label>
</td>
</tr>
</table>
</td>
</tr>
</tbody>
<tbody class="romrow">
<tr>
<th class="romcell">Internet Game Database Match</th>
<td class="romcell">
<table cellspacing="0" style="width: 100%;">
<tr>
<td style="width: 30px;">
<input type="radio" id="rominfo_metadata_match_none" name="rominfo_metadata_match"
value="0" checked>
</td>
<td colspan="2">
<label for="rominfo_metadata_match_none">None</label>
</td>
</tr>
<tr>
<td style="width: 30px;">
<input type="radio" id="rominfo_metadata_match_match" name="rominfo_metadata_match"
value="1">
</td>
<td colspan="2">
<label for="rominfo_metadata_match_match">Matched to:</label>
</td>
</tr>
<tr>
<td></td>
<td style="width: 100px;">
Platform:
</td>
<td>
<select id="properties_fixplatform" style="width: 100%;"></select>
</td>
</tr>
<tr>
<td></td>
<td>
Game:
</td>
<td>
<select id="properties_fixgame" style="width: 100%;"></select>
</td>
</tr>
</table>
</td>
</tr>
</tbody>
</table>
</div>

View File

@@ -0,0 +1,17 @@
<div class="section">
<div class="section-header">Upload</div>
<div class="section-body">
<div id="upload_target">
<div style="display: block;">Upload ROMs by dragging and dropping them here, or by clicking here.</div>
</div>
</div>
</div>
<div class="section">
<div class="section-header">Uploaded ROMs</div>
<div class="section-body">
<div id="uploaded_roms">
<div id="uploaded_roms_emptylabel" style="display: block;">No ROMs uploaded.</div>
</div>
</div>
</div>

View File

@@ -0,0 +1,346 @@
<div id="tab4" name="modalTab" data-tabname="General">
<div style="display: flex; gap: 10px; width: 100%;">
<div class="section" style="flex-grow:1;">
<div class="section-header">General</div>
<div class="section-body">
<table class="romtable">
<tr class="romrow">
<th class="romcell">User Id</th>
<td id="user-id" class="romcell"></td>
</tr>
<tr class="romrow">
<th class="romcell">Account lockout</th>
<td id="user-lockedout" class="romcell"></td>
</tr>
<tr class="romrow">
<th class="romcell">Account lockout ends</th>
<td id="user-lockedout-end" class="romcell"></td>
</tr>
</table>
</div>
</div>
<div id="user-profile-card" style="flex-grow:0;"></div>
</div>
</div>
<div id="tab2" name="modalTab" data-tabname="Permissions">
<div style="display: flex; gap: 10px;">
<div class="section" style="flex-grow:1;">
<div class="section-header">User Role</div>
<div class="section-body">
<table cellspacing="0">
<tr>
<td>
<input type="radio" name="settings_user_role" id="settings_user_role_player" value="Player">
<label for="settings_user_role_player">Player</label>
</td>
</tr>
<tr>
<td>
<input type="radio" name="settings_user_role" id="settings_user_role_gamer" value="Gamer">
<label for="settings_user_role_gamer">Gamer</label>
</td>
</tr>
<tr>
<td>
<input type="radio" name="settings_user_role" id="settings_user_role_admin" value="Admin">
<label for="settings_user_role_admin">Administrator</label>
</td>
</tr>
</table>
</div>
</div>
<div style="flex-grow:1">
<div class="section">
<div class="section-header">Assigned Permissions</div>
<div class="section-body">
<div class="role-permissions">
<div id="role-permissions-table" class="role-permissions-table collapsed">
<table style="width: 100%;" class="romtable" cellspacing="0">
<tr>
<th colspan="2">
Games and ROMs
</th>
</tr>
<tr class="romrow">
<td class="romcell">Play games</td>
<td class="romcell" name="role-player">
<div class="listitem listitem-green"></div>
</td>
<td class="romcell" name="role-gamer">
<div class="listitem listitem-green"></div>
</td>
<td class="romcell" name="role-admin">
<div class="listitem listitem-green"></div>
</td>
</tr>
<tr class="romrow">
<td class="romcell">Download ROM images</td>
<td class="romcell" name="role-player">
<div class="listitem listitem-green"></div>
</td>
<td class="romcell" name="role-gamer">
<div class="listitem listitem-green"></div>
</td>
<td class="romcell" name="role-admin">
<div class="listitem listitem-green"></div>
</td>
</tr>
<tr class="romrow">
<td class="romcell">Upload ROM images</td>
<td class="romcell" name="role-player">
<div class="listitem listitem-red"></div>
</td>
<td class="romcell" name="role-gamer">
<div class="listitem listitem-green"></div>
</td>
<td class="romcell" name="role-admin">
<div class="listitem listitem-green"></div>
</td>
</tr>
<tr class="romrow">
<td class="romcell">Create and delete multidisk packages</td>
<td class="romcell" name="role-player">
<div class="listitem listitem-red"></div>
</td>
<td class="romcell" name="role-gamer">
<div class="listitem listitem-green"></div>
</td>
<td class="romcell" name="role-admin">
<div class="listitem listitem-green"></div>
</td>
</tr>
<tr class="romrow">
<td class="romcell">Delete ROM images</td>
<td class="romcell" name="role-player">
<div class="listitem listitem-red"></div>
</td>
<td class="romcell" name="role-gamer">
<div class="listitem listitem-green"></div>
</td>
<td class="romcell" name="role-admin">
<div class="listitem listitem-green"></div>
</td>
</tr>
<tr class="romrow">
<td class="romcell">Fix ROM image matches</td>
<td class="romcell" name="role-player">
<div class="listitem listitem-red"></div>
</td>
<td class="romcell" name="role-gamer">
<div class="listitem listitem-green"></div>
</td>
<td class="romcell" name="role-admin">
<div class="listitem listitem-green"></div>
</td>
</tr>
<tr>
<th colspan="2">
Collections
</th>
</tr>
<tr class="romrow">
<td class="romcell">Download packages</td>
<td class="romcell" name="role-player">
<div class="listitem listitem-green"></div>
</td>
<td class="romcell" name="role-gamer">
<div class="listitem listitem-green"></div>
</td>
<td class="romcell" name="role-admin">
<div class="listitem listitem-green"></div>
</td>
</tr>
<tr class="romrow">
<td class="romcell">Create packages</td>
<td class="romcell" name="role-player">
<div class="listitem listitem-red"></div>
</td>
<td class="romcell" name="role-gamer">
<div class="listitem listitem-green"></div>
</td>
<td class="romcell" name="role-admin">
<div class="listitem listitem-green"></div>
</td>
</tr>
<tr class="romrow">
<td class="romcell">Edit packages</td>
<td class="romcell" name="role-player">
<div class="listitem listitem-red"></div>
</td>
<td class="romcell" name="role-gamer">
<div class="listitem listitem-green"></div>
</td>
<td class="romcell" name="role-admin">
<div class="listitem listitem-green"></div>
</td>
</tr>
<tr class="romrow">
<td class="romcell">Delete packages</td>
<td class="romcell" name="role-player">
<div class="listitem listitem-red"></div>
</td>
<td class="romcell" name="role-gamer">
<div class="listitem listitem-green"></div>
</td>
<td class="romcell" name="role-admin">
<div class="listitem listitem-green"></div>
</td>
</tr>
<tr>
<th colspan="2">
Settings
</th>
</tr>
<tr class="romrow">
<td class="romcell">Download firmware</td>
<td class="romcell" name="role-player">
<div class="listitem listitem-green"></div>
</td>
<td class="romcell" name="role-gamer">
<div class="listitem listitem-green"></div>
</td>
<td class="romcell" name="role-admin">
<div class="listitem listitem-green"></div>
</td>
</tr>
<tr class="romrow">
<td class="romcell">View background tasks</td>
<td class="romcell" name="role-player">
<div class="listitem listitem-green"></div>
</td>
<td class="romcell" name="role-gamer">
<div class="listitem listitem-green"></div>
</td>
<td class="romcell" name="role-admin">
<div class="listitem listitem-green"></div>
</td>
</tr>
<tr class="romrow">
<td class="romcell">View platform mapping</td>
<td class="romcell" name="role-player">
<div class="listitem listitem-green"></div>
</td>
<td class="romcell" name="role-gamer">
<div class="listitem listitem-green"></div>
</td>
<td class="romcell" name="role-admin">
<div class="listitem listitem-green"></div>
</td>
</tr>
<tr class="romrow">
<td class="romcell">Modify platform mapping</td>
<td class="romcell" name="role-player">
<div class="listitem listitem-red"></div>
</td>
<td class="romcell" name="role-gamer">
<div class="listitem listitem-red"></div>
</td>
<td class="romcell" name="role-admin">
<div class="listitem listitem-green"></div>
</td>
</tr>
<tr class="romrow">
<td class="romcell">Manually start background tasks</td>
<td class="romcell" name="role-player">
<div class="listitem listitem-red"></div>
</td>
<td class="romcell" name="role-gamer">
<div class="listitem listitem-red"></div>
</td>
<td class="romcell" name="role-admin">
<div class="listitem listitem-green"></div>
</td>
</tr>
<tr class="romrow">
<td class="romcell">View logs</td>
<td class="romcell" name="role-player">
<div class="listitem listitem-red"></div>
</td>
<td class="romcell" name="role-gamer">
<div class="listitem listitem-red"></div>
</td>
<td class="romcell" name="role-admin">
<div class="listitem listitem-green"></div>
</td>
</tr>
<tr class="romrow">
<td class="romcell">Manage user accounts</td>
<td class="romcell" name="role-player">
<div class="listitem listitem-red"></div>
</td>
<td class="romcell" name="role-gamer">
<div class="listitem listitem-red"></div>
</td>
<td class="romcell" name="role-admin">
<div class="listitem listitem-green"></div>
</td>
</tr>
</table>
</div>
<div id="role-permissions-expand" class="role-permissions-expand collapsed">
</div>
<div id="role-permissions-expand-link" class="role-permissions-expand-link">Show details...
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div id="tab3" name="modalTab" data-tabname="Age Restrictions">
<div style="display: flex; gap: 10px;">
<div style="flex-grow:1">
<div class="section">
<div class="section-header">Age Group</div>
<div class="section-body">
<div id="settings_user_agerestrictions">
</div>
</div>
</div>
</div>
<div style="flex-grow:1">
<div class="section">
<div class="section-header">Allowed Age Ratings</div>
<div class="section-body">
<div class="role-permissions">
<div id="settings_user_agerestrictions_preview" class="role-permissions-table collapsed">
</div>
<div id="settings_user_agerestrictions_expand" class="role-permissions-expand collapsed">
</div>
<div id="settings_user_agerestrictions_expand-link" class="role-permissions-expand-link">Show
details...
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div id="tab1" name="modalTab" data-tabname="Login">
<div class="section">
<div class="section-header">Change Password</div>
<div class="section-body">
<div style="display: flex; gap: 10px;">
<div style="flex-grow:1">
<div>New Password</div>
<input type="password" id="new-password" name="new-password" style="width: 95%;"
class="inputWithVerticalLabel" />
<div>Confirm New Password</div>
<input type="password" id="confirm-new-password" name="confirm-new-password" style="width: 95%;"
class="inputWithVerticalLabel" />
</div>
<div style="flex-grow:1">
<p>Password requirements:</p>
<div id="password-error"></div>
</div>
</div>
</div>
</div>
</div>

View File

@@ -0,0 +1,19 @@
<div style="display: flex; gap: 10px;">
<div style="flex-grow:1; padding-top: 10px;">
<div>Email Address</div>
<input type="email" id="email-address" name="email-address" style="width: 95%;"
class="inputWithVerticalLabel" />
<div>New Password</div>
<input type="password" id="new-password" name="new-password" style="width: 95%;"
class="inputWithVerticalLabel" />
<div>Confirm New Password</div>
<input type="password" id="confirm-new-password" name="confirm-new-password" style="width: 95%;"
class="inputWithVerticalLabel" />
</div>
<div style="flex-grow:1">
<p>Email requirements:</p>
<div id="email-error"></div>
<p>Password requirements:</p>
<div id="password-error"></div>
</div>
</div>

View File

@@ -0,0 +1,41 @@
<div class="section">
<div class="section-header">Web Emulator</div>
<div class="section-body">
<div id="webemulator_select">
</div>
<div id="webemulator_info_emulatorjs" style="display: none;" class="section">
<div class="section-body">
<img src="/images/EmulatorJS.png" style="float: left; width: 36px; margin-right: 10px;">The EmulatorJS
web
emulator is a
web-based emulator that allows you to run various retro systems in your
browser. For more information, see the project home page at <a href="https://emulatorjs.org"
class="romlink" target="_blank" rel="noopener noreferrer">https://emulatorjs.org</a>.
</div>
</div>
</div>
</div>
<div class="section" id="webemulator_core_select-section">
<div class="section-header">Core</div>
<div class="section-body">
<div id="webemulator_core_select">
</div>
<p id="webemulator_core_info_emulatorjs" style="display: none;">
<img src="/images/help.svg" class="banner_button_image banner_button_image_smaller" alt="Help" title="Help">
See
<a href="https://emulatorjs.org/docs4devs/cores" target="_blank" rel="noopener noreferrer"
class="romlink">https://emulatorjs.org/docs4devs/cores</a>
for more information regarding EmulatorJS cores.
</p>
</div>
</div>
<div class="section" id="webemulator_bios_select-section">
<div class="section-header">BIOS Files Available when Running the Emulator</div>
<div class="section-body">
<div id="webemulator_bios_select">
</div>
</div>
</div>

View File

@@ -1,7 +1,7 @@
<div id="bgImage"
<!-- <div id="bgImage"
style="background-image: url('/images/SettingsWallpaper.jpg'); background-position: center; background-repeat: no-repeat; background-size: cover; filter: blur(10px); -webkit-filter: blur(10px);">
<div id="bgImage_Opacity"></div>
</div>
</div> -->
<div id="gamepage">
<div id="properties_toc" class="settings_toc">
@@ -18,62 +18,25 @@
style="display: none;">
Services</div>
<div id="properties_toc_mapping" name="properties_toc_item" onclick="SelectTab('mapping');"
style="display: none;">Platform Mapping</div>
style="display: none;">Platforms</div>
<div id="properties_toc_bios" name="properties_toc_item" onclick="SelectTab('bios');">Firmware</div>
<div id="properties_toc_logs" name="properties_toc_item" onclick="SelectTab('logs');" style="display: none;">
Logs</div>
<div id="properties_toc_about" name="properties_toc_item" onclick="SelectTab('about');">About</div>
</div>
<div id="properties_bodypanel">
</div>
</div>
<div id="settings_photocredit">
<!-- <div id="settings_photocredit">
Wallpaper by <a href="https://unsplash.com/@lorenzoherrera" class="romlink">Lorenzo Herrera</a> / <a
href="https://unsplash.com/photos/p0j-mE6mGo4" class="romlink">Unsplash</a>
</div>
</div> -->
<script type="text/javascript">
if (userProfile.roles.includes("Admin")) {
document.getElementById('properties_toc_settings').style.display = '';
document.getElementById('properties_toc_libraries').style.display = '';
document.getElementById('properties_toc_users').style.display = '';
document.getElementById('properties_toc_services').style.display = '';
document.getElementById('properties_toc_mapping').style.display = '';
document.getElementById('properties_toc_logs').style.display = '';
}
if (userProfile.roles.includes("Gamer")) {
document.getElementById('properties_toc_mapping').style.display = '';
}
var myParam = getQueryString('sub', 'string');
var selectedTab = '';
if (myParam) {
selectedTab = myParam;
} else {
selectedTab = 'system';
}
SelectTab(selectedTab);
function SelectTab(TabName) {
if (selectedTab != TabName) {
window.location.href = '/index.html?page=settings&sub=' + TabName;
}
var tocs = document.getElementsByName('properties_toc_item');
for (var i = 0; i < tocs.length; i++) {
if ((tocs[i].id) == ("properties_toc_" + TabName)) {
tocs[i].className = "properties_toc_item_selected";
} else {
tocs[i].className = '';
}
}
$('#properties_bodypanel').load('/pages/settings/' + TabName + '.html?v=' + AppVersion);
}
// load the default settings page
SetupPage();
</script>

View File

@@ -0,0 +1,51 @@
let selectedTab = '';
function SetupPage() {
if (userProfile.roles.includes("Admin")) {
document.getElementById('properties_toc_settings').style.display = '';
document.getElementById('properties_toc_libraries').style.display = '';
document.getElementById('properties_toc_users').style.display = '';
document.getElementById('properties_toc_services').style.display = '';
document.getElementById('properties_toc_mapping').style.display = '';
document.getElementById('properties_toc_logs').style.display = '';
}
if (userProfile.roles.includes("Gamer")) {
document.getElementById('properties_toc_mapping').style.display = '';
}
let myParam = getQueryString('sub', 'string');
if (myParam) {
selectedTab = myParam;
} else {
selectedTab = 'system';
}
SelectTab(selectedTab);
}
function SelectTab(TabName) {
if (selectedTab != TabName) {
window.location.href = '/index.html?page=settings&sub=' + TabName;
}
let tocs = document.getElementsByName('properties_toc_item');
for (let i = 0; i < tocs.length; i++) {
if ((tocs[i].id) == ("properties_toc_" + TabName)) {
tocs[i].className = "properties_toc_item_selected";
} else {
tocs[i].className = '';
}
}
let subScriptObject = document.createElement('script');
subScriptObject.src = '/pages/settings/' + TabName + '.js?v=' + AppVersion;
subScriptObject.setAttribute('type', 'text/javascript');
subScriptObject.setAttribute('async', 'false');
subScriptObject.addEventListener('load', function () {
$('#properties_bodypanel').load('/pages/settings/' + TabName + '.html?v=' + AppVersion);
});
document.head.appendChild(subScriptObject);
}
SetupPage();

View File

@@ -2,91 +2,130 @@
<h1 id="gametitle_label">About Gaseous</h1>
</div>
<table style="width: 100%;">
<tr>
<th style="width: 20%;">Home Page</th>
<td><a href="https://github.com/gaseous-project/gaseous-server" class="romlink">https://github.com/gaseous-project/gaseous-server</a></td>
<td rowspan="5" style="text-align: center; width: 128px;">
<img src="/images/logo.png" style="display: block; margin: 20px auto; width: 100px;" />
<span style="display: block;">The Gaseous logo was designed by Tom2.0</span>
</td>
</tr>
<tr>
<th>Bugs and Feature Requests</th>
<td><a href="https://github.com/gaseous-project/gaseous-server/issues" class="romlink">https://github.com/gaseous-project/gaseous-server/issues</a></td>
</tr>
<tr>
<th>Join our Discord</th>
<td><a href="https://discord.gg/Nhu7wpT3k4" class="romlink">https://discord.gg/Nhu7wpT3k4</a></td>
</tr>
<tr>
<th>Server Version</th>
<td id="settings_appversion"></td>
</tr>
<tr>
<th>Database Schema Version</th>
<td id="settings_dbversion"></td>
</tr>
<tr>
<td colspan="3">
<h3>Projects That Make Gaseous Possible</h3>
</td>
</tr>
<tr>
<td style="text-align: center;"><a href="https://github.com/EmulatorJS/EmulatorJS" target="_blank"><img src="/images/EmulatorJS.png" style="height: 36px;" /></a></td>
<td colspan="3">
The EmulatorJS Project<br />
<a href="https://github.com/EmulatorJS/EmulatorJS" target="_blank" class="romlink">https://github.com/EmulatorJS/EmulatorJS</a>
</td>
</tr>
<tr>
<td colspan="3">
<h3>Data Sources</h2>
<h4>Game data</h4>
</td>
</tr>
<tr>
<td style="text-align: center;">
<a href="https://www.igdb.com/" target="_blank"><img src="/images/IGDB_logo.svg" style="filter: invert(100%); height: 36px;" /></a>
</td>
<td colspan="2">
The Internet Game Database<br />
<a href="https://www.igdb.com/" target="_blank" class="romlink">https://www.igdb.com/</a>
</td>
</tr>
<tr>
<td colspan="3">
<h4>Signature data sources</h4>
</td>
</tr>
<tr>
<td style="text-align: center;">
<a href="https://www.tosecdev.org/" target="_blank"><img src="/images/TOSEC_logo.gif" style="height: 36px;" /></a>
</td>
<td colspan="2">
The Old School Emulation Center<br />
<a href="https://www.tosecdev.org/" target="_blank" class="romlink">https://www.tosecdev.org/</a>
</td>
</tr>
<tr>
<td style="text-align: center;">
<a href="https://www.progettosnaps.net/index.php" target="_blank"><img src="/images/ProgettoSnaps.gif" style="height: 36px;" /></a>
</td>
<td colspan="2">
Progetto-Snaps<br />
<a href="https://www.progettosnaps.net/index.php" target="_blank" class="romlink">https://www.progettosnaps.net/index.php</a>
</td>
</tr>
</table>
<div class="section">
<div class="section-body">
<table style="width: 100%;">
<tr>
<td style="width: 20%;">Home Page</td>
<td><a href="https://github.com/gaseous-project/gaseous-server" class="romlink" target="_blank"
rel="noopener noreferrer">https://github.com/gaseous-project/gaseous-server</a></td>
<td rowspan="5" style="text-align: center; width: 128px;">
<img src="/images/logo.png" style="display: block; margin: 20px auto; width: 100px;" />
<span style="display: block;">The Gaseous logo was designed by Tom1243</span>
</td>
</tr>
<tr>
<td>Bugs and Feature Requests</td>
<td><a href="https://github.com/gaseous-project/gaseous-server/issues" class="romlink" target="_blank"
rel="noopener noreferrer">https://github.com/gaseous-project/gaseous-server/issues</a></td>
</tr>
<tr>
<td>Join our Discord</td>
<td><a href="https://discord.gg/Nhu7wpT3k4" class="romlink" target="_blank"
rel="noopener noreferrer">https://discord.gg/Nhu7wpT3k4</a></td>
</tr>
<tr>
<td>Server Version</td>
<td id="settings_appversion"></td>
</tr>
<tr>
<td>Database Schema Version</td>
<td id="settings_dbversion"></td>
</tr>
</table>
</div>
</div>
<div class="section">
<div class="section-header">Projects That Make Gaseous Possible</div>
<div class="section-body">
<table style="width: 100%;">
<tr>
<td style="text-align: center; width: 20%;"><a href="https://github.com/EmulatorJS/EmulatorJS"
target="_blank" rel="noopener noreferrer"><img src="/images/EmulatorJS.png"
style="height: 36px;" /></a></td>
<td colspan="3">
The EmulatorJS Project<br />
<a href="https://github.com/EmulatorJS/EmulatorJS" class="romlink" target="_blank"
rel="noopener noreferrer">https://github.com/EmulatorJS/EmulatorJS</a>
</td>
</tr>
</table>
</div>
</div>
<div class="section">
<div class="section-header">Data Sources</div>
<div class="section-body">
<table style="width: 100%;">
<tr>
<td colspan="3">
<h4>Metadata sources</h4>
</td>
</tr>
<tr>
<td style="text-align: center; width: 20%;">
<a href="https://www.igdb.com/" target="_blank" rel="noopener noreferrer"><img
src="/images/IGDB_logo.svg" style="filter: invert(100%); height: 36px;" /></a>
</td>
<td colspan="2">
The Internet Game Database<br />
<a href="https://www.igdb.com/" target="_blank" rel="noopener noreferrer"
class="romlink">https://www.igdb.com/</a>
</td>
</tr>
<tr>
<td colspan="3">
<h4>Signature data sources</h4>
</td>
</tr>
<tr>
<td style="text-align: center;">
<a href="https://hasheous.org/" target="_blank" rel="noopener noreferrer"><img
src="/images/hasheous.svg" style="height: 36px;" /></a>
</td>
<td colspan="2">
Hasheous<br />
<a href="https://hasheous.org/" target="_blank" rel="noopener noreferrer"
class="romlink">https://hasheous.org/</a>
</td>
</tr>
<tr>
<td style="text-align: center;">
<a href="https://www.tosecdev.org/" target="_blank" rel="noopener noreferrer"><img
src="/images/TOSEC_logo.gif" style="height: 36px;" /></a>
</td>
<td colspan="2">
The Old School Emulation Center<br />
<a href="https://www.tosecdev.org/" target="_blank" rel="noopener noreferrer"
class="romlink">https://www.tosecdev.org/</a>
</td>
</tr>
<tr>
<td style="text-align: center;">
<a href="https://www.progettosnaps.net/index.php" target="_blank" rel="noopener noreferrer"><img
src="/images/ProgettoSnaps.gif" style="height: 36px;" /></a>
</td>
<td colspan="2">
Progetto-Snaps<br />
<a href="https://www.progettosnaps.net/index.php" target="_blank" rel="noopener noreferrer"
class="romlink">https://www.progettosnaps.net/index.php</a>
</td>
</tr>
<tr>
<td style="text-align: center;">
<a href="https://no-intro.org" target="_blank" rel="noopener noreferrer"><img
src="/images/NoIntro-logo.svg" style="height: 36px;" /></a>
</td>
<td colspan="2">
No-Intro<br />
<a href="https://no-intro.org" target="_blank" rel="noopener noreferrer"
class="romlink">https://no-intro.org</a>
</td>
</tr>
</table>
</div>
</div>
<script type="text/javascript">
var versionBox = document.getElementById('settings_appversion');
if (AppVersion == "1.5.0.0") {
versionBox.innerHTML = "Built from source";
} else {
versionBox.innerHTML = AppVersion;
}
var versionBox = document.getElementById('settings_dbversion');
versionBox.innerHTML = DBSchemaVersion;
// populate the page with the server version and database schema version
populatePage();
</script>

View File

@@ -0,0 +1,11 @@
function populatePage() {
let appVersionBox = document.getElementById('settings_appversion');
if (AppVersion == "1.5.0.0") {
appVersionBox.innerHTML = "Built from source";
} else {
appVersionBox.innerHTML = AppVersion;
}
let dbVersionBox = document.getElementById('settings_dbversion');
dbVersionBox.innerHTML = DBSchemaVersion;
}

View File

@@ -2,121 +2,26 @@
<h1 id="gametitle_label">Firmware</h1>
</div>
<h3>Firmware Availablility <span id="firmware_totalcount" style="float: right;"></span></h3>
<p>
Display:
<ul style="list-style-type:none;">
<li><input type="checkbox" id="firmware_showavailable" checked="checked" onclick="displayFirmwareList();"/><label for="firmware_showavailable"> Available</label></li>
<li><input type="checkbox" id="firmware_showunavailable" checked="checked" onclick="displayFirmwareList();"/><label for="firmware_showunavailable"> Unavailable</label></li>
</ul>
</p>
<table id="table_firmware" class="romtable" cellspacing="0">
<div class="section">
<div class="section-header">Firmware Availablility <span id="firmware_totalcount" style="float: right;"></span>
</div>
<div class="section-body">
<p>
Display:
<ul style="list-style-type:none;">
<li><input type="checkbox" id="firmware_showavailable" checked="checked"
onclick="displayFirmwareList();" /><label for="firmware_showavailable"> Available</label></li>
<li><input type="checkbox" id="firmware_showunavailable" checked="checked"
onclick="displayFirmwareList();" /><label for="firmware_showunavailable"> Unavailable</label></li>
</ul>
</p>
<table id="table_firmware" class="romtable" cellspacing="0">
</table>
</table>
</div>
</div>
<script type="text/javascript">
var biosDict = {};
ajaxCall('/api/v1.1/Bios', 'GET', function (result) {
result.sort((a, b) => a.platformname.charCodeAt(0) - b.platformname.charCodeAt(0));
// sort into a dictionary
for (var i = 0; i < result.length; i++) {
var tempArray = [];
if (biosDict.hasOwnProperty(result[i].platformname)) {
tempArray = biosDict[result[i].platformname];
tempArray.push(result[i]);
} else {
tempArray.push(result[i]);
biosDict[result[i].platformname] = tempArray;
}
biosDict[result[i].platformname] = tempArray;
}
console.log(biosDict);
displayFirmwareList();
});
function displayFirmwareList() {
var lastPlatform = '';
var newTable = document.getElementById('table_firmware');
newTable.innerHTML = '';
newTable.appendChild(createTableRow(true, ['Description', 'File name', 'MD5 Hash', 'Available']));
var totalAvailable = 0;
var totalCount = 0;
for (const [key, value] of Object.entries(biosDict)) {
// new platform - show a header
var platformRow = document.createElement('tr');
var platformHeader = document.createElement('th');
platformHeader.setAttribute('colspan', 4);
var platformHeaderValue = document.createElement('span');
platformHeaderValue.innerHTML = key;
platformHeader.appendChild(platformHeaderValue);
var platformHeaderCounter = document.createElement('span');
platformHeaderCounter.style.float = 'right';
platformHeader.appendChild(platformHeaderCounter);
platformRow.appendChild(platformHeader);
newTable.appendChild(platformRow);
var totalPlatformAvailable = 0;
var showAvailable = document.getElementById('firmware_showavailable').checked;
var showUnavailable = document.getElementById('firmware_showunavailable').checked;
for (var i = 0; i < value.length; i++) {
// update counters
if (value[i].available == true) {
totalAvailable += 1;
totalPlatformAvailable += 1;
}
if (
(value[i].available == true && showAvailable == true) ||
(value[i].available == false && showUnavailable == true)
) {
var biosFilename = document.createElement('a');
biosFilename.href = '/api/v1.1/Bios/' + value[i].platformid + '/' + value[i].filename;
biosFilename.innerHTML = value[i].filename;
biosFilename.className = 'romlink';
var availableText = document.createElement('span');
if (value[i].available == true) {
availableText.innerHTML = 'Available';
availableText.className = 'greentext';
biosFilename = document.createElement('a');
biosFilename.href = '/api/v1.1/Bios/' + value[i].platformid + '/' + value[i].filename;
biosFilename.innerHTML = value[i].filename;
biosFilename.className = 'romlink';
} else {
availableText.innerHTML = 'Unavailable';
availableText.className = 'redtext';
biosFilename = document.createElement('span');
biosFilename.innerHTML = value[i].filename;
}
var newRow = [
value[i].description,
biosFilename,
value[i].hash,
availableText
];
newTable.appendChild(createTableRow(false, newRow, 'romrow', 'romcell'));
}
totalCount += 1;
}
platformHeaderCounter.innerHTML = totalPlatformAvailable + ' / ' + value.length + ' available';
}
document.getElementById('firmware_totalcount').innerHTML = totalAvailable + ' / ' + totalCount + ' available';
}
// load the bios list
loadBios();
</script>

View File

@@ -0,0 +1,303 @@
let biosDict = {};
function loadBios() {
biosDict = {};
ajaxCall('/api/v1.1/Bios', 'GET', function (result) {
result.sort((a, b) => a.platformname.charCodeAt(0) - b.platformname.charCodeAt(0));
// sort into a dictionary
for (let i = 0; i < result.length; i++) {
let tempArray = [];
if (biosDict.hasOwnProperty(result[i].platformname)) {
tempArray = biosDict[result[i].platformname];
tempArray.push(result[i]);
} else {
tempArray.push(result[i]);
biosDict[result[i].platformname] = tempArray;
}
biosDict[result[i].platformname] = tempArray;
}
displayFirmwareList();
});
}
function displayFirmwareList() {
let lastPlatform = '';
let targetDiv = document.getElementById('table_firmware');
targetDiv.innerHTML = '';
let totalAvailable = 0;
let totalCount = 0;
for (const [key, value] of Object.entries(biosDict)) {
// new platform - show a header
let platformRow = document.createElement('div');
platformRow.classList.add('section')
let platformHeader = document.createElement('div');
platformHeader.classList.add('section-header');
let platformHeaderValue = document.createElement('span');
platformHeaderValue.innerHTML = key;
platformHeader.appendChild(platformHeaderValue);
let platformHeaderEdit = document.createElement('a');
platformHeaderEdit.href = '#';
platformHeaderEdit.style.float = 'right';
platformHeaderEdit.onclick = function () {
let biosEditor = new BiosEditor(value[0].platformid, loadBios);
biosEditor.open();
};
let platformHeaderEditIcon = document.createElement('img');
platformHeaderEditIcon.src = '/images/edit.svg';
platformHeaderEditIcon.classList.add('banner_button_image');
platformHeaderEdit.appendChild(platformHeaderEditIcon);
platformHeader.appendChild(platformHeaderEdit);
let platformHeaderCounter = document.createElement('span');
platformHeaderCounter.style.float = 'right';
platformHeaderCounter.style.marginRight = '10px';
platformHeader.appendChild(platformHeaderCounter);
platformRow.appendChild(platformHeader);
let platformBody = document.createElement('div');
platformBody.classList.add('section-body');
// create new table
let newTable = document.createElement('table');
newTable.classList.add('romtable');
newTable.setAttribute('cellspacing', 0);
newTable.appendChild(createTableRow(true, ['Description', 'File name', 'MD5 Hash', 'Available']));
let totalPlatformAvailable = 0;
let showAvailable = document.getElementById('firmware_showavailable').checked;
let showUnavailable = document.getElementById('firmware_showunavailable').checked;
for (let i = 0; i < value.length; i++) {
// update counters
if (value[i].available == true) {
totalAvailable += 1;
totalPlatformAvailable += 1;
}
if (
(value[i].available == true && showAvailable == true) ||
(value[i].available == false && showUnavailable == true)
) {
let biosFilename = document.createElement('a');
biosFilename.href = '/api/v1.1/Bios/' + value[i].platformid + '/' + value[i].filename;
biosFilename.innerHTML = value[i].filename;
biosFilename.className = 'romlink';
let availableText = document.createElement('span');
if (value[i].available == true) {
availableText.innerHTML = 'Available';
availableText.className = 'greentext';
biosFilename = document.createElement('a');
biosFilename.href = '/api/v1.1/Bios/' + value[i].platformid + '/' + value[i].filename;
biosFilename.innerHTML = value[i].filename;
biosFilename.className = 'romlink';
} else {
availableText.innerHTML = 'Unavailable';
availableText.className = 'redtext';
biosFilename = document.createElement('span');
biosFilename.innerHTML = value[i].filename;
}
let newRow = [
value[i].description,
biosFilename,
value[i].hash,
availableText
];
newTable.appendChild(createTableRow(false, newRow, 'romrow', 'romcell bioscell'));
}
totalCount += 1;
}
platformHeaderCounter.innerHTML = totalPlatformAvailable + ' / ' + value.length + ' available';
platformBody.append(newTable);
platformRow.append(platformBody);
targetDiv.append(platformRow);
}
document.getElementById('firmware_totalcount').innerHTML = totalAvailable + ' / ' + totalCount + ' available';
}
class BiosEditor {
constructor(PlatformId, OKCallback, CancelCallback) {
this.PlatformId = PlatformId;
this.OKCallback = OKCallback;
this.CancelCallback = CancelCallback;
}
BiosItems = [];
async open() {
// Create the modal
this.dialog = await new Modal("bios");
await this.dialog.BuildModal();
// Get the platform data
await fetch('/api/v1.1/PlatformMaps/' + this.PlatformId, {
method: 'GET',
headers: {
'Content-Type': 'application/json'
}
}).then(async response => {
if (response.ok) {
let result = await response.json();
this.PlatformData = result;
// setup the dialog
this.dialog.modalElement.querySelector('#modal-header-text').innerHTML = this.PlatformData.igdbName;
// setup the bios editor page
let biosEditor = this.dialog.modalElement.querySelector('#bios_editor');
biosEditor.innerHTML = '';
for (let i = 0; i < this.PlatformData.bios.length; i++) {
let biosItem = new MappingBiosItem(this.PlatformData.bios[i].hash, this.PlatformData.bios[i].description, this.PlatformData.bios[i].filename);
biosEditor.appendChild(biosItem.Item);
this.BiosItems.push(biosItem);
}
let newBiosItem = new MappingBiosItem('', '', '');
biosEditor.appendChild(newBiosItem.Item);
this.BiosItems.push(newBiosItem);
let addBiosButton = this.dialog.modalElement.querySelector('#mapping_edit_bios_add');
addBiosButton.addEventListener('click', () => {
let newBiosItem = new MappingBiosItem('', '', '');
biosEditor.appendChild(newBiosItem.Item);
this.BiosItems.push(newBiosItem);
});
// setup the buttons
let okButton = new ModalButton("OK", 1, this, async function (callingObject) {
// build bios items list
let biosItems = [];
for (let i = 0; i < callingObject.BiosItems.length; i++) {
// only add items that are not deleted and have a hash and filename
if (callingObject.BiosItems[i].Deleted == false && callingObject.BiosItems[i].HashInput.value != '' && callingObject.BiosItems[i].FilenameInput.value != '') {
let biosItem = {
hash: callingObject.BiosItems[i].HashInput.value,
description: callingObject.BiosItems[i].DescriptionInput.value,
filename: callingObject.BiosItems[i].FilenameInput.value
};
biosItems.push(biosItem);
}
}
callingObject.PlatformData.bios = biosItems;
await fetch('/api/v1.1/PlatformMaps/' + callingObject.PlatformId, {
method: 'PATCH',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(callingObject.PlatformData)
}).then(async response => {
if (response.ok) {
let result = await response.json();
console.log(result);
if (callingObject.OKCallback) {
callingObject.OKCallback();
}
callingObject.dialog.close();
} else {
let warningDialog = new Dialog("Error", "Failed to save platform data", "OK");
warningDialog.open();
}
});
});
this.dialog.addButton(okButton);
// create the cancel button
let cancelButton = new ModalButton("Cancel", 0, this, function (callingObject) {
if (callingObject.CancelCallback) {
callingObject.CancelCallback();
}
callingObject.dialog.close();
});
this.dialog.addButton(cancelButton);
// Show the modal
this.dialog.open();
} else {
let warningDialog = new MessageBox("Error", "Failed to load platform data", "OK");
warningDialog.open();
return;
}
});
}
}
class MappingBiosItem {
constructor(Hash, Description, Filename) {
this.Hash = Hash;
this.Description = Description;
this.Filename = Filename;
this.Deleted = false;
this.Item = document.createElement('div');
this.Item.classList.add('biositem');
this.Item.classList.add('romrow');
this.HashInput = document.createElement('input');
this.HashInput.type = 'text';
this.HashInput.value = this.Hash;
this.HashInput.classList.add('biosinput');
this.HashInput.classList.add('bioshash');
this.HashInput.placeholder = 'Hash';
this.Item.appendChild(this.HashInput);
this.DescriptionInput = document.createElement('input');
this.DescriptionInput.type = 'text';
this.DescriptionInput.value = this.Description;
this.DescriptionInput.classList.add('biosinput');
this.DescriptionInput.classList.add('biosdescription');
this.DescriptionInput.placeholder = 'Description';
this.Item.appendChild(this.DescriptionInput);
this.FilenameInput = document.createElement('input');
this.FilenameInput.type = 'text';
this.FilenameInput.value = this.Filename;
this.FilenameInput.classList.add('biosinput');
this.FilenameInput.classList.add('biosfilename');
this.FilenameInput.placeholder = 'Filename';
this.Item.appendChild(this.FilenameInput);
this.DeleteButton = document.createElement('a');
this.DeleteButton.href = '#';
this.DeleteButton.classList.add('biositemcontrol');
this.DeleteButton.classList.add('biosdelete');
this.DeleteButton.addEventListener('click', () => {
this.Item.parentElement.removeChild(this.Item);
this.Deleted = true;
});
this.DeleteImage = document.createElement('img');
this.DeleteImage.src = '/images/delete.svg';
this.DeleteImage.alt = 'Delete';
this.DeleteImage.title = 'Delete';
this.DeleteImage.classList.add('banner_button_image');
this.DeleteButton.appendChild(this.DeleteImage);
this.Item.appendChild(this.DeleteButton);
}
}

View File

@@ -2,62 +2,18 @@
<h1 id="gametitle_label">Libraries</h1>
</div>
<table id="settings_libraries" class="romtable" style="width: 100%;" cellspacing="0">
<div class="section">
<div class="section-body">
<table id="settings_libraries" class="romtable" style="width: 100%;" cellspacing="0">
</table>
<div style="text-align: right;"><button id="settings_newlibrary" onclick="showDialog('librarynew');">New
Library</button></div>
</table>
<div style="text-align: right;"><button id="settings_newlibrary">New
Library</button></div>
</div>
</div>
<script type="text/javascript">
function drawLibrary() {
ajaxCall(
'/api/v1.1/Library',
'GET',
function (result) {
var newTable = document.getElementById('settings_libraries');
newTable.innerHTML = '';
newTable.appendChild(createTableRow(true, ['Name', 'Path', 'Default Platform', 'Default Library', '']));
for (var i = 0; i < result.length; i++) {
var platformName = '';
if (result[i].defaultPlatformId == 0) {
if (result[i].isDefaultLibrary == true) {
platformName = "n/a";
} else {
platformName = "";
}
} else {
platformName = result[i].defaultPlatformName;
}
var defaultLibrary = '';
if (result[i].isDefaultLibrary == true) {
defaultLibrary = "Yes";
} else {
defaultLibrary = "";
}
var deleteButton = '';
if (result[i].isDefaultLibrary == false) {
var deleteButton = '<a href="#" onclick="showSubDialog(\'librarydelete\', ' + result[i].id + ');" class="romlink"><img src="/images/delete.svg" class="banner_button_image" alt="Delete" title="Delete" /></a>';
}
newTable.appendChild(createTableRow(
false,
[
result[i].name,
result[i].path,
platformName,
defaultLibrary,
'<div style="text-align: right;">' + deleteButton + '</div>'
],
'romrow',
'romcell'
));
}
}
);
}
// Load the libraries
setupButtons();
drawLibrary();
</script>

View File

@@ -0,0 +1,91 @@
function setupButtons() {
document.getElementById('settings_newlibrary').addEventListener('click', function () {
let newLibrary = new NewLibrary();
newLibrary.open();
});
}
function drawLibrary() {
ajaxCall(
'/api/v1.1/Library',
'GET',
function (result) {
let newTable = document.getElementById('settings_libraries');
newTable.innerHTML = '';
newTable.appendChild(createTableRow(true, ['Name', 'Path', 'Default Platform', 'Default Library', '']));
for (let i = 0; i < result.length; i++) {
let platformName = '';
if (result[i].defaultPlatformId == 0) {
if (result[i].isDefaultLibrary == true) {
platformName = "n/a";
} else {
platformName = "";
}
} else {
platformName = result[i].defaultPlatformName;
}
let defaultLibrary = '';
if (result[i].isDefaultLibrary == true) {
defaultLibrary = "Yes";
} else {
defaultLibrary = "";
}
let controls = document.createElement('div');
controls.style.textAlign = 'right';
let deleteButton = '';
if (result[i].isDefaultLibrary == false) {
deleteButton = document.createElement('a');
deleteButton.href = '#';
deleteButton.addEventListener('click', () => {
let deleteLibrary = new MessageBox('Delete Library', 'Are you sure you want to delete this library?<br /><br /><strong>Warning</strong>: This cannot be undone!');
deleteLibrary.addButton(new ModalButton('OK', 2, deleteLibrary, function (callingObject) {
ajaxCall(
'/api/v1.1/Library/' + result[i].id,
'DELETE',
function () {
callingObject.msgDialog.close();
drawLibrary();
},
function () {
callingObject.msgDialog.close();
drawLibrary();
}
);
}));
deleteLibrary.addButton(new ModalButton('Cancel', 0, deleteLibrary, function (callingObject) {
callingObject.msgDialog.close();
}));
deleteLibrary.open();
});
let deleteButtonImage = document.createElement('img');
deleteButtonImage.src = '/images/delete.svg';
deleteButtonImage.className = 'banner_button_image';
deleteButtonImage.alt = 'Delete';
deleteButtonImage.title = 'Delete';
deleteButton.appendChild(deleteButtonImage);
controls.appendChild(deleteButton);
}
newTable.appendChild(createTableRow(
false,
[
result[i].name,
result[i].path,
platformName,
defaultLibrary,
controls
],
'romrow',
'romcell'
));
}
}
);
}

View File

@@ -5,7 +5,8 @@
<table style="width: 960px; max-width: 960px;" cellspacing="0">
<tr>
<td>
<input type="datetime-local" id="logs_startdate" style="width: 30%;" /> <input type="datetime-local" id="logs_enddate" style="width: 30%;" />
<input type="datetime-local" id="logs_startdate" style="width: 30%;" /> <input type="datetime-local"
id="logs_enddate" style="width: 30%;" />
</td>
<td>
<input type="checkbox" id="logs_type_info"><label for="logs_type_info">Information</label>
@@ -35,7 +36,7 @@
<!-- <a href="#" class="romlink" onclick="loadLogs();" style="float: right;"><img src="/images/refresh.svg" alt="Refresh" title="Refresh" class="banner_button_image" /></a> -->
<table id="settings_events_table" style="width: 960px; max-width: 960px;" cellspacing="0">
</table>
<div style="width: 960px; text-align: center;">
@@ -43,189 +44,7 @@
</div>
<script type="text/javascript">
var lastStartIndex = 0;
var currentPage = 1;
var searchModel = {};
var correlationIdParam = getQueryString('correlationid', 'string');
if (correlationIdParam) {
if (correlationIdParam.length > 0) {
document.getElementById('logs_correlationid').value = correlationIdParam;
}
}
function resetFilters() {
document.getElementById('logs_startdate').value = '';
document.getElementById('logs_enddate').value = '';
document.getElementById('logs_type_info').checked = false;
document.getElementById('logs_type_warning').checked = false;
document.getElementById('logs_type_critical').checked = false;
document.getElementById('logs_textsearch').value = '';
document.getElementById('logs_correlationid').value = '';
loadLogs();
}
function loadLogs(StartIndex, PageNumber) {
var model = {}
if (StartIndex && PageNumber) {
currentPage += 1;
// get saved search model
model = searchModel;
model.StartIndex = StartIndex;
model.PageNumber = PageNumber;
} else {
currentPage = 1;
// create search model
var statusList = [];
if (document.getElementById('logs_type_info').checked == true) { statusList.push(0); }
if (document.getElementById('logs_type_warning').checked == true) { statusList.push(2); }
if (document.getElementById('logs_type_critical').checked == true) { statusList.push(3); }
var startDate = null;
var startDateObj = document.getElementById('logs_startdate');
if (startDateObj.value != null) { startDate = new Date(startDateObj.value); }
var endDate = null;
var endDateObj = document.getElementById('logs_enddate');
if (endDateObj.value != null) { endDate = new Date(endDateObj.value); }
var searchText = null;
var searchTextObj = document.getElementById('logs_textsearch');
if (searchTextObj.value != null) { searchText = searchTextObj.value; }
var correlationId = null;
var correlationIdTextObj = document.getElementById('logs_correlationid');
if (correlationIdTextObj.value != null) { correlationId = correlationIdTextObj.value; }
model = {
"StartIndex": StartIndex,
"PageNumber": PageNumber,
"PageSize": 100,
"Status": statusList,
"StartDateTime": startDate,
"EndDateTime": endDate,
"SearchText": searchText,
"CorrelationId": correlationId
}
searchModel = model;
}
console.log(model);
ajaxCall(
'/api/v1.1/Logs',
'POST',
function (result) {
var newTable = document.getElementById('settings_events_table');
if (currentPage == 1) {
newTable.innerHTML = '';
newTable.appendChild(
createTableRow(
true,
[
//'Id',
['Event Time', 'logs_table_cell_150px'],
['Severity', 'logs_table_cell_150px'],
'Process',
'Message'
],
'',
''
)
);
}
for (var i = 0; i < result.length; i++) {
lastStartIndex = result[i].id;
console.log(result[i]);
var surroundingRow = document.createElement('tbody');
surroundingRow.setAttribute('colspan', 4);
surroundingRow.className = 'logs_table_row_' + result[i].eventType;
var newRow = [
moment(result[i].eventTime).format("YYYY-MM-DD h:mm:ss a"),
result[i].eventType,
result[i].process,
result[i].message.replaceAll("\n", "<br />")
];
surroundingRow.appendChild(createTableRow(false, newRow, '', 'romcell logs_table_cell'));
// exception
var exceptionString = '';
if (result[i].exceptionValue) {
exceptionString = "<strong>Exception</strong><pre class='logs_table_exception' style='width: 795px; word-wrap: break-word; overflow-wrap: break-word; overflow-y: scroll;'>" + syntaxHighlight(JSON.stringify(result[i].exceptionValue, null, 2)).replace(/\\n/g, "<br /> ") + "</pre>";
var exRow = document.createElement('tr');
var leadCell = document.createElement('td');
exRow.appendChild(leadCell);
var exCell = document.createElement('td');
exCell.colSpan = '3';
exCell.innerHTML = exceptionString;
exRow.appendChild(exCell);
surroundingRow.appendChild(exRow);
}
// calling process
var infoRow = document.createElement('tr');
var infoRowEmptyCell = document.createElement('td');
infoRowEmptyCell.className = 'romcell';
var infoRowDataCell = document.createElement('td');
infoRowDataCell.className = 'romcell';
infoRowDataCell.setAttribute('colspan', 3);
infoRowDataCell.innerHTML = '<strong>Calling process:</strong> ' + result[i].callingProcess;
infoRow.appendChild(infoRowEmptyCell);
infoRow.appendChild(infoRowDataCell);
surroundingRow.appendChild(infoRow);
// initiated by user
if (result[i].callingUser) {
if (result[i].callingUser.length > 0) {
var infoRow3 = document.createElement('tr');
var infoRowEmptyCell3 = document.createElement('td');
infoRowEmptyCell3.className = 'romcell';
var infoRowDataCell3 = document.createElement('td');
infoRowDataCell3.className = 'romcell';
infoRowDataCell3.setAttribute('colspan', 3);
infoRowDataCell3.innerHTML = '<strong>User:</strong> ' + result[i].callingUser + "</a>";
infoRow3.appendChild(infoRowEmptyCell3);
infoRow3.appendChild(infoRowDataCell3);
surroundingRow.appendChild(infoRow3);
}
}
// correlation id
var infoRow2 = document.createElement('tr');
var infoRowEmptyCell2 = document.createElement('td');
infoRowEmptyCell2.className = 'romcell';
var infoRowDataCell2 = document.createElement('td');
infoRowDataCell2.className = 'romcell';
infoRowDataCell2.setAttribute('colspan', 3);
infoRowDataCell2.innerHTML = '<strong>Correlation Id:</strong> <a class="romlink" href="/index.html?page=settings&sub=logs&correlationid=' + result[i].correlationId + '">' + result[i].correlationId + "</a>";
infoRow2.appendChild(infoRowEmptyCell2);
infoRow2.appendChild(infoRowDataCell2);
surroundingRow.appendChild(infoRow2);
newTable.appendChild(surroundingRow);
}
},
function (error) {
},
JSON.stringify(model)
);
}
// load the logs
initLogs();
loadLogs();
</script>

View File

@@ -0,0 +1,181 @@
let lastStartIndex = 0;
let currentPage = 1;
let searchModel = {};
function initLogs() {
let correlationIdParam = getQueryString('correlationid', 'string');
if (correlationIdParam) {
if (correlationIdParam.length > 0) {
document.getElementById('logs_correlationid').value = correlationIdParam;
}
}
}
function resetFilters() {
document.getElementById('logs_startdate').value = '';
document.getElementById('logs_enddate').value = '';
document.getElementById('logs_type_info').checked = false;
document.getElementById('logs_type_warning').checked = false;
document.getElementById('logs_type_critical').checked = false;
document.getElementById('logs_textsearch').value = '';
document.getElementById('logs_correlationid').value = '';
loadLogs();
}
function loadLogs(StartIndex, PageNumber) {
let model = {}
if (StartIndex && PageNumber) {
currentPage += 1;
// get saved search model
model = searchModel;
model.StartIndex = StartIndex;
model.PageNumber = PageNumber;
} else {
currentPage = 1;
// create search model
let statusList = [];
if (document.getElementById('logs_type_info').checked == true) { statusList.push(0); }
if (document.getElementById('logs_type_warning').checked == true) { statusList.push(2); }
if (document.getElementById('logs_type_critical').checked == true) { statusList.push(3); }
let startDate = null;
let startDateObj = document.getElementById('logs_startdate');
if (startDateObj.value != null) { startDate = new Date(startDateObj.value); }
let endDate = null;
let endDateObj = document.getElementById('logs_enddate');
if (endDateObj.value != null) { endDate = new Date(endDateObj.value); }
let searchText = null;
let searchTextObj = document.getElementById('logs_textsearch');
if (searchTextObj.value != null) { searchText = searchTextObj.value; }
let correlationId = null;
let correlationIdTextObj = document.getElementById('logs_correlationid');
if (correlationIdTextObj.value != null) { correlationId = correlationIdTextObj.value; }
model = {
"StartIndex": StartIndex,
"PageNumber": PageNumber,
"PageSize": 100,
"Status": statusList,
"StartDateTime": startDate,
"EndDateTime": endDate,
"SearchText": searchText,
"CorrelationId": correlationId
}
searchModel = model;
}
ajaxCall(
'/api/v1.1/Logs',
'POST',
function (result) {
let newTable = document.getElementById('settings_events_table');
if (currentPage == 1) {
newTable.innerHTML = '';
newTable.appendChild(
createTableRow(
true,
[
//'Id',
['Event Time', 'logs_table_cell_150px'],
['Severity', 'logs_table_cell_150px'],
'Process',
'Message'
],
'',
''
)
);
}
for (let i = 0; i < result.length; i++) {
lastStartIndex = result[i].id;
let surroundingRow = document.createElement('tbody');
surroundingRow.setAttribute('colspan', 4);
surroundingRow.className = 'logs_table_row_' + result[i].eventType;
let newRow = [
moment(result[i].eventTime).format("YYYY-MM-DD h:mm:ss a"),
result[i].eventType,
result[i].process,
result[i].message.replaceAll("\n", "<br />")
];
surroundingRow.appendChild(createTableRow(false, newRow, '', 'romcell logs_table_cell'));
// exception
let exceptionString = '';
if (result[i].exceptionValue) {
exceptionString = "<strong>Exception</strong><pre class='logs_table_exception' style='width: 795px; word-wrap: break-word; overflow-wrap: break-word; overflow-y: scroll;'>" + syntaxHighlight(JSON.stringify(result[i].exceptionValue, null, 2)).replace(/\\n/g, "<br /> ") + "</pre>";
let exRow = document.createElement('tr');
let leadCell = document.createElement('td');
exRow.appendChild(leadCell);
let exCell = document.createElement('td');
exCell.colSpan = '3';
exCell.innerHTML = exceptionString;
exRow.appendChild(exCell);
surroundingRow.appendChild(exRow);
}
// calling process
let infoRow = document.createElement('tr');
let infoRowEmptyCell = document.createElement('td');
infoRowEmptyCell.className = 'romcell';
let infoRowDataCell = document.createElement('td');
infoRowDataCell.className = 'romcell';
infoRowDataCell.setAttribute('colspan', 3);
infoRowDataCell.innerHTML = '<strong>Calling process:</strong> ' + result[i].callingProcess;
infoRow.appendChild(infoRowEmptyCell);
infoRow.appendChild(infoRowDataCell);
surroundingRow.appendChild(infoRow);
// initiated by user
if (result[i].callingUser) {
if (result[i].callingUser.length > 0) {
let infoRow3 = document.createElement('tr');
let infoRowEmptyCell3 = document.createElement('td');
infoRowEmptyCell3.className = 'romcell';
let infoRowDataCell3 = document.createElement('td');
infoRowDataCell3.className = 'romcell';
infoRowDataCell3.setAttribute('colspan', 3);
infoRowDataCell3.innerHTML = '<strong>User:</strong> ' + result[i].callingUser + "</a>";
infoRow3.appendChild(infoRowEmptyCell3);
infoRow3.appendChild(infoRowDataCell3);
surroundingRow.appendChild(infoRow3);
}
}
// correlation id
let infoRow2 = document.createElement('tr');
let infoRowEmptyCell2 = document.createElement('td');
infoRowEmptyCell2.className = 'romcell';
let infoRowDataCell2 = document.createElement('td');
infoRowDataCell2.className = 'romcell';
infoRowDataCell2.setAttribute('colspan', 3);
infoRowDataCell2.innerHTML = '<strong>Correlation Id:</strong> <a class="romlink" href="/index.html?page=settings&sub=logs&correlationid=' + result[i].correlationId + '">' + result[i].correlationId + "</a>";
infoRow2.appendChild(infoRowEmptyCell2);
infoRow2.appendChild(infoRowDataCell2);
surroundingRow.appendChild(infoRow2);
newTable.appendChild(surroundingRow);
}
},
function (error) {
},
JSON.stringify(model)
);
}

View File

@@ -1,98 +1,37 @@
<div id="gametitle">
<h1 id="gametitle_label">Platform Mapping</h1>
<h1 id="gametitle_label">Platforms</h1>
</div>
<p>When determining the platform of a ROM or image (which is later used when determining the game title), only the "Unique File Extensions" are used. All other extensions are ignored as they will limit the ability of Gaseous to determine the game title (see <a href="https://github.com/gaseous-project/gaseous-server#game-image-title-matching" class="romlink">https://github.com/gaseous-project/gaseous-server#game-image-title-matching</a> for more information on how matching works).</p>
<div class="section">
<div class="section-body">
<p>When determining the platform of a ROM or image (which is later used when determining the game title), only
the "Unique File Extensions" are used. All other extensions are ignored as they will limit the ability of
Gaseous to determine the game title (see <a
href="https://github.com/gaseous-project/gaseous-server/wiki/ROM-Metadata-Matching" class="romlink"
target="_blank"
rel="noopener noreferrer">https://github.com/gaseous-project/gaseous-server/wiki/ROM-Metadata-Matching</a>
for
more
information on how matching works).</p>
<p>This list is pre-populated with some of the more common platforms. New platforms will appear in this list as titles are added.</p>
<p>This list is pre-populated with some of the more common platforms. New platforms will appear in this list as
titles are added.</p>
<p id="settings_mapping_import" style="display: none;"><button value="Export to JSON" onclick="DownloadJSON();">Export to JSON</button><button id="importjson" value="Import JSON">Import JSON</button><button value="Reset to Default" onclick="loadPlatformMapping(true);">Reset to Default</button></p>
<p id="settings_mapping_import" style="display: none;"><button value="Export to JSON"
onclick="DownloadJSON();">Export to JSON</button><button id="importjson" value="Import JSON">Import
JSON</button><button value="Reset to Default" onclick="loadPlatformMapping(true);">Reset to
Default</button></p>
<input id='uploadjson' type='file' name='files' hidden/>
<input id='uploadjson' type='file' name='files' hidden />
<table id="settings_mapping_table" style="width: 100%;" cellspacing="0">
</table>
<table id="settings_mapping_table" style="width: 100%;" cellspacing="0">
</table>
</div>
</div>
<script type="text/javascript">
if (userProfile.roles.includes("Admin")) {
document.getElementById('settings_mapping_import').style.display = '';
}
function loadPlatformMapping(Overwrite) {
var queryString = '';
if (Overwrite == true) {
queryString = '?ResetToDefault=true';
}
ajaxCall(
'/api/v1.1/PlatformMaps' + queryString,
'GET',
function (result) {
var newTable = document.getElementById('settings_mapping_table');
newTable.innerHTML = '';
newTable.appendChild(
createTableRow(
true,
[
'Platform',
'Supported File Extensions',
'Unique File Extensions',
'Has Web Emulator'
],
'',
''
)
);
for (var i = 0; i < result.length; i++) {
var hasWebEmulator = '';
if (result[i].webEmulator.type.length > 0) {
hasWebEmulator = 'Yes';
}
var platformLink = '';
if (userProfile.roles.includes("Admin")) {
platformLink = '<a href="#/" onclick="ShowPlatformMappingDialog(' + result[i].igdbId + ');" class="romlink">' + result[i].igdbName + '</a>';
} else {
platformLink = result[i].igdbName;
}
var newRow = [
platformLink,
result[i].extensions.supportedFileExtensions.join(', '),
result[i].extensions.uniqueFileExtensions.join(', '),
hasWebEmulator
];
newTable.appendChild(createTableRow(false, newRow, 'romrow', 'romcell logs_table_cell'));
}
}
);
}
function DownloadJSON() {
window.location = '/api/v1.1/PlatformMaps/PlatformMap.json';
}
document.getElementById('importjson').addEventListener('click', openDialog);
function openDialog() {
document.getElementById('uploadjson').click();
}
$('#uploadjson').change(function () {
$(this).simpleUpload("/api/v1.1/PlatformMaps", {
start: function (file) {
//upload started
console.log("JSON upload started");
},
success: function(data){
//upload successful
window.location.reload();
}
});
});
// Load the platform mapping
SetupButtons();
loadPlatformMapping();
</script>

View File

@@ -0,0 +1,448 @@
function loadPlatformMapping(Overwrite) {
let queryString = '';
if (Overwrite == true) {
console.log('Overwriting PlatformMap.json');
queryString = '?ResetToDefault=true';
}
ajaxCall(
'/api/v1.1/PlatformMaps' + queryString,
'GET',
function (result) {
let newTable = document.getElementById('settings_mapping_table');
newTable.innerHTML = '';
newTable.appendChild(
createTableRow(
true,
[
'Platform',
'Supported File Extensions',
'Unique File Extensions',
'Has Web Emulator',
''
],
'',
''
)
);
for (let i = 0; i < result.length; i++) {
let hasWebEmulator = '';
if (result[i].webEmulator.type.length > 0) {
hasWebEmulator = 'Yes';
}
let platformEditButton = null;
if (userProfile.roles.includes("Admin")) {
platformEditButton = document.createElement('div');
platformEditButton.classList.add('romlink');
platformEditButton.onclick = function () {
let mappingModal = new Mapping(result[i].igdbId, loadPlatformMapping);
mappingModal.open();
};
let editButtonImage = document.createElement('img');
editButtonImage.src = '/images/edit.svg';
editButtonImage.alt = 'Edit';
editButtonImage.title = 'Edit';
editButtonImage.classList.add('banner_button_image');
platformEditButton.appendChild(editButtonImage);
}
let newRow = [
result[i].igdbName,
result[i].extensions.supportedFileExtensions.join(', '),
result[i].extensions.uniqueFileExtensions.join(', '),
hasWebEmulator,
platformEditButton
];
newTable.appendChild(createTableRow(false, newRow, 'romrow', 'romcell logs_table_cell'));
}
}
);
}
function DownloadJSON() {
window.location = '/api/v1.1/PlatformMaps/PlatformMap.json';
}
function SetupButtons() {
if (userProfile.roles.includes("Admin")) {
document.getElementById('settings_mapping_import').style.display = '';
document.getElementById('uploadjson').addEventListener('change', function () {
$(this).simpleUpload("/api/v1.1/PlatformMaps", {
start: function (file) {
//upload started
console.log("JSON upload started");
},
success: function (data) {
//upload successful
window.location.reload();
}
});
});
document.getElementById('importjson').addEventListener('click', openDialog);
}
}
function openDialog() {
document.getElementById('uploadjson').click();
}
class Mapping {
constructor(PlatformId, OKCallback, CancelCallback) {
this.PlatformId = PlatformId;
this.OKCallback = OKCallback;
this.CancelCallback = CancelCallback;
}
async open() {
// Create the modal
this.dialog = await new Modal("mappings");
await this.dialog.BuildModal();
// Get the platform data
await fetch('/api/v1.1/PlatformMaps/' + this.PlatformId, {
method: 'GET',
headers: {
'Content-Type': 'application/json'
}
}).then(async response => {
if (response.ok) {
let result = await response.json();
this.PlatformData = result;
} else {
let warningDialog = new MessageBox("Error", "Failed to load platform data", "OK");
warningDialog.open();
}
});
// setup the dialog
this.dialog.modalElement.querySelector('#modal-header-text').innerHTML = this.PlatformData.igdbName;
// setup general page
this.alternateNames = this.dialog.modalElement.querySelector('#mapping_edit_alternativenames');
$(this.alternateNames).select2({
tags: true,
tokenSeparators: [',']
});
this.#AddTokensFromList(this.alternateNames, this.PlatformData.alternateNames);
this.supportedFileExtensions = this.dialog.modalElement.querySelector('#mapping_edit_supportedfileextensions');
$(this.supportedFileExtensions).select2({
tags: true,
tokenSeparators: [','],
createTag: function (params) {
if (params.term.indexOf('.') === -1) {
// Return null to disable tag creation
return null;
}
return {
id: params.term.toUpperCase(),
text: params.term.toUpperCase()
}
}
});
this.#AddTokensFromList(this.supportedFileExtensions, this.PlatformData.extensions.supportedFileExtensions);
this.dialog.modalElement.querySelector('#mapping_edit_igdbslug').value = this.PlatformData.igdbSlug;
this.dialog.modalElement.querySelector('#mapping_edit_retropie').value = this.PlatformData.retroPieDirectoryName;
// setup the emulator page
this.webEmulatorConfiguration = new WebEmulatorConfiguration(this.PlatformData);
await this.webEmulatorConfiguration.open();
this.dialog.modalElement.querySelector('#mapping_edit_webemulator').appendChild(this.webEmulatorConfiguration.panel);
// setup the buttons
let okButton = new ModalButton("OK", 1, this, async function (callingObject) {
callingObject.PlatformData.alternateNames = $(callingObject.alternateNames).val();
callingObject.PlatformData.extensions.supportedFileExtensions = $(callingObject.supportedFileExtensions).val();
callingObject.PlatformData.retroPieDirectoryName = callingObject.dialog.modalElement.querySelector('#mapping_edit_retropie').value;
callingObject.PlatformData.webEmulator.type = callingObject.webEmulatorConfiguration.PlatformMap.webEmulator.type;
callingObject.PlatformData.webEmulator.core = callingObject.webEmulatorConfiguration.PlatformMap.webEmulator.core;
callingObject.PlatformData.enabledBIOSHashes = callingObject.webEmulatorConfiguration.PlatformMap.enabledBIOSHashes;
await fetch('/api/v1.1/PlatformMaps/' + callingObject.PlatformId, {
method: 'PATCH',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(callingObject.PlatformData)
}).then(async response => {
if (response.ok) {
let result = await response.json();
if (callingObject.OKCallback) {
callingObject.OKCallback();
}
callingObject.dialog.close();
} else {
let warningDialog = new Dialog("Error", "Failed to save platform data", "OK");
warningDialog.open();
}
});
});
this.dialog.addButton(okButton);
// create the cancel button
let cancelButton = new ModalButton("Cancel", 0, this, function (callingObject) {
if (callingObject.CancelCallback) {
callingObject.CancelCallback();
}
callingObject.dialog.close();
});
this.dialog.addButton(cancelButton);
this.dialog.open();
}
#AddTokensFromList(selectObj, tagList) {
for (let i = 0; i < tagList.length; i++) {
let data = {
id: tagList[i],
text: tagList[i]
}
let newOption = new Option(data.text, data.id, true, true);
$(selectObj).append(newOption).trigger('change');
}
}
}
class WebEmulatorConfiguration {
constructor(PlatformMap) {
this.PlatformMap = PlatformMap;
if (this.PlatformMap.bios.length > 0) {
this.PlatformMap.bios.sort((a, b) => (a.description > b.description) ? 1 : ((b.description > a.description) ? -1 : 0))
}
}
async open() {
// create the panel
this.panel = document.createElement('div');
const templateResponse = await fetch('/pages/modals/webemulator.html');
const templateContent = await templateResponse.text();
this.panel.innerHTML = templateContent;
// load the emulator list
this.#LoadEmulatorList();
// select the emulator and core
if (this.PlatformMap.webEmulator.type.length === 0) {
this.PlatformMap.webEmulator.type = 'none';
}
let emulatorSelect = this.panel.querySelector('#webemulator_select_' + this.PlatformMap.webEmulator.type);
if (emulatorSelect != null) {
emulatorSelect.checked = true;
this.#LoadCoreList(this.PlatformMap.webEmulator.type);
let coreSelect = this.panel.querySelector('#webemulator_core_select_' + this.PlatformMap.webEmulator.core);
if (coreSelect != null) {
coreSelect.checked = true;
}
}
this.#EmulatorInfoPanels();
// load the bios list
this.#LoadBiosList();
}
#LoadEmulatorList() {
let emulatorSelect = this.panel.querySelector('#webemulator_select');
let emulatorSelectTable = document.createElement('table');
// create radio button list of available web emulators
let emulatorSelectTableRow = document.createElement('tr');
let emulatorSelectTableCell = document.createElement('td');
let newOption = document.createElement('input');
newOption.id = 'webemulator_select_none';
newOption.name = 'webemulator_select';
newOption.type = 'radio';
newOption.value = '';
newOption.addEventListener('change', () => {
this.#LoadCoreList('');
this.PlatformMap.webEmulator.type = '';
this.#EmulatorInfoPanels();
});
emulatorSelectTableCell.appendChild(newOption);
let newLabel = document.createElement('label');
newLabel.htmlFor = 'webemulator_select_none';
newLabel.innerHTML = '&nbsp;None';
emulatorSelectTableCell.appendChild(newLabel);
emulatorSelectTableRow.appendChild(emulatorSelectTableCell);
emulatorSelectTable.appendChild(emulatorSelectTableRow);
if (this.PlatformMap.webEmulator.availableWebEmulators) {
if (this.PlatformMap.webEmulator.availableWebEmulators.length > 0) {
for (let i = 0; i < this.PlatformMap.webEmulator.availableWebEmulators.length; i++) {
let emulatorSelectTableRow = document.createElement('tr');
let emulatorSelectTableCell = document.createElement('td');
let newOption = document.createElement('input');
newOption.id = 'webemulator_select_' + this.PlatformMap.webEmulator.availableWebEmulators[i].emulatorType;
newOption.name = 'webemulator_select';
newOption.type = 'radio';
newOption.value = this.PlatformMap.webEmulator.availableWebEmulators[i].emulatorType;
newOption.addEventListener('change', () => {
this.#LoadCoreList(this.PlatformMap.webEmulator.availableWebEmulators[i].emulatorType);
this.PlatformMap.webEmulator.type = this.PlatformMap.webEmulator.availableWebEmulators[i].emulatorType;
this.#EmulatorInfoPanels();
});
emulatorSelectTableCell.appendChild(newOption);
let newLabel = document.createElement('label');
newLabel.htmlFor = 'webemulator_select_' + this.PlatformMap.webEmulator.availableWebEmulators[i].emulatorType;
newLabel.innerHTML = "&nbsp;" + this.PlatformMap.webEmulator.availableWebEmulators[i].emulatorType;
emulatorSelectTableCell.appendChild(newLabel);
emulatorSelectTableRow.appendChild(emulatorSelectTableCell);
emulatorSelectTable.appendChild(emulatorSelectTableRow);
}
}
}
emulatorSelect.appendChild(emulatorSelectTable);
}
#EmulatorInfoPanels() {
// show appropriate emulator info panel
switch (this.PlatformMap.webEmulator.type) {
case 'EmulatorJS':
this.panel.querySelector('#webemulator_info_emulatorjs').style.display = '';
break;
default:
this.panel.querySelector('#webemulator_info_emulatorjs').style.display = 'none';
break;
}
}
#LoadCoreList(EmulatorType) {
let coreSelectSection = this.panel.querySelector('#webemulator_core_select-section');
coreSelectSection.style.display = 'none';
// show core help (if available)
switch (EmulatorType) {
case 'EmulatorJS':
this.panel.querySelector('#webemulator_core_info_emulatorjs').style.display = '';
break;
}
let coreSelect = this.panel.querySelector('#webemulator_core_select');
coreSelect.innerHTML = '';
let coreSelectTable = document.createElement('table');
if (this.PlatformMap.webEmulator.availableWebEmulators) {
if (this.PlatformMap.webEmulator.availableWebEmulators.length > 0) {
for (let i = 0; i < this.PlatformMap.webEmulator.availableWebEmulators.length; i++) {
if (this.PlatformMap.webEmulator.availableWebEmulators[i].emulatorType == EmulatorType) {
for (let j = 0; j < this.PlatformMap.webEmulator.availableWebEmulators[i].availableWebEmulatorCores.length; j++) {
coreSelectSection.style.display = '';
let coreSelectTableRow = document.createElement('tr');
let coreSelectTableCell = document.createElement('td');
let newOption = document.createElement('input');
newOption.id = 'webemulator_core_select_' + this.PlatformMap.webEmulator.availableWebEmulators[i].availableWebEmulatorCores[j].core;
newOption.name = 'webemulator_core_select';
newOption.type = 'radio';
newOption.value = this.PlatformMap.webEmulator.availableWebEmulators[i].availableWebEmulatorCores[j].core;
newOption.text = this.PlatformMap.webEmulator.availableWebEmulators[i].availableWebEmulatorCores[j].core;
if (this.PlatformMap.webEmulator.availableWebEmulators[i].availableWebEmulatorCores[j].default == true) {
newOption.checked = true;
}
newOption.addEventListener('change', () => {
this.PlatformMap.webEmulator.core = this.PlatformMap.webEmulator.availableWebEmulators[i].availableWebEmulatorCores[j].core;
});
coreSelectTableCell.appendChild(newOption);
let newLabel = document.createElement('label');
newLabel.htmlFor = 'webemulator_core_select_' + this.PlatformMap.webEmulator.availableWebEmulators[i].availableWebEmulatorCores[j].core;
let labelText = "";
if (this.PlatformMap.webEmulator.availableWebEmulators[i].availableWebEmulatorCores[j].alternateCoreName.length > 0) {
labelText = "&nbsp;" + this.PlatformMap.webEmulator.availableWebEmulators[i].availableWebEmulatorCores[j].core + " (maps to core: " + this.PlatformMap.webEmulator.availableWebEmulators[i].availableWebEmulatorCores[j].alternateCoreName + ")";
} else {
labelText = "&nbsp;" + this.PlatformMap.webEmulator.availableWebEmulators[i].availableWebEmulatorCores[j].core;
}
if (this.PlatformMap.webEmulator.availableWebEmulators[i].availableWebEmulatorCores[j].default == true) {
labelText += " (Default)";
}
newLabel.innerHTML = labelText;
coreSelectTableCell.appendChild(newLabel);
coreSelectTableRow.appendChild(coreSelectTableCell);
coreSelectTable.appendChild(coreSelectTableRow);
}
}
}
}
}
coreSelect.appendChild(coreSelectTable);
}
#LoadBiosList() {
if (this.PlatformMap.bios.length > 0) {
let biosSelect = this.panel.querySelector('#webemulator_bios_select');
biosSelect.innerHTML = '';
let biosSelectTable = document.createElement('table');
biosSelectTable.style.width = '100%';
for (let i = 0; i < this.PlatformMap.bios.length; i++) {
let biosSelectTableRow = document.createElement('tr');
biosSelectTableRow.classList.add('romrow');
let biosSelectTableCell = document.createElement('td');
biosSelectTableCell.classList.add('romcell');
let newOption = document.createElement('input');
newOption.id = 'webemulator_bios_select_' + this.PlatformMap.bios[i].hash;
newOption.name = 'webemulator_bios_select';
newOption.type = 'checkbox';
newOption.value = this.PlatformMap.bios[i].hash;
if (this.PlatformMap.enabledBIOSHashes.includes(this.PlatformMap.bios[i].hash)) {
newOption.checked = true;
}
newOption.addEventListener('change', () => {
if (newOption.checked) {
this.PlatformMap.enabledBIOSHashes.push(this.PlatformMap.bios[i].hash);
} else {
let index = this.PlatformMap.enabledBIOSHashes.indexOf(this.PlatformMap.bios[i].hash);
if (index > -1) {
this.PlatformMap.enabledBIOSHashes.splice(index, 1);
}
}
});
biosSelectTableCell.appendChild(newOption);
let newLabel = document.createElement('label');
newLabel.htmlFor = 'webemulator_bios_select_' + this.PlatformMap.bios[i].hash;
let labelText = "";
if (this.PlatformMap.bios[i].description.length > 0) {
labelText = this.PlatformMap.bios[i].description + " (" + this.PlatformMap.bios[i].filename + ")";
} else {
labelText = this.PlatformMap.bios[i].filename;
}
newLabel.innerHTML = "&nbsp;" + labelText;
biosSelectTableCell.appendChild(newLabel);
biosSelectTableRow.appendChild(biosSelectTableCell);
biosSelectTable.appendChild(biosSelectTableRow);
}
biosSelect.appendChild(biosSelectTable);
} else {
this.panel.querySelector('#webemulator_bios_select-section').style.display = 'none';
}
}
}

View File

@@ -1,290 +1,16 @@
<div id="gametitle">
<h1 id="gametitle_label">Services</h1>
</div>
<table id="settings_tasktimers" class="romtable" style="width: 100%;" cellspacing="0">
</table>
<div style="text-align: right;"><button id="settings_tasktimers_default" onclick="defaultTaskTimers();">Reset to
Default</button><button id="settings_tasktimers_new" onclick="saveTaskTimers();">Save</button></div>
<div class="section">
<div id="settings_tasktimers" style="width: 100%;">
</div>
<div style="text-align: right;"><button id="settings_tasktimers_default" onclick="defaultTaskTimers();">Reset to
Default</button><button id="settings_tasktimers_new" onclick="saveTaskTimers();">Save</button></div>
</div>
<script type="text/javascript">
function getBackgroundTaskTimers() {
ajaxCall(
'/api/v1/System/Settings/BackgroundTasks/Configuration',
'GET',
function (result) {
var targetTable = document.getElementById('settings_tasktimers');
targetTable.innerHTML = '';
for (const [key, value] of Object.entries(result)) {
var newTableRowBody = document.createElement('tbody');
newTableRowBody.className = 'romrow';
var enabledString = "";
if (value.enabled == true) {
enabledString = 'checked="checked"';
}
var newTableIntervalRow = createTableRow(
false,
[
GetTaskFriendlyName(value.task),
'Enabled',
'<input id="settings_enabled_' + value.task + '" name="settings_tasktimers_enabled" type="checkbox" ' + enabledString + '/>',
],
'',
'romcell'
);
newTableRowBody.appendChild(newTableIntervalRow);
var newTableRow = createTableRow(
false,
[
'',
'Minimum Interval (Minutes):',
'<input id="settings_tasktimers_' + value.task + '" name="settings_tasktimers_values" data-name="' + value.task + '" data-default="' + value.defaultInterval + '" type="number" placeholder="' + value.defaultInterval + '" min="' + value.minimumAllowedInterval + '" value="' + value.interval + '" />'
],
'',
'romcell'
);
newTableRowBody.appendChild(newTableRow);
// allowed time periods row
var newTableRowTime = document.createElement('tr');
var rowTimeSpace = document.createElement('td');
newTableRowTime.appendChild(rowTimeSpace);
var rowTimeContentTitle = document.createElement('td');
rowTimeContentTitle.className = 'romcell';
rowTimeContentTitle.innerHTML = "Allowed Days:";
newTableRowTime.appendChild(rowTimeContentTitle);
var rowTimeContent = document.createElement('td');
// rowTimeContent.setAttribute('colspan', 2);
rowTimeContent.className = 'romcell';
var daySelector = document.createElement('select');
daySelector.id = 'settings_alloweddays_' + value.task;
daySelector.name = 'settings_alloweddays';
daySelector.multiple = 'multiple';
daySelector.setAttribute('data-default', value.defaultAllowedDays.join(","));
daySelector.style.width = '95%';
var days = ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"];
for (var d = 0; d < days.length; d++) {
var dayOpt = document.createElement('option');
dayOpt.value = days[d];
dayOpt.innerHTML = days[d];
if (value.allowedDays.includes(days[d])) {
dayOpt.selected = 'selected';
}
daySelector.appendChild(dayOpt);
}
rowTimeContent.appendChild(daySelector);
$(daySelector).select2({
tags: false
});
newTableRowTime.appendChild(rowTimeContent);
newTableRowBody.appendChild(newTableRowTime);
// add start and end times
var newTableRowClock = document.createElement('tr');
var rowClockSpace = document.createElement('td');
newTableRowClock.appendChild(rowClockSpace);
var rowClockContentTitle = document.createElement('td');
rowClockContentTitle.className = 'romcell';
rowClockContentTitle.innerHTML = "Time Range:";
newTableRowClock.appendChild(rowClockContentTitle);
var rowClockContent = document.createElement('td');
rowClockContent.className = 'romcell';
// rowClockContent.setAttribute('colspan', 2);
rowClockContent.appendChild(generateTimeDropDowns(value.task, 'Start', value.defaultAllowedStartHours, value.defaultAllowedStartMinutes, value.allowedStartHours, value.allowedStartMinutes));
rowClockContentSeparator = document.createElement('span');
rowClockContentSeparator.innerHTML = '&nbsp;-&nbsp;';
rowClockContent.appendChild(rowClockContentSeparator);
rowClockContent.appendChild(generateTimeDropDowns(value.task, 'End', value.defaultAllowedEndHours, value.defaultAllowedEndMinutes, value.allowedEndHours, value.allowedEndMinutes));
newTableRowClock.appendChild(rowClockContent);
newTableRowBody.appendChild(newTableRowClock);
// blocks tasks
var newTableRowBlocks = document.createElement('tr');
var rowBlocksSpace = document.createElement('td');
newTableRowBlocks.appendChild(rowBlocksSpace);
var rowBlocksContentTitle = document.createElement('td');
rowBlocksContentTitle.className = 'romcell';
rowBlocksContentTitle.innerHTML = "Blocks:";
newTableRowBlocks.appendChild(rowBlocksContentTitle);
var rowBlocksContent = document.createElement('td');
rowBlocksContent.className = 'romcell';
// rowBlocksContent.setAttribute('colspan', 2);
var blocksString = "";
for (var i = 0; i < value.blocks.length; i++) {
if (blocksString.length > 0) { blocksString += ", "; }
blocksString += GetTaskFriendlyName(value.blocks[i]);
}
if (blocksString.length == 0) { blocksString = 'None'; }
rowBlocksContent.innerHTML = blocksString;
newTableRowBlocks.appendChild(rowBlocksContent);
newTableRowBody.appendChild(newTableRowBlocks);
// blocked by tasks
var newTableRowBlockedBy = document.createElement('tr');
var rowBlockedBySpace = document.createElement('td');
newTableRowBlockedBy.appendChild(rowBlockedBySpace);
var rowBlockedByContentTitle = document.createElement('td');
rowBlockedByContentTitle.className = 'romcell';
rowBlockedByContentTitle.innerHTML = "Blocked By:";
newTableRowBlockedBy.appendChild(rowBlockedByContentTitle);
var rowBlockedByContent = document.createElement('td');
rowBlockedByContent.className = 'romcell';
// rowBlockedByContent.setAttribute('colspan', 2);
var BlockedByString = "";
for (var i = 0; i < value.blockedBy.length; i++) {
if (BlockedByString.length > 0) { BlockedByString += ", "; }
BlockedByString += GetTaskFriendlyName(value.blockedBy[i]);
}
if (BlockedByString.length == 0) { BlockedByString = 'None'; }
rowBlockedByContent.innerHTML = BlockedByString;
newTableRowBlockedBy.appendChild(rowBlockedByContent);
newTableRowBody.appendChild(newTableRowBlockedBy);
// complete row
targetTable.appendChild(newTableRowBody);
}
}
);
}
function generateTimeDropDowns(taskName, rangeName, defaultHour, defaultMinute, valueHour, valueMinute) {
var container = document.createElement('div');
container.style.display = 'inline';
var elementName = 'settings_tasktimers_time';
var hourSelector = document.createElement('input');
hourSelector.id = 'settings_tasktimers_' + taskName + '_' + rangeName + '_Hour';
hourSelector.name = elementName;
hourSelector.setAttribute('data-name', taskName);
hourSelector.setAttribute('type', 'number');
hourSelector.setAttribute('min', '0');
hourSelector.setAttribute('max', '23');
hourSelector.setAttribute('placeholder', defaultHour);
hourSelector.value = valueHour;
container.appendChild(hourSelector);
var separator = document.createElement('span');
separator.innerHTML = " : ";
container.appendChild(separator);
var minSelector = document.createElement('input');
minSelector.id = 'settings_tasktimers_' + taskName + '_' + rangeName + '_Minute';
minSelector.name = elementName;
minSelector.setAttribute('type', 'number');
minSelector.setAttribute('min', '0');
minSelector.setAttribute('max', '59');
minSelector.setAttribute('placeholder', defaultMinute);
minSelector.value = valueMinute;
container.appendChild(minSelector);
return container;
}
function saveTaskTimers() {
var timerValues = document.getElementsByName('settings_tasktimers_values');
var model = [];
for (var i = 0; i < timerValues.length; i++) {
var taskName = timerValues[i].getAttribute('data-name');
var taskEnabled = document.getElementById('settings_enabled_' + taskName).checked;
var taskIntervalObj = document.getElementById('settings_tasktimers_' + taskName);
var taskInterval = function () { if (taskIntervalObj.value) { return taskIntervalObj.value; } else { return taskIntervalObj.getAttribute('placeholder'); } };
var taskDaysRaw = $('#settings_alloweddays_' + taskName).select2('data');
var taskDays = [];
if (taskDaysRaw.length > 0) {
for (var d = 0; d < taskDaysRaw.length; d++) {
taskDays.push(taskDaysRaw[d].id);
}
} else {
taskDays.push("Monday");
}
var taskStartHourObj = document.getElementById('settings_tasktimers_' + taskName + '_Start_Hour');
var taskStartMinuteObj = document.getElementById('settings_tasktimers_' + taskName + '_Start_Minute');
var taskEndHourObj = document.getElementById('settings_tasktimers_' + taskName + '_End_Hour');
var taskEndMinuteObj = document.getElementById('settings_tasktimers_' + taskName + '_End_Minute');
var taskStartHour = function () { if (taskStartHourObj.value) { return taskStartHourObj.value; } else { return taskStartHourObj.getAttribute('placeholder'); } };
var taskStartMinute = function () { if (taskStartMinuteObj.value) { return taskStartMinuteObj.value; } else { return taskStartMinuteObj.getAttribute('placeholder'); } };
var taskEndHour = function () { if (taskEndHourObj.value) { return taskEndHourObj.value; } else { return taskEndHourObj.getAttribute('placeholder'); } };
var taskEndMinute = function () { if (taskEndMinuteObj.value) { return taskEndMinuteObj.value; } else { return taskEndMinuteObj.getAttribute('placeholder'); } };
model.push(
{
"task": taskName,
"enabled": taskEnabled,
"interval": taskInterval(),
"allowedDays": taskDays,
"allowedStartHours": taskStartHour(),
"allowedStartMinutes": taskStartMinute(),
"allowedEndHours": taskEndHour(),
"allowedEndMinutes": taskEndMinute()
}
);
}
ajaxCall(
'/api/v1/System/Settings/BackgroundTasks/Configuration',
'POST',
function (result) {
getBackgroundTaskTimers();
},
function (error) {
getBackgroundTaskTimers();
},
JSON.stringify(model)
);
}
function defaultTaskTimers() {
var timerValues = document.getElementsByName('settings_tasktimers_enabled');
for (var i = 0; i < timerValues.length; i++) {
timerValues[i].checked = true;
}
var timerValues = document.getElementsByName('settings_tasktimers_values');
for (var i = 0; i < timerValues.length; i++) {
timerValues[i].value = timerValues[i].getAttribute('data-default');
}
var timerValues = document.getElementsByName('settings_alloweddays');
for (var i = 0; i < timerValues.length; i++) {
var defaultSelections = timerValues[i].getAttribute('data-default').split(',');
$(timerValues[i]).val(defaultSelections);
$(timerValues[i]).trigger('change');
}
var timerValues = document.getElementsByName('settings_tasktimers_time');
for (var i = 0; i < timerValues.length; i++) {
timerValues[i].value = timerValues[i].getAttribute('placeholder');
}
saveTaskTimers();
}
// populate the page
getBackgroundTaskTimers();
</script>

View File

@@ -0,0 +1,297 @@
function getBackgroundTaskTimers() {
ajaxCall(
'/api/v1/System/Settings/BackgroundTasks/Configuration',
'GET',
function (result) {
let targetTable = document.getElementById('settings_tasktimers');
targetTable.innerHTML = '';
for (const [key, value] of Object.entries(result)) {
let enabledString = "";
if (value.enabled == true) {
enabledString = 'checked="checked"';
}
// add heading
let serviceHeader = document.createElement('div');
serviceHeader.className = 'section-header';
serviceHeader.innerHTML = GetTaskFriendlyName(value.task);
targetTable.appendChild(serviceHeader);
// create table for each service
let serviceTable = document.createElement('table');
serviceTable.style.width = '100%';
serviceTable.classList.add('section-body');
// add enabled
let newEnabledRow = document.createElement('tr');
let newEnabledTitle = document.createElement('td');
newEnabledTitle.className = 'romcell romcell-headercell';
newEnabledTitle.innerHTML = "Enabled:";
newEnabledRow.appendChild(newEnabledTitle);
let newEnabledContent = document.createElement('td');
newEnabledContent.className = 'romcell';
let newEnabledCheckbox = document.createElement('input');
newEnabledCheckbox.id = 'settings_enabled_' + value.task;
newEnabledCheckbox.name = 'settings_tasktimers_enabled';
newEnabledCheckbox.type = 'checkbox';
newEnabledCheckbox.checked = value.enabled;
newEnabledContent.appendChild(newEnabledCheckbox);
newEnabledRow.appendChild(newEnabledContent);
serviceTable.appendChild(newEnabledRow);
// add interval
let newIntervalRow = document.createElement('tr');
let newIntervalTitle = document.createElement('td');
newIntervalTitle.className = 'romcell romcell-headercell';
newIntervalTitle.innerHTML = "Minimum Interval (Minutes):";
newIntervalRow.appendChild(newIntervalTitle);
let newIntervalContent = document.createElement('td');
newIntervalContent.className = 'romcell';
let newIntervalInput = document.createElement('input');
newIntervalInput.id = 'settings_tasktimers_' + value.task;
newIntervalInput.name = 'settings_tasktimers_values';
newIntervalInput.setAttribute('data-name', value.task);
newIntervalInput.setAttribute('data-default', value.defaultInterval);
newIntervalInput.type = 'number';
newIntervalInput.placeholder = value.defaultInterval;
newIntervalInput.min = value.minimumAllowedInterval;
newIntervalInput.value = value.interval;
newIntervalContent.appendChild(newIntervalInput);
newIntervalRow.appendChild(newIntervalContent);
serviceTable.appendChild(newIntervalRow);
// allowed time periods row
let newTableRowTime = document.createElement('tr');
let rowTimeContentTitle = document.createElement('td');
rowTimeContentTitle.className = 'romcell romcell-headercell';
rowTimeContentTitle.innerHTML = "Allowed Days:";
newTableRowTime.appendChild(rowTimeContentTitle);
let rowTimeContent = document.createElement('td');
// rowTimeContent.setAttribute('colspan', 2);
rowTimeContent.className = 'romcell';
let daySelector = document.createElement('select');
daySelector.id = 'settings_alloweddays_' + value.task;
daySelector.name = 'settings_alloweddays';
daySelector.multiple = 'multiple';
daySelector.setAttribute('data-default', value.defaultAllowedDays.join(","));
daySelector.style.width = '95%';
let days = ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"];
for (let d = 0; d < days.length; d++) {
let dayOpt = document.createElement('option');
dayOpt.value = days[d];
dayOpt.innerHTML = days[d];
if (value.allowedDays.includes(days[d])) {
dayOpt.selected = 'selected';
}
daySelector.appendChild(dayOpt);
}
rowTimeContent.appendChild(daySelector);
$(daySelector).select2({
tags: false
});
newTableRowTime.appendChild(rowTimeContent);
serviceTable.appendChild(newTableRowTime);
// add start and end times
let newTableRowClock = document.createElement('tr');
let rowClockContentTitle = document.createElement('td');
rowClockContentTitle.className = 'romcell romcell-headercell';
rowClockContentTitle.innerHTML = "Time Range:";
newTableRowClock.appendChild(rowClockContentTitle);
let rowClockContent = document.createElement('td');
rowClockContent.className = 'romcell';
// rowClockContent.setAttribute('colspan', 2);
rowClockContent.appendChild(generateTimeDropDowns(value.task, 'Start', value.defaultAllowedStartHours, value.defaultAllowedStartMinutes, value.allowedStartHours, value.allowedStartMinutes));
rowClockContentSeparator = document.createElement('span');
rowClockContentSeparator.innerHTML = '&nbsp;-&nbsp;';
rowClockContent.appendChild(rowClockContentSeparator);
rowClockContent.appendChild(generateTimeDropDowns(value.task, 'End', value.defaultAllowedEndHours, value.defaultAllowedEndMinutes, value.allowedEndHours, value.allowedEndMinutes));
newTableRowClock.appendChild(rowClockContent);
serviceTable.appendChild(newTableRowClock);
// blocks tasks
let newTableRowBlocks = document.createElement('tr');
let rowBlocksContentTitle = document.createElement('td');
rowBlocksContentTitle.className = 'romcell romcell-headercell';
rowBlocksContentTitle.innerHTML = "Blocks:";
newTableRowBlocks.appendChild(rowBlocksContentTitle);
let rowBlocksContent = document.createElement('td');
rowBlocksContent.className = 'romcell';
// rowBlocksContent.setAttribute('colspan', 2);
let blocksString = "";
for (let i = 0; i < value.blocks.length; i++) {
if (blocksString.length > 0) { blocksString += ", "; }
blocksString += GetTaskFriendlyName(value.blocks[i]);
}
if (blocksString.length == 0) { blocksString = 'None'; }
rowBlocksContent.innerHTML = blocksString;
newTableRowBlocks.appendChild(rowBlocksContent);
serviceTable.appendChild(newTableRowBlocks);
// blocked by tasks
let newTableRowBlockedBy = document.createElement('tr');
let rowBlockedByContentTitle = document.createElement('td');
rowBlockedByContentTitle.className = 'romcell romcell-headercell';
rowBlockedByContentTitle.innerHTML = "Blocked By:";
newTableRowBlockedBy.appendChild(rowBlockedByContentTitle);
let rowBlockedByContent = document.createElement('td');
rowBlockedByContent.className = 'romcell';
// rowBlockedByContent.setAttribute('colspan', 2);
let BlockedByString = "";
for (let i = 0; i < value.blockedBy.length; i++) {
if (BlockedByString.length > 0) { BlockedByString += ", "; }
BlockedByString += GetTaskFriendlyName(value.blockedBy[i]);
}
if (BlockedByString.length == 0) { BlockedByString = 'None'; }
rowBlockedByContent.innerHTML = BlockedByString;
newTableRowBlockedBy.appendChild(rowBlockedByContent);
serviceTable.appendChild(newTableRowBlockedBy);
// complete row
targetTable.appendChild(serviceTable);
}
}
);
}
function generateTimeDropDowns(taskName, rangeName, defaultHour, defaultMinute, valueHour, valueMinute) {
let container = document.createElement('div');
container.style.display = 'inline';
let elementName = 'settings_tasktimers_time';
let hourSelector = document.createElement('input');
hourSelector.id = 'settings_tasktimers_' + taskName + '_' + rangeName + '_Hour';
hourSelector.name = elementName;
hourSelector.setAttribute('data-name', taskName);
hourSelector.setAttribute('type', 'number');
hourSelector.setAttribute('min', '0');
hourSelector.setAttribute('max', '23');
hourSelector.setAttribute('placeholder', defaultHour);
hourSelector.value = valueHour;
container.appendChild(hourSelector);
let separator = document.createElement('span');
separator.innerHTML = " : ";
container.appendChild(separator);
let minSelector = document.createElement('input');
minSelector.id = 'settings_tasktimers_' + taskName + '_' + rangeName + '_Minute';
minSelector.name = elementName;
minSelector.setAttribute('type', 'number');
minSelector.setAttribute('min', '0');
minSelector.setAttribute('max', '59');
minSelector.setAttribute('placeholder', defaultMinute);
minSelector.value = valueMinute;
container.appendChild(minSelector);
return container;
}
function saveTaskTimers() {
let timerValues = document.getElementsByName('settings_tasktimers_values');
let model = [];
for (let i = 0; i < timerValues.length; i++) {
let taskName = timerValues[i].getAttribute('data-name');
let taskEnabled = document.getElementById('settings_enabled_' + taskName).checked;
let taskIntervalObj = document.getElementById('settings_tasktimers_' + taskName);
let taskInterval = function () { if (taskIntervalObj.value) { return taskIntervalObj.value; } else { return taskIntervalObj.getAttribute('placeholder'); } };
let taskDaysRaw = $('#settings_alloweddays_' + taskName).select2('data');
let taskDays = [];
if (taskDaysRaw.length > 0) {
for (let d = 0; d < taskDaysRaw.length; d++) {
taskDays.push(taskDaysRaw[d].id);
}
} else {
taskDays.push("Monday");
}
let taskStartHourObj = document.getElementById('settings_tasktimers_' + taskName + '_Start_Hour');
let taskStartMinuteObj = document.getElementById('settings_tasktimers_' + taskName + '_Start_Minute');
let taskEndHourObj = document.getElementById('settings_tasktimers_' + taskName + '_End_Hour');
let taskEndMinuteObj = document.getElementById('settings_tasktimers_' + taskName + '_End_Minute');
let taskStartHour = function () { if (taskStartHourObj.value) { return taskStartHourObj.value; } else { return taskStartHourObj.getAttribute('placeholder'); } };
let taskStartMinute = function () { if (taskStartMinuteObj.value) { return taskStartMinuteObj.value; } else { return taskStartMinuteObj.getAttribute('placeholder'); } };
let taskEndHour = function () { if (taskEndHourObj.value) { return taskEndHourObj.value; } else { return taskEndHourObj.getAttribute('placeholder'); } };
let taskEndMinute = function () { if (taskEndMinuteObj.value) { return taskEndMinuteObj.value; } else { return taskEndMinuteObj.getAttribute('placeholder'); } };
model.push(
{
"task": taskName,
"enabled": taskEnabled,
"interval": taskInterval(),
"allowedDays": taskDays,
"allowedStartHours": taskStartHour(),
"allowedStartMinutes": taskStartMinute(),
"allowedEndHours": taskEndHour(),
"allowedEndMinutes": taskEndMinute()
}
);
}
ajaxCall(
'/api/v1/System/Settings/BackgroundTasks/Configuration',
'POST',
function (result) {
getBackgroundTaskTimers();
},
function (error) {
getBackgroundTaskTimers();
},
JSON.stringify(model)
);
}
function defaultTaskTimers() {
let taskEnabled = document.getElementsByName('settings_tasktimers_enabled');
for (let i = 0; i < taskEnabled.length; i++) {
taskEnabled[i].checked = true;
}
let taskTimerValues = document.getElementsByName('settings_tasktimers_values');
for (let i = 0; i < taskTimerValues.length; i++) {
taskTimerValues[i].value = taskTimerValues[i].getAttribute('data-default');
}
let taskAllowedDays = document.getElementsByName('settings_alloweddays');
for (let i = 0; i < taskAllowedDays.length; i++) {
let defaultSelections = taskAllowedDays[i].getAttribute('data-default').split(',');
$(taskAllowedDays[i]).val(defaultSelections);
$(taskAllowedDays[i]).trigger('change');
}
let taskTimes = document.getElementsByName('settings_tasktimers_time');
for (let i = 0; i < taskTimes.length; i++) {
taskTimes[i].value = taskTimes[i].getAttribute('placeholder');
}
saveTaskTimers();
}

View File

@@ -2,190 +2,105 @@
<h1 id="gametitle_label">Settings</h1>
</div>
<table cellspacing="0" style="width: 100%; vertical-align: top;">
<tr>
<th colspan="2">
<h3>Metadata Sources</h3>
</th>
</tr>
<tr>
<th style="width: 25%;">
Signature Source
</th>
<td>
<input type="radio" name="settings_signaturesource" id="settings_signaturesource_local" value="LocalOnly"
onclick="document.getElementById('settings_hasheoushost_row').style.display = 'none';">
<label for="settings_signaturesource_local">Local Only</label>
</td>
</tr>
<tr>
<td></td>
<td>
<input type="radio" name="settings_signaturesource" id="settings_signaturesource_hasheous" value="Hasheous"
onclick="document.getElementById('settings_hasheoushost_row').style.display = '';">
<label for="settings_signaturesource_hasheous">Hasheous</label>
</td>
</tr>
<tr id="settings_hasheoushost_row" style="display: none;">
<th>
Hasheous Host
</th>
<td>
<input type="url" id="settings_signaturesource_hasheoushost" style="width: 90%;">
</td>
</tr>
<tr>
<th>
<label for="settings_hasheoussubmit">Submit updates to Hasheous when fixing ROM matches</label>
</th>
<td>
<input type="checkbox" id="settings_hasheoussubmit" onchange="toggleHasheousAPIKey(this);">
</td>
</tr>
<tr id="settings_hasheousapikey_row" style="display: none;">
<th>
Hasheous API key
</th>
<td>
<textarea id="settings_hasheousapikey" rows="2" style="width: 90%;"></textarea>
</td>
</tr>
<tr>
<th colspan="2">
<h3>Logging</h3>
</th>
</tr>
<tr>
<th>
Write logs
</th>
<td>
<input type="radio" name="settings_logs_write" id="settings_logs_write_db" value="false"
checked="checked"><label for="settings_logs_write_db"> To database only
(default)</label>
</td>
</tr>
<tr>
<td></td>
<td>
<input type="radio" name="settings_logs_write" id="settings_logs_write_fs" value="true"><label
for="settings_logs_write_fs"> To database and disk</label>
</td>
</tr>
<tr>
<td colspan="2">&nbsp;</td>
</tr>
<tr>
<th>
Minimum log retention (days):
</th>
<td>
<input type="number" min="1" id="settings_logs_retention" />
</td>
</tr>
<tr>
<th colspan="2">
<h3>Emulator</h3>
</th>
</tr>
<tr>
<th><label for="settings_emulator_debug">Enable debug mode</label></th>
<td><input type="checkbox" name="settings_emulator" id="settings_emulator_debug" checked="checked" /></td>
</tr>
<tr>
<td colspan="2" style="text-align: right;">
<button id="settings_tasktimers_new" onclick="setSystemSettings();">Save</button>
</td>
</tr>
</table>
<script type="text/javascript">
function getSystemSettings() {
ajaxCall(
'/api/v1/System/Settings/System',
'GET',
function (result) {
var optionToSelect = 'settings_logs_write_db';
if (result.alwaysLogToDisk == true) {
optionToSelect = 'settings_logs_write_fs';
}
document.getElementById(optionToSelect).checked = true;
document.getElementById('settings_logs_retention').value = result.minimumLogRetentionPeriod;
document.getElementById('settings_emulator_debug').checked = result.emulatorDebugMode;
switch (result.signatureSource.source) {
case "LocalOnly":
document.getElementById('settings_signaturesource_local').checked = true;
break;
case "Hasheous":
document.getElementById('settings_signaturesource_hasheous').checked = true;
document.getElementById('settings_hasheoushost_row').style.display = '';
break;
}
document.getElementById('settings_signaturesource_hasheoushost').value = result.signatureSource.hasheousHost;
let hasheousSubmitCheck = document.getElementById('settings_hasheoussubmit');
if (result.signatureSource.hasheousSubmitFixes == true) {
hasheousSubmitCheck.checked = true;
}
document.getElementById('settings_hasheousapikey').innerHTML = result.signatureSource.hasheousAPIKey;
toggleHasheousAPIKey(hasheousSubmitCheck);
}
);
}
function setSystemSettings() {
var alwaysLogToDisk = false;
if ($("input[type='radio'][name='settings_logs_write']:checked").val() == "true") {
alwaysLogToDisk = true;
}
var retention = document.getElementById('settings_logs_retention');
var retentionValue = 0;
if (retention.value) {
retentionValue = retention.value;
} else {
retentionValue = 7;
}
var model = {
"alwaysLogToDisk": alwaysLogToDisk,
"minimumLogRetentionPeriod": Number(retentionValue),
"emulatorDebugMode": document.getElementById('settings_emulator_debug').checked,
"signatureSource": {
"Source": $("input[type='radio'][name='settings_signaturesource']:checked").val(),
"HasheousHost": document.getElementById('settings_signaturesource_hasheoushost').value,
"HasheousAPIKey": document.getElementById('settings_hasheousapikey').innerHTML,
"HasheousSubmitFixes": document.getElementById('settings_hasheoussubmit').checked
}
};
ajaxCall(
'/api/v1/System/Settings/System',
'POST',
function (result) {
getSystemSettings();
},
function (error) {
getSystemSettings();
},
JSON.stringify(model)
);
}
function toggleHasheousAPIKey(checkbox) {
let settings_hasheousapikey_row = document.getElementById('settings_hasheousapikey_row');
if (checkbox.checked == true) {
settings_hasheousapikey_row.style.display = '';
} else {
settings_hasheousapikey_row.style.display = 'none';
}
}
<div class="section">
<div class="section-header">Metadata Sources</div>
<div class="section-body">
<table>
<tr>
<td style="width: 25%;">
Signature Source
</td>
<td>
<input type="radio" name="settings_signaturesource" id="settings_signaturesource_local"
value="LocalOnly"
onclick="document.getElementById('settings_hasheoushost_row').style.display = 'none';">
<label for="settings_signaturesource_local">Local Only</label>
</td>
</tr>
<tr>
<td></td>
<td>
<input type="radio" name="settings_signaturesource" id="settings_signaturesource_hasheous"
value="Hasheous"
onclick="document.getElementById('settings_hasheoushost_row').style.display = '';">
<label for="settings_signaturesource_hasheous">Hasheous</label>
</td>
</tr>
<tr id="settings_hasheoushost_row" style="display: none;">
<td>
Hasheous Host
</td>
<td>
<input type="url" id="settings_signaturesource_hasheoushost" style="width: 90%;">
</td>
</tr>
<tr>
<td>
<label for="settings_hasheoussubmit">Submit updates to Hasheous when fixing ROM matches</label>
</td>
<td>
<input type="checkbox" id="settings_hasheoussubmit" onchange="toggleHasheousAPIKey(this);">
</td>
</tr>
<tr id="settings_hasheousapikey_row" style="display: none;">
<td>
Hasheous API key
</td>
<td>
<input type="text" id="settings_hasheousapikey" style="width: 90%;">
</td>
</tr>
</table>
</div>
<div class="section-header">Logging</div>
<div class="section-body">
<table>
<tr>
<td style="width: 25%;">
Write logs
</td>
<td>
<input type="radio" name="settings_logs_write" id="settings_logs_write_db" value="false"
checked="checked"><label for="settings_logs_write_db"> To database only
(default)</label>
</td>
</tr>
<tr>
<td></td>
<td>
<input type="radio" name="settings_logs_write" id="settings_logs_write_fs" value="true"><label
for="settings_logs_write_fs"> To database and disk</label>
</td>
</tr>
<tr>
<td colspan="2">&nbsp;</td>
</tr>
<tr>
<td style="width: 25%;">
Minimum log retention (days):
</td>
<td>
<input type="number" min="1" id="settings_logs_retention" />
</td>
</tr>
</table>
</div>
<div class="section-header">Emulator</div>
<div class="section-body">
<table>
<tr>
<td style="width: 25%;"><label for="settings_emulator_debug">Enable debug mode</label></td>
<td><input type="checkbox" name="settings_emulator" id="settings_emulator_debug" checked="checked" />
</td>
</tr>
</table>
</div>
<div style="text-align: right;">
<button id="settings_tasktimers_new" onclick="setSystemSettings();">Save</button>
</div>
</div>
<script>
// kick of page data load
getSystemSettings();
</script>

View File

@@ -0,0 +1,88 @@
function getSystemSettings() {
ajaxCall(
'/api/v1/System/Settings/System',
'GET',
function (result) {
console.log(result);
let optionToSelect = 'settings_logs_write_db';
if (result.alwaysLogToDisk == true) {
optionToSelect = 'settings_logs_write_fs';
}
document.getElementById(optionToSelect).checked = true;
document.getElementById('settings_logs_retention').value = result.minimumLogRetentionPeriod;
document.getElementById('settings_emulator_debug').checked = result.emulatorDebugMode;
switch (result.signatureSource.source) {
case "LocalOnly":
document.getElementById('settings_signaturesource_local').checked = true;
break;
case "Hasheous":
document.getElementById('settings_signaturesource_hasheous').checked = true;
document.getElementById('settings_hasheoushost_row').style.display = '';
break;
}
document.getElementById('settings_signaturesource_hasheoushost').value = result.signatureSource.hasheousHost;
let hasheousSubmitCheck = document.getElementById('settings_hasheoussubmit');
if (result.signatureSource.hasheousSubmitFixes == true) {
hasheousSubmitCheck.checked = true;
}
document.getElementById('settings_hasheousapikey').value = result.signatureSource.hasheousAPIKey;
toggleHasheousAPIKey(hasheousSubmitCheck);
}
);
}
function setSystemSettings() {
let alwaysLogToDisk = false;
if ($("input[type='radio'][name='settings_logs_write']:checked").val() == "true") {
alwaysLogToDisk = true;
}
let retention = document.getElementById('settings_logs_retention');
let retentionValue = 0;
if (retention.value) {
retentionValue = retention.value;
} else {
retentionValue = 7;
}
let model = {
"alwaysLogToDisk": alwaysLogToDisk,
"minimumLogRetentionPeriod": Number(retentionValue),
"emulatorDebugMode": document.getElementById('settings_emulator_debug').checked,
"signatureSource": {
"Source": $("input[type='radio'][name='settings_signaturesource']:checked").val(),
"HasheousHost": document.getElementById('settings_signaturesource_hasheoushost').value,
"HasheousAPIKey": document.getElementById('settings_hasheousapikey').value,
"HasheousSubmitFixes": document.getElementById('settings_hasheoussubmit').checked
}
};
console.log(model);
ajaxCall(
'/api/v1/System/Settings/System',
'POST',
function (result) {
getSystemSettings();
},
function (error) {
getSystemSettings();
},
JSON.stringify(model)
);
}
function toggleHasheousAPIKey(checkbox) {
let settings_hasheousapikey_row = document.getElementById('settings_hasheousapikey_row');
if (checkbox.checked == true) {
settings_hasheousapikey_row.style.display = '';
} else {
settings_hasheousapikey_row.style.display = 'none';
}
}

View File

@@ -2,271 +2,50 @@
<h1 id="gametitle_label">System</h1>
</div>
<h3>Background Tasks</h3>
<div id="system_tasks"></div>
<h3>Usage</h3>
<p><strong>Disk</strong></p>
<div id="system_disks"></div>
<p><strong>Library</strong></p>
<div>
<table cellspacing="0" style="width: 100%;">
<tr>
<td id="system_platforms"></td>
</tr>
<tr>
<td id="system_platforms_legend"></td>
</tr>
</table>
<div class="section">
<div class="section-header">Background Tasks</div>
<div id="system_tasks" class="section-body"></div>
</div>
<p><strong>Database</strong></p>
<div id="system_database"></div>
<h3>Local Database Signatures</h3>
<div id="system_signatures"></div>
<div class="section">
<div class="section-header">Disk Usage</div>
<div class="section-body">
<div id="system_disks"></div>
</div>
</div>
<div class="section">
<div class="section-header">Library</div>
<div class="section-body">
<table cellspacing="0" style="width: 100%;">
<tr>
<td id="system_platforms"></td>
</tr>
<tr>
<td id="system_platforms_legend"></td>
</tr>
</table>
</div>
</div>
<div class="section">
<div class="section-header">Database</div>
<div class="section-body">
<div id="system_database"></div>
</div>
</div>
<div class="section">
<div class="section-header">Local Database Signatures</div>
<div class="section-body">
<div id="system_signatures"></div>
</div>
</div>
<script type="text/javascript">
function SystemLoadStatus() {
ajaxCall('/api/v1.1/BackgroundTasks', 'GET', function (result) {
var newTable = document.createElement('table');
newTable.className = 'romtable';
newTable.setAttribute('cellspacing', 0);
newTable.appendChild(createTableRow(true, ['Task', 'Status', 'Interval<br/>(minutes)', 'Last Run Duration<br />(hh:mm:ss)', '', 'Last Run Start', 'Next Run Start', '']));
if (result) {
for (var i = 0; i < result.length; i++) {
if (result[i].itemState != "Disabled") {
var itemTypeName = GetTaskFriendlyName(result[i].itemType, result[i].options);
var itemStateName;
var itemLastStart;
var hasError = "";
if (result[i].hasErrors) {
if (result[i].hasErrors.errorType != null) {
hasError = " (" + result[i].hasErrors.errorType + ")";
}
}
if (result[i].isBlocked == false) {
switch (result[i].itemState) {
case 'NeverStarted':
itemStateName = "Never started";
itemLastStart = '-';
break;
case 'Stopped':
itemStateName = "Stopped";
itemLastStart = moment(result[i].lastRunTime).format("YYYY-MM-DD h:mm:ss a");
break;
case 'Running':
var progressPercent = "";
if (result[i].currentStateProgress) {
progressPercent = " (" + result[i].currentStateProgress + ")";
}
itemStateName = "Running" + progressPercent;
itemLastStart = moment(result[i].lastRunTime).format("YYYY-MM-DD h:mm:ss a");
break;
default:
itemStateName = "Unknown status";
itemLastStart = moment(result[i].lastRunTime).format("YYYY-MM-DD h:mm:ss a");
break;
}
} else {
itemStateName = "Blocked";
itemLastStart = moment(result[i].lastRunTime).format("YYYY-MM-DD h:mm:ss a");
}
itemStateName += hasError;
var itemInterval = result[i].interval;
var nextRunTime = moment(result[i].nextRunTime).format("YYYY-MM-DD h:mm:ss a");
var startButton = '';
if (userProfile.roles.includes("Admin")) {
if (result[i].allowManualStart == true && !["Running"].includes(result[i].itemState) && result[i].isBlocked == false) {
startButton = "<span id='startProcess' class='romstart' onclick='StartProcess(\"" + result[i].itemType + "\");'>Start</span>";
}
}
if (result[i].allowManualStart == false && result[i].removeWhenStopped == true) {
itemInterval = '';
nextRunTime = '';
}
var logLink = '';
if (result[i].correlationId) {
logLink = '<a href="/index.html?page=settings&sub=logs&correlationid=' + result[i].correlationId + '" class="romlink">View Log</a>';
}
var newRow = [
itemTypeName,
itemStateName,
itemInterval,
new Date(result[i].lastRunDuration * 1000).toISOString().slice(11, 19),
logLink,
itemLastStart,
nextRunTime,
startButton
];
newTable.appendChild(createTableRow(false, newRow, 'romrow', 'romcell'));
}
}
}
var targetDiv = document.getElementById('system_tasks');
targetDiv.innerHTML = '';
targetDiv.appendChild(newTable);
});
}
function SystemLoadSystemStatus() {
ajaxCall('/api/v1.1/System', 'GET', function (result) {
if (result) {
var totalLibrarySpace = 0;
// disks
var newTable = document.createElement('table');
newTable.className = 'romtable';
newTable.setAttribute('cellspacing', 0);
newTable.appendChild(createTableRow(true, ['Path', 'Library Size <div id="disk_LibSize" style="width: 10px; height: 10px; background-color: green;"></div>', 'Other <div id="disk_OtherSize" style="width: 10px; height: 10px; background-color: lightgreen;"></div>', 'Total Size <div id="disk_FreeSize" style="width: 10px; height: 10px; background-color: lightgray;"></div>']));
for (var i = 0; i < result.paths.length; i++) {
var spaceUsedByLibrary = result.paths[i].spaceUsed;
totalLibrarySpace += spaceUsedByLibrary;
var spaceUsedByOthers = result.paths[i].totalSpace - result.paths[i].spaceAvailable;
var newRow = [
result.paths[i].libraryPath,
formatBytes(spaceUsedByLibrary),
formatBytes(spaceUsedByOthers),
formatBytes(result.paths[i].totalSpace)
];
newTable.appendChild(createTableRow(false, newRow, 'romrow', 'romcell'));
var spaceRow = document.createElement('tr');
var spaceCell = document.createElement('td');
spaceCell.setAttribute('colspan', 4);
spaceCell.appendChild(BuildSpaceBar(spaceUsedByLibrary, spaceUsedByOthers, result.paths[i].totalSpace));
spaceRow.appendChild(spaceCell);
newTable.appendChild(spaceRow);
}
var targetDiv = document.getElementById('system_disks');
targetDiv.innerHTML = '';
targetDiv.appendChild(newTable);
BuildLibraryStatisticsBar(document.getElementById('system_platforms'), document.getElementById('system_platforms_legend'), result.platformStatistics, totalLibrarySpace);
// database
var newDbTable = document.createElement('table');
newDbTable.className = 'romtable';
newDbTable.setAttribute('cellspacing', 0);
newDbTable.appendChild(createTableRow(false, ['Database Size', formatBytes(result.databaseSize)]));
var targetDbDiv = document.getElementById('system_database');
targetDbDiv.innerHTML = '';
targetDbDiv.appendChild(newDbTable);
}
});
}
function BuildSpaceBar(LibrarySize, OtherSize, TotalSize) {
var newTable = document.createElement('table');
newTable.setAttribute('cellspacing', 0);
newTable.setAttribute('style', 'width: 100%; height: 10px;');
var newRow = document.createElement('tr');
var LibrarySizePercent = Math.floor(LibrarySize / TotalSize * 100);
var OtherSizePercent = Math.floor(OtherSize / TotalSize * 100);
var FreeSizePercent = Math.floor((LibrarySize + OtherSize) / TotalSize * 100);
var LibraryCell = document.createElement('td');
LibraryCell.setAttribute('style', 'width: ' + LibrarySizePercent + '%; background-color: green;');
var OtherCell = document.createElement('td');
OtherCell.setAttribute('style', 'width: ' + OtherSizePercent + '%; background-color: lightgreen;');
var FreeCell = document.createElement('td');
FreeCell.setAttribute('style', 'width: ' + FreeSizePercent + '%; background-color: lightgray;');
newRow.appendChild(LibraryCell);
newRow.appendChild(OtherCell);
newRow.appendChild(FreeCell);
newTable.appendChild(newRow);
return newTable;
}
function BuildLibraryStatisticsBar(TargetObject, TargetObjectLegend, LibraryStatistics, LibrarySize) {
TargetObject.innerHTML = '';
TargetObjectLegend.innerHTML = '';
var newTable = document.createElement('table');
newTable.setAttribute('cellspacing', 0);
newTable.setAttribute('style', 'width: 100%; height: 10px;');
var newRow = document.createElement('tr');
for (var i = 0; i < LibraryStatistics.length; i++) {
var platformSizePercent = LibraryStatistics[i].totalSize / LibrarySize * 100;
var platformSizeColour = intToRGB(hashCode(LibraryStatistics[i].platform));
var newCell = document.createElement('td');
newCell.setAttribute('style', 'min-width: 2px; width: ' + platformSizePercent + '%; background-color: #' + platformSizeColour);
newRow.appendChild(newCell);
var legend = document.createElement('div');
legend.className = 'legend_box';
var legendColour = document.createElement('div');
legendColour.className = 'legend_colour';
legendColour.setAttribute('style', 'background-color: #' + platformSizeColour + ';');
var legendLabel = document.createElement('div');
legendLabel.className = 'legend_label';
legendLabel.innerHTML = LibraryStatistics[i].platform + '<br />' + formatBytes(LibraryStatistics[i].totalSize) + '<br />Images: ' + LibraryStatistics[i].romCount;
legend.appendChild(legendColour);
legend.appendChild(legendLabel);
TargetObjectLegend.appendChild(legend);
}
newTable.appendChild(newRow);
TargetObject.appendChild(newTable);
}
function SystemSignaturesStatus() {
ajaxCall('/api/v1.1/Signatures/Status', 'GET', function (result) {
var newTable = document.createElement('table');
newTable.className = 'romtable';
newTable.setAttribute('cellspacing', 0);
newTable.appendChild(createTableRow(true, ['Sources', 'Platforms', 'Games', 'ROMs']));
if (result) {
var newRow = [
result.sources,
result.platforms,
result.games,
result.roms
];
newTable.appendChild(createTableRow(false, newRow, 'romrow', 'romcell'));
}
var targetDiv = document.getElementById('system_signatures');
targetDiv.innerHTML = '';
targetDiv.appendChild(newTable);
});
}
function StartProcess(itemType) {
ajaxCall('/api/v1.1/BackgroundTasks/' + itemType + '?ForceRun=true', 'GET', function (result) {
SystemLoadStatus();
});
}
// Load the system status
SystemLoadStatus();
setInterval(SystemLoadStatus, 3000);
setInterval(SystemLoadStatus, 2000);
SystemLoadSystemStatus();
setInterval(SystemLoadSystemStatus, 60000);
SystemSignaturesStatus();

View File

@@ -0,0 +1,297 @@
function SystemLoadStatus() {
ajaxCall('/api/v1.1/BackgroundTasks', 'GET', function (result) {
let newTable = document.createElement('table');
newTable.className = 'romtable';
newTable.setAttribute('cellspacing', 0);
newTable.appendChild(createTableRow(true, ['Task', 'Status', '', '', 'Interval<br/>(minutes)', 'Last Run Duration<br />(hh:mm:ss)', 'Last Run Start', 'Next Run Start', '']));
if (result) {
for (let i = 0; i < result.length; i++) {
if (result[i].itemState != "Disabled") {
let itemTypeName = GetTaskFriendlyName(result[i].itemType, result[i].options);
let itemStateName;
let itemLastStart;
let hasError = "";
if (result[i].hasErrors) {
if (result[i].hasErrors.errorType != null) {
// hasError = " (" + result[i].hasErrors.errorType + ")";
hasError = "<img src='/images/" + result[i].hasErrors.errorType + ".svg' class='banner_button_image' style='padding-top: 5px;' title='" + result[i].hasErrors.errorType + "'>";
}
}
if (result[i].isBlocked == false) {
if (result[i].force == true && result[i].itemState != "Running") {
itemStateName = "<div>Pending </div><div><progress></progress></div>";
itemLastStart = '-';
} else {
switch (result[i].itemState) {
case 'NeverStarted':
itemStateName = "Never started";
itemLastStart = moment(result[i].lastRunTime).format("YYYY-MM-DD h:mm:ss a");
break;
case 'Stopped':
itemStateName = "Stopped";
itemLastStart = moment(result[i].lastRunTime).format("YYYY-MM-DD h:mm:ss a");
break;
case 'Running':
itemStateName = "Running";
if (result[i].currentStateProgress) {
if (result[i].currentStateProgress.includes(" of ")) {
let progressParts = result[i].currentStateProgress.split(" of ");
itemStateName = "<div>Running " + result[i].currentStateProgress + "</div><div><progress value=\"" + progressParts[0] + "\" max=\"" + progressParts[1] + "\">" + result[i].currentStateProgress + "</progress></div>";
} else {
itemStateName = "Running (" + result[i].currentStateProgress + ")";
}
}
itemLastStart = moment(result[i].lastRunTime).format("YYYY-MM-DD h:mm:ss a");
break;
default:
itemStateName = "Unknown status";
itemLastStart = moment(result[i].lastRunTime).format("YYYY-MM-DD h:mm:ss a");
break;
}
}
} else {
itemStateName = "Blocked";
itemLastStart = moment(result[i].lastRunTime).format("YYYY-MM-DD h:mm:ss a");
}
let itemInterval = result[i].interval;
let nextRunTime = moment(result[i].nextRunTime).format("YYYY-MM-DD h:mm:ss a");
let startButton = '';
if (userProfile.roles.includes("Admin")) {
if (result[i].force == false) {
if (result[i].allowManualStart == true && !["Running"].includes(result[i].itemState) && result[i].isBlocked == false) {
startButton = "<img id='startProcess' class='taskstart' src='/images/start-task.svg' onclick='StartProcess(\"" + result[i].itemType + "\");' title='Start'>";
}
}
}
if (result[i].allowManualStart == false && result[i].removeWhenStopped == true) {
itemInterval = '';
nextRunTime = '';
}
let logLink = '';
if (result[i].correlationId) {
logLink = '<a href="/index.html?page=settings&sub=logs&correlationid=' + result[i].correlationId + '" class="romlink">Logs</a>';
}
let newRow = [
itemTypeName,
itemStateName,
hasError,
logLink,
itemInterval,
new Date(result[i].lastRunDuration * 1000).toISOString().slice(11, 19),
itemLastStart,
nextRunTime,
startButton
];
newTable.appendChild(createTableRow(false, newRow, 'romrow taskrow', 'romcell'));
}
}
}
let targetDiv = document.getElementById('system_tasks');
targetDiv.innerHTML = '';
targetDiv.appendChild(newTable);
});
}
function SystemLoadSystemStatus() {
ajaxCall('/api/v1.1/System', 'GET', function (result) {
if (result) {
let totalLibrarySpace = 0;
// disks
let newTable = document.createElement('table');
newTable.className = 'romtable';
newTable.setAttribute('cellspacing', 0);
newTable.appendChild(createTableRow(true, ['Path', 'Library Size <div id="disk_LibSize" style="width: 10px; height: 10px; background-color: green;"></div>', 'Other <div id="disk_OtherSize" style="width: 10px; height: 10px; background-color: lightgreen;"></div>', 'Total Size <div id="disk_FreeSize" style="width: 10px; height: 10px; background-color: lightgray;"></div>']));
for (let i = 0; i < result.paths.length; i++) {
let spaceUsedByLibrary = result.paths[i].spaceUsed;
totalLibrarySpace += spaceUsedByLibrary;
let spaceUsedByOthers = result.paths[i].totalSpace - result.paths[i].spaceAvailable;
let libraryRow = document.createElement('tbody');
libraryRow.className = 'romrow';
let titleRow = document.createElement('tr');
let titleCell = document.createElement('td');
titleCell.setAttribute('colspan', 4);
titleCell.innerHTML = '<strong>' + result.paths[i].name + '</strong>';
titleCell.className = 'romcell';
titleRow.appendChild(titleCell);
libraryRow.appendChild(titleRow);
let newRow = [
result.paths[i].libraryPath,
formatBytes(spaceUsedByLibrary),
formatBytes(spaceUsedByOthers),
formatBytes(result.paths[i].totalSpace)
];
libraryRow.appendChild(createTableRow(false, newRow, '', 'romcell'));
let spaceRow = document.createElement('tr');
let spaceCell = document.createElement('td');
spaceCell.setAttribute('colspan', 4);
spaceCell.appendChild(BuildSpaceBar(spaceUsedByLibrary, spaceUsedByOthers, result.paths[i].totalSpace));
spaceRow.appendChild(spaceCell);
libraryRow.appendChild(spaceRow);
newTable.appendChild(libraryRow);
}
let targetDiv = document.getElementById('system_disks');
targetDiv.innerHTML = '';
targetDiv.appendChild(newTable);
BuildLibraryStatisticsBar(document.getElementById('system_platforms'), document.getElementById('system_platforms_legend'), result.platformStatistics, totalLibrarySpace);
// database
let newDbTable = document.createElement('table');
newDbTable.className = 'romtable';
newDbTable.setAttribute('cellspacing', 0);
newDbTable.appendChild(createTableRow(false, ['Database Size', formatBytes(result.databaseSize)]));
let targetDbDiv = document.getElementById('system_database');
targetDbDiv.innerHTML = '';
targetDbDiv.appendChild(newDbTable);
}
});
}
function BuildSpaceBar(LibrarySize, OtherSize, TotalSize) {
let newTable = document.createElement('table');
newTable.setAttribute('cellspacing', 0);
newTable.setAttribute('style', 'width: 100%; height: 10px;');
let newRow = document.createElement('tr');
let LibrarySizePercent = Math.floor(LibrarySize / TotalSize * 100);
let OtherSizePercent = Math.floor(OtherSize / TotalSize * 100);
let FreeSizePercent = Math.floor((LibrarySize + OtherSize) / TotalSize * 100);
let LibraryCell = document.createElement('td');
LibraryCell.setAttribute('style', 'width: ' + LibrarySizePercent + '%; background-color: green;');
let OtherCell = document.createElement('td');
OtherCell.setAttribute('style', 'width: ' + OtherSizePercent + '%; background-color: lightgreen;');
let FreeCell = document.createElement('td');
FreeCell.setAttribute('style', 'width: ' + FreeSizePercent + '%; background-color: lightgray;');
newRow.appendChild(LibraryCell);
newRow.appendChild(OtherCell);
newRow.appendChild(FreeCell);
newTable.appendChild(newRow);
return newTable;
}
function BuildLibraryStatisticsBar(TargetObject, TargetObjectLegend, LibraryStatistics, LibrarySize) {
TargetObject.innerHTML = '';
TargetObjectLegend.innerHTML = '';
let newTable = document.createElement('div');
newTable.setAttribute('cellspacing', 0);
newTable.setAttribute('style', 'width: 100%; height: 10px;');
let newRow = document.createElement('div');
newRow.setAttribute('style', 'display: flex; width: 100%;');
for (let i = 0; i < LibraryStatistics.length; i++) {
let platformSizePercent = LibraryStatistics[i].totalSize / LibrarySize * 100;
let platformSizeColour = intToRGB(hashCode(LibraryStatistics[i].platform));
let newCell = document.createElement('div');
let segmentId = 'platform_' + LibraryStatistics[i].platform;
newCell.id = segmentId;
newCell.setAttribute('style', 'display: inline; height: 10px; min-width: 1px; width: ' + platformSizePercent + '%; background-color: #' + platformSizeColour);
// newCell.innerHTML = '&nbsp;';
newRow.appendChild(newCell);
let legend = document.createElement('div');
legend.id = 'legend_' + LibraryStatistics[i].platform;
legend.className = 'legend_box';
let legendColour = document.createElement('div');
let colourId = 'colour_' + LibraryStatistics[i].platform;
legendColour.id = colourId;
legendColour.className = 'legend_colour';
legendColour.setAttribute('style', 'background-color: #' + platformSizeColour + ';');
let legendLabel = document.createElement('div');
legendLabel.className = 'legend_label';
legendLabel.innerHTML = '<strong>' + LibraryStatistics[i].platform + '</strong><br />' + formatBytes(LibraryStatistics[i].totalSize) + '<br />ROMs: ' + LibraryStatistics[i].romCount;
// event listeners
legend.addEventListener('mouseenter', function () {
let segment = document.getElementById(segmentId);
segment.style.outline = '2px solid #' + platformSizeColour;
segment.style.outlineOffset = '0px';
segment.style.zIndex = '1';
segment.style.boxShadow = '0px 0px 10px 0px #' + platformSizeColour;
let legendColour = document.getElementById(colourId);
legendColour.style.outline = '2px solid #' + platformSizeColour;
legendColour.style.outlineOffset = '0px';
legendColour.style.zIndex = '1';
legendColour.style.boxShadow = '0px 0px 10px 0px #' + platformSizeColour;
});
legend.addEventListener('mouseleave', function () {
let segment = document.getElementById(segmentId);
segment.style.outline = 'none';
segment.style.outlineOffset = '0px';
segment.style.zIndex = '0';
segment.style.boxShadow = 'none';
let legendColour = document.getElementById(colourId);
legendColour.style.outline = 'none';
legendColour.style.outlineOffset = '0px';
legendColour.style.zIndex = '0';
legendColour.style.boxShadow = 'none';
});
legend.appendChild(legendColour);
legend.appendChild(legendLabel);
TargetObjectLegend.appendChild(legend);
}
newTable.appendChild(newRow);
TargetObject.appendChild(newTable);
}
function SystemSignaturesStatus() {
ajaxCall('/api/v1.1/Signatures/Status', 'GET', function (result) {
let newTable = document.createElement('table');
newTable.className = 'romtable';
newTable.setAttribute('cellspacing', 0);
newTable.appendChild(createTableRow(true, ['Sources', 'Platforms', 'Games', 'ROMs']));
if (result) {
let newRow = [
result.sources,
result.platforms,
result.games,
result.roms
];
newTable.appendChild(createTableRow(false, newRow, 'romrow', 'romcell'));
}
let targetDiv = document.getElementById('system_signatures');
targetDiv.innerHTML = '';
targetDiv.appendChild(newTable);
});
}
function StartProcess(itemType) {
ajaxCall('/api/v1.1/BackgroundTasks/' + itemType + '?ForceRun=true', 'GET', function (result) {
SystemLoadStatus();
});
}

View File

@@ -2,100 +2,19 @@
<h1 id="gametitle_label">Users</h1>
</div>
<button id="settings_users_new" value="New User" style="float: right;" onclick="showSubDialog('settingsusernew');">New User</button>
<div id="settings_users_table_container">
<div class="section">
<div class="section-body">
<div id="settings_users_table_container">
</div>
<div style="text-align: right;"><button id="settings_users_new" value="New User">New
User</button>
</div>
</div>
</div>
<script type="text/javascript">
function GetUsers() {
var targetDiv = document.getElementById('settings_users_table_container');
targetDiv.innerHTML = '';
ajaxCall(
'/api/v1.1/Account/Users',
'GET',
function(result) {
var newTable = document.createElement('table');
newTable.className = 'romtable';
newTable.style.width = '100%';
newTable.cellSpacing = 0;
newTable.appendChild(
createTableRow(
true,
[
'',
'Email',
'Role',
'Age Restriction',
''
],
'',
''
)
);
for (var i = 0; i < result.length; i++) {
var userAvatar = document.createElement('img');
userAvatar.className = "user_list_icon";
if (result[i].avatar != "00000000-0000-0000-0000-000000000000") {
userAvatar.setAttribute("src", "/api/v1.1/Account/Avatar/" + result[i].avatar + ".jpg");
} else {
userAvatar.setAttribute("src", "/images/user.svg");
userAvatar.classList.add("user_list_icon_reversed");
}
var roleDiv = document.createElement('div');
var roleItem = CreateBadge(result[i].highestRole);
roleDiv.appendChild(roleItem);
var ageRestrictionPolicyDescription = document.createElement('div');
if (result[i].securityProfile != null) {
if (result[i].securityProfile.ageRestrictionPolicy != null) {
var IncludeUnratedText = '';
if (result[i].securityProfile.ageRestrictionPolicy.includeUnrated == true) {
IncludeUnratedText = " &#43; Unclassified titles";
}
var restrictionText = result[i].securityProfile.ageRestrictionPolicy.maximumAgeRestriction + IncludeUnratedText;
ageRestrictionPolicyDescription = CreateBadge(restrictionText);
}
}
var editButton = '';
var deleteButton = '';
if (userProfile.userId != result[i].id) {
editButton = '<a href="#" onclick="showDialog(\'settingsuseredit\', \'' + result[i].id + '\');" class="romlink"><img src="/images/edit.svg" class="banner_button_image" alt="Edit" title="Edit" /></a>';
deleteButton = '<a href="#" onclick="showSubDialog(\'settingsuserdelete\', \'' + result[i].id + '\');" class="romlink"><img src="/images/delete.svg" class="banner_button_image" alt="Delete" title="Delete" /></a>';
}
newTable.appendChild(
createTableRow(
false,
[
userAvatar,
result[i].emailAddress,
roleDiv,
ageRestrictionPolicyDescription,
'<div style="text-align: right;">' + editButton + deleteButton + '</div>'
],
'romrow',
'romcell'
)
);
}
targetDiv.appendChild(newTable);
}
);
}
// Load the users table
SetupPage();
GetUsers();
</script>

View File

@@ -0,0 +1,590 @@
function SetupPage() {
// set up new user button
let newUserButton = document.getElementById('settings_users_new');
newUserButton.addEventListener('click', function () {
let userNew = new UserNew();
userNew.open();
});
}
function GetUsers() {
console.log("Loading users...");
let targetDiv = document.getElementById('settings_users_table_container');
targetDiv.innerHTML = '';
ajaxCall(
'/api/v1.1/Account/Users',
'GET',
function (result) {
let newTable = document.createElement('table');
newTable.className = 'romtable';
newTable.style.width = '100%';
newTable.cellSpacing = 0;
newTable.appendChild(
createTableRow(
true,
[
'',
'Email',
'Role',
'Age Restriction',
''
],
'',
''
)
);
for (let i = 0; i < result.length; i++) {
let userAvatar = new Avatar(result[i].profileId, 32, 32, true);
userAvatar.classList.add("user_list_icon");
let roleDiv = document.createElement('div');
let roleItem = CreateBadge(result[i].highestRole);
roleDiv.appendChild(roleItem);
let ageRestrictionPolicyDescription = document.createElement('div');
if (result[i].securityProfile != null) {
if (result[i].securityProfile.ageRestrictionPolicy != null) {
let IncludeUnratedText = '';
if (result[i].securityProfile.ageRestrictionPolicy.includeUnrated == true) {
IncludeUnratedText = " &#43; Unclassified titles";
}
let restrictionText = result[i].securityProfile.ageRestrictionPolicy.maximumAgeRestriction + IncludeUnratedText;
ageRestrictionPolicyDescription = CreateBadge(restrictionText);
}
}
let controls = document.createElement('div');
controls.style.textAlign = 'right';
let editButton = '';
let deleteButton = '';
if (userProfile.userId != result[i].id) {
editButton = document.createElement('a');
editButton.href = '#';
editButton.addEventListener('click', () => {
// showDialog('settingsuseredit', result[i].id);
let userEdit = new UserEdit(result[i].id, GetUsers);
userEdit.open();
});
editButton.classList.add('romlink');
let editButtonImage = document.createElement('img');
editButtonImage.src = '/images/edit.svg';
editButtonImage.classList.add('banner_button_image');
editButtonImage.alt = 'Edit';
editButtonImage.title = 'Edit';
editButton.appendChild(editButtonImage);
controls.appendChild(editButton);
deleteButton = document.createElement('a');
deleteButton.href = '#';
deleteButton.addEventListener('click', () => {
let warningDialog = new MessageBox("Delete User", "Are you sure you want to delete this user?<br /><br /><strong>Warning</strong>: This cannot be undone!");
warningDialog.addButton(new ModalButton("OK", 2, warningDialog, async (callingObject) => {
fetch("/api/v1.1/Account/Users/" + result[i].id, {
method: 'DELETE'
}).then(async response => {
if (response.ok) {
GetUsers();
callingObject.msgDialog.close();
} else {
let result = await response.json();
let warningDialog = new MessageBox("Delete User Error", "An error occurred while deleting the user.");
warningDialog.open();
}
});
}));
warningDialog.addButton(new ModalButton("Cancel", 0, warningDialog, async (callingObject) => {
callingObject.msgDialog.close();
}));
warningDialog.open();
});
deleteButton.classList.add('romlink');
let deleteButtonImage = document.createElement('img');
deleteButtonImage.src = '/images/delete.svg';
deleteButtonImage.classList.add('banner_button_image');
deleteButtonImage.alt = 'Delete';
deleteButtonImage.title = 'Delete';
deleteButton.appendChild(deleteButtonImage);
controls.appendChild(deleteButton);
}
newTable.appendChild(
createTableRow(
false,
[
userAvatar,
result[i].emailAddress,
roleDiv,
ageRestrictionPolicyDescription,
controls
],
'romrow',
'romcell'
)
);
}
targetDiv.appendChild(newTable);
}
);
}
class UserNew {
constructor() {
}
async open() {
// Create the modal
this.dialog = await new Modal("usernew");
await this.dialog.BuildModal();
// setup the dialog
this.dialog.modalElement.querySelector('#modal-header-text').innerHTML = "New User";
this.dialog.modalElement.style = 'width: 550px; height: 380px; min-width: unset; min-height: unset; max-width: unset; max-height: unset;';
// setup email check
this.email = this.dialog.modalElement.querySelector('#email-address');
this.email_error = this.dialog.modalElement.querySelector('#email-error');
this.EmailCheck = new EmailCheck(this.email, this.email_error);
// setup password check
this.password_new = this.dialog.modalElement.querySelector('#new-password');
this.password_confirm = this.dialog.modalElement.querySelector('#confirm-new-password');
this.password_error = this.dialog.modalElement.querySelector('#password-error');
this.PasswordCheck = new PasswordCheck(this.password_new, this.password_confirm, this.password_error);
// add the ok button
let okButton = new ModalButton("OK", 1, this, async function (callingObject) {
if (!await EmailCheck.CheckEmail(callingObject.EmailCheck, callingObject.email)) {
// display an error
let warningDialog = new MessageBox("New User Error", "Invalid email address. Please correct the errors before continuing.");
warningDialog.open();
return;
}
if (!PasswordCheck.CheckPasswords(callingObject.PasswordCheck, callingObject.password_new, callingObject.password_confirm)) {
// display an error
let warningDialog = new MessageBox("New User Error", "The password doesn't meet the requirements. Please correct the errors before continuing.");
warningDialog.open();
return;
}
// create the new user
var model = {
"userName": callingObject.email.value,
"email": callingObject.email.value,
"password": callingObject.password_new.value,
"confirmPassword": callingObject.password_confirm.value
}
fetch("/api/v1.1/Account/Users", {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(model)
}).then(async response => {
if (response.ok) {
let result = await response.json();
GetUsers();
callingObject.dialog.close();
} else {
let result = await response.json();
let warningDialog = new MessageBox("New User Error", "An error occurred while creating the user. Check that the email address is valid and the password meets the requirements.");
warningDialog.open();
}
});
});
this.dialog.addButton(okButton);
// add the cancel button
let cancelButton = new ModalButton("Cancel", 0, this, async function (callingObject) {
callingObject.dialog.close();
});
this.dialog.addButton(cancelButton);
// show the dialog
await this.dialog.open();
}
}
class UserEdit {
constructor(UserId, OkCallback, CancelCallback) {
this.userId = UserId;
this.okCallback = OkCallback;
this.cancelCallback = CancelCallback;
}
async open() {
// Create the modal
this.dialog = await new Modal("useredit");
await this.dialog.BuildModal();
await fetch("/api/v1.1/Account/Users/" + this.userId, {
method: 'GET'
}).then(async response => {
if (response.ok) {
let result = await response.json();
this.user = result;
} else {
let result = await response.json();
let warningDialog = new MessageBox("Edit User Error", "An error occurred while retrieving the user.");
warningDialog.open();
}
});
// setup the dialog
if (this.user.profileId == "00000000-0000-0000-0000-000000000000") {
this.dialog.modalElement.querySelector('#modal-header-text').innerHTML = this.user.emailAddress;
} else {
await fetch("/api/v1.1/UserProfile/" + this.user.profileId, {
method: 'GET'
}).then(async response => {
if (response.ok) {
let result = await response.json();
this.profile = result;
this.dialog.modalElement.querySelector('#modal-header-text').innerHTML = this.profile.displayName + ' (' + this.user.emailAddress + ')';
} else {
this.dialog.modalElement.querySelector('#modal-header-text').innerHTML = this.user.emailAddress;
}
});
}
// setup general page
this.dialog.modalElement.querySelector('#user-id').innerHTML = this.user.id;
let userProfileCard = new ProfileCard(this.user.profileId, true);
if (this.user.lockoutEnabled === true) {
this.dialog.modalElement.querySelector('#user-lockedout').innerHTML = 'Locked';
this.dialog.modalElement.querySelector('#user-lockedout').style.backgroundColor = 'red';
this.dialog.modalElement.querySelector('#user-lockedout-end').innerHTML = 'until ' + new Date(this.user.lockoutEnd).toLocaleString();
} else {
this.dialog.modalElement.querySelector('#user-lockedout').innerHTML = 'Unlocked';
this.dialog.modalElement.querySelector('#user-lockedout').style.backgroundColor = '';
this.dialog.modalElement.querySelector('#user-lockedout-end').innerHTML = '';
}
this.dialog.modalElement.querySelector('#user-profile-card').appendChild(userProfileCard);
// set user role
this.role_Player = this.dialog.modalElement.querySelector('#settings_user_role_player');
this.role_Player.addEventListener('change', () => {
this.UpdateRolePermissionsDisplay();
});
this.role_Gamer = this.dialog.modalElement.querySelector('#settings_user_role_gamer');
this.role_Gamer.addEventListener('change', () => {
this.UpdateRolePermissionsDisplay();
});
this.role_Admin = this.dialog.modalElement.querySelector('#settings_user_role_admin');
this.role_Admin.addEventListener('change', () => {
this.UpdateRolePermissionsDisplay();
});
this.dialog.modalElement.querySelector('#settings_user_role_' + this.user.highestRole.toLowerCase()).checked = true;
this.UpdateRolePermissionsDisplay();
this.rolePermTable = this.dialog.modalElement.querySelector('#role-permissions-table');
this.rolePermCover = this.dialog.modalElement.querySelector('#role-permissions-expand');
this.rolePermLink = this.dialog.modalElement.querySelector('#role-permissions-expand-link');
this.rolePermLink.addEventListener('click', () => {
if (Array.from(this.rolePermTable.classList).includes('collapsed')) {
this.rolePermTable.classList.remove('collapsed');
this.rolePermTable.classList.add('expanded');
this.rolePermCover.classList.remove('collapsed');
this.rolePermCover.classList.add('expanded');
this.rolePermLink.innerHTML = 'Hide details...';
} else {
this.rolePermTable.classList.remove('expanded');
this.rolePermTable.classList.add('collapsed');
this.rolePermCover.classList.remove('expanded');
this.rolePermCover.classList.add('collapsed');
this.rolePermLink.innerHTML = 'Show details...';
}
});
// setup age restriction tab
let ageRestrictionPolicyBox = this.dialog.modalElement.querySelector('#settings_user_agerestrictions');
let ageRestrictionPolicyTable = document.createElement('table');
for (let ageGroup in AgeRatingGroups) {
let tRow = document.createElement('tr');
let tCell = document.createElement('td');
let ageGroupRadio = document.createElement('input');
ageGroupRadio.type = 'radio';
ageGroupRadio.name = 'ageGroup';
ageGroupRadio.value = ageGroup;
ageGroupRadio.id = 'ageGroup_' + ageGroup;
ageGroupRadio.addEventListener('change', () => {
this.UpdateAssignedAgeGroupDisplay();
});
tCell.appendChild(ageGroupRadio);
let ageGroupLabel = document.createElement('label');
ageGroupLabel.htmlFor = 'ageGroup_' + ageGroup;
ageGroupLabel.innerHTML = ageGroup;
tCell.appendChild(ageGroupLabel);
tRow.appendChild(tCell);
ageRestrictionPolicyTable.appendChild(tRow);
}
// add allow unclassified titles checkbox
let tRow = document.createElement('tr');
let tCell = document.createElement('td');
let includeUnratedCheckbox = document.createElement('input');
includeUnratedCheckbox.type = 'checkbox';
includeUnratedCheckbox.id = 'includeUnrated';
includeUnratedCheckbox.addEventListener('change', () => {
this.UpdateAssignedAgeGroupDisplay();
});
tCell.appendChild(includeUnratedCheckbox);
let includeUnratedLabel = document.createElement('label');
includeUnratedLabel.htmlFor = 'includeUnrated';
includeUnratedLabel.innerHTML = 'Include unrated titles';
tCell.appendChild(includeUnratedLabel);
tRow.appendChild(tCell);
ageRestrictionPolicyTable.appendChild(tRow);
ageRestrictionPolicyBox.appendChild(ageRestrictionPolicyTable);
this.dialog.modalElement.querySelector('#ageGroup_' + this.user.securityProfile.ageRestrictionPolicy.maximumAgeRestriction).checked = true;
if (this.user.securityProfile.ageRestrictionPolicy.includeUnrated === true) {
this.dialog.modalElement.querySelector('#includeUnrated').checked = true;
}
this.UpdateAssignedAgeGroupDisplay();
this.agePermTable = this.dialog.modalElement.querySelector('#settings_user_agerestrictions_preview');
this.agePermCover = this.dialog.modalElement.querySelector('#settings_user_agerestrictions_expand');
this.agePermLink = this.dialog.modalElement.querySelector('#settings_user_agerestrictions_expand-link');
this.agePermLink.addEventListener('click', () => {
if (Array.from(this.agePermTable.classList).includes('collapsed')) {
this.agePermTable.classList.remove('collapsed');
this.agePermTable.classList.add('expanded');
this.agePermCover.classList.remove('collapsed');
this.agePermCover.classList.add('expanded');
this.agePermLink.innerHTML = 'Hide details...';
} else {
this.agePermTable.classList.remove('expanded');
this.agePermTable.classList.add('collapsed');
this.agePermCover.classList.remove('expanded');
this.agePermCover.classList.add('collapsed');
this.agePermLink.innerHTML = 'Show details...';
}
});
// set up the password change form
this.password_new = this.dialog.modalElement.querySelector('#new-password');
this.password_confirm = this.dialog.modalElement.querySelector('#confirm-new-password');
this.password_error = this.dialog.modalElement.querySelector('#password-error');
this.PasswordCheck = new PasswordCheck(this.password_new, this.password_confirm, this.password_error);
// create the ok button
let okButton = new ModalButton("OK", 1, this, async function (callingObject) {
// check if a new password has been entered
if (callingObject.password_new.value.length > 0 && callingObject.password_confirm.value.length > 0) {
// check if the new password meets the rules
if (!PasswordCheck.CheckPasswords(callingObject.PasswordCheck, callingObject.password_new, callingObject.password_confirm)) {
// display an error
let warningDialog = new MessageBox("Password Reset Error", "The new password does not meet the requirements.");
warningDialog.open();
return;
}
// requirements met, reset the password
let model = {
newPassword: callingObject.password_new.value,
confirmPassword: callingObject.password_confirm.value
};
let changeSuccessfull = false;
await fetch("/api/v1.1/Account/Users/" + callingObject.userId + "/Password", {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(model)
}).then(async response => {
if (!response.ok) {
// handle the error
console.error("Error updating password:");
console.error(response);
let warningDialog = new MessageBox("Password Reset Error", "The password reset failed. Check the current password and try again.");
warningDialog.open();
changeSuccessfull = false;
return;
} else {
// clear the password fields
callingObject.password_new.value = "";
callingObject.password_confirm.value = "";
callingObject.password_error.innerHTML = "";
changeSuccessfull = true;
}
});
if (changeSuccessfull == false) {
return;
}
}
// set the role
let selectedRole = callingObject.dialog.modalElement.querySelector('input[name="settings_user_role"]:checked').value.toLowerCase();
await fetch("/api/v1.1/Account/Users/" + callingObject.userId + "/Roles?RoleName=" + selectedRole, {
method: 'POST'
}).then(async response => {
if (!response.ok) {
// handle the error
console.error("Error updating role:");
console.error(response);
let warningDialog = new MessageBox("Role Update Error", "The role update failed. Check the role and try again.");
warningDialog.open();
return;
}
});
// set the security profile
let securityProfile = {
"ageRestrictionPolicy": {
"maximumAgeRestriction": callingObject.dialog.modalElement.querySelector('input[name="ageGroup"]:checked').value,
"includeUnrated": callingObject.dialog.modalElement.querySelector('#includeUnrated').checked
}
};
await fetch("/api/v1.1/Account/Users/" + callingObject.userId + "/SecurityProfile", {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(securityProfile)
}).then(async response => {
if (!response.ok) {
// handle the error
console.error("Error updating security profile:");
console.error(response);
let warningDialog = new MessageBox("Security Profile Update Error", "The security profile update failed. Check the settings and try again.");
warningDialog.open();
return;
}
});
if (callingObject.okCallback) {
callingObject.okCallback();
}
callingObject.dialog.close();
});
this.dialog.addButton(okButton);
// create the cancel button
let cancelButton = new ModalButton("Cancel", 0, this, function (callingObject) {
if (callingObject.cancelCallback) {
callingObject.cancelCallback();
}
callingObject.dialog.close();
});
this.dialog.addButton(cancelButton);
// show the dialog
this.dialog.open();
}
UpdateRolePermissionsDisplay() {
// get selected role
let selectedRole = this.dialog.modalElement.querySelector('input[name="settings_user_role"]:checked').value.toLowerCase();
// get the player role icons
let playerPermssions = this.dialog.modalElement.querySelectorAll('td[name="role-player"]');
playerPermssions.forEach(element => {
if (selectedRole == 'player') {
element.style.display = '';
} else {
element.style.display = 'none';
}
});
// get the gamer role icons
let gamerPermssions = this.dialog.modalElement.querySelectorAll('td[name="role-gamer"]');
gamerPermssions.forEach(element => {
if (selectedRole == 'gamer') {
element.style.display = '';
} else {
element.style.display = 'none';
}
});
// get the admin role icons
let adminPermssions = this.dialog.modalElement.querySelectorAll('td[name="role-admin"]');
adminPermssions.forEach(element => {
if (selectedRole == 'admin') {
element.style.display = '';
} else {
element.style.display = 'none';
}
});
}
UpdateAssignedAgeGroupDisplay() {
// get the selected age group
let selectedAgeGroup = this.dialog.modalElement.querySelector('input[name="ageGroup"]:checked').value;
let ageGroupList = [];
switch (selectedAgeGroup) {
case "Adult":
ageGroupList = ["Child", "Teen", "Mature", "Adult"];
break;
case "Mature":
ageGroupList = ["Child", "Teen", "Mature"];
break;
case "Teen":
ageGroupList = ["Child", "Teen"];
break;
case "Child":
ageGroupList = ["Child"];
break;
default:
break;
}
// get target div
let assignedAgeGroup = this.dialog.modalElement.querySelector('#settings_user_agerestrictions_preview');
assignedAgeGroup.innerHTML = '';
// generate restrictions table
let ageRestrictionPolicyTable = document.createElement('table');
ageRestrictionPolicyTable.classList.add('romtable');
ageRestrictionPolicyTable.setAttribute('cellspacing', '0');
for (const [key, value] of Object.entries(ClassificationBoards)) {
let thRow = document.createElement('tr');
let thCell = document.createElement('th');
thCell.innerHTML = value;
thRow.appendChild(thCell);
ageRestrictionPolicyTable.appendChild(thRow);
// add age rating icons
let trRow = document.createElement('tr');
let tdCell = document.createElement('td');
for (let i = 0; i < ageGroupList.length; i++) {
let ageRatingBadgeIndexes = AgeRatingGroups[ageGroupList[i]][key];
for (let j = 0; j < ageRatingBadgeIndexes.length; j++) {
let ageRatingBatch = document.createElement('img');
ageRatingBatch.src = '/images/Ratings/' + key + '/' + AgeRatingStrings[ageRatingBadgeIndexes[j]] + '.svg';
ageRatingBatch.classList.add('rating_image_mini');
ageRatingBatch.setAttribute('title', ClassificationRatings[AgeRatingStrings[ageRatingBadgeIndexes[j]]]);
tdCell.appendChild(ageRatingBatch);
}
ageRestrictionPolicyTable.appendChild(trRow);
}
trRow.appendChild(tdCell);
ageRestrictionPolicyTable.appendChild(trRow);
}
assignedAgeGroup.appendChild(ageRestrictionPolicyTable);
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 267 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.5 MiB

View File

@@ -0,0 +1,634 @@
class AccountWindow {
constructor() {
}
async open() {
// Create the modal
this.dialog = await new Modal("account");
await this.dialog.BuildModal();
// setup the dialog
this.dialog.modalElement.querySelector('#modal-header-text').innerHTML = "Profile and Account";
this.AvatarPreview = this.dialog.modalElement.querySelector('#avatar-preview');
this.AvatarPreviewChanged = false;
let AvatarPreviewChanged = this.AvatarPreviewChanged;
this.BackgroundPreview = this.dialog.modalElement.querySelector('#background-preview');
this.BackgroundPreviewChanged = false;
let BackgroundPreviewChanged = this.BackgroundPreviewChanged;
this.DisplayNamePreview = this.dialog.modalElement.querySelector('#display-name');
let DisplayNamePreview = this.DisplayNamePreview;
this.QuipPreview = this.dialog.modalElement.querySelector('#quip');
let QuipPreview = this.QuipPreview;
// configure the file upload buttons
this.profile_avatarUpload = this.dialog.modalElement.querySelector('#avatar-upload');
let profile_avatarUpload = this.profile_avatarUpload;
this.profile_avatarUpload.addEventListener('change', function (event) {
const file = event.target.files[0];
const reader = new FileReader();
reader.onload = function (e) {
const imagePreview = document.querySelector('#avatar-preview');
imagePreview.style.backgroundImage = `url(${e.target.result})`;
imagePreview.innerHTML = "";
AvatarPreviewChanged = true;
};
reader.readAsDataURL(file);
});
this.profile_avatarUploadClear = this.dialog.modalElement.querySelector('#avatar-upload-clear');
this.profile_avatarUploadClear.addEventListener('click', function (event) {
let avatarBackgroundColor = intToRGB(hashCode(DisplayNamePreview.value));
const imagePreview = document.querySelector('#avatar-preview');
imagePreview.style.backgroundImage = "";
imagePreview.innerHTML = DisplayNamePreview.value[0].toUpperCase();
imagePreview.style.backgroundColor = "#" + avatarBackgroundColor;
profile_avatarUpload.value = "";
AvatarPreviewChanged = true;
});
this.profile_backgroundUpload = this.dialog.modalElement.querySelector('#background-upload');
let profile_backgroundUpload = this.profile_backgroundUpload;
this.profile_backgroundUpload.addEventListener('change', function (event) {
const file = event.target.files[0];
const reader = new FileReader();
reader.onload = function (e) {
const imagePreview = document.querySelector('#background-preview');
imagePreview.style.backgroundImage = `url(${e.target.result})`;
BackgroundPreviewChanged = true;
};
reader.readAsDataURL(file);
});
this.profile_backgroundUploadClear = this.dialog.modalElement.querySelector('#background-upload-clear');
this.profile_backgroundUploadClear.addEventListener('click', function (event) {
const imagePreview = document.querySelector('#background-preview');
imagePreview.style.backgroundImage = "";
profile_backgroundUpload.value = "";
BackgroundPreviewChanged = true;
});
// add an event to the display name field to update the avatar preview
this.DisplayNamePreview.addEventListener('input', function (event) {
let avatarBackgroundColor = intToRGB(hashCode(DisplayNamePreview.value));
const imagePreview = document.querySelector('#avatar-preview');
imagePreview.style.backgroundColor = "#" + avatarBackgroundColor;
if (imagePreview.style.backgroundImage === "") {
imagePreview.innerHTML = DisplayNamePreview.value[0].toUpperCase();
}
});
// add an event to the quip field to note an update
this.QuipPreview.addEventListener('input', function (event) {
let quip = QuipPreview.value;
});
// populate the previews with the existing profile images
const response = await fetch("/api/v1.1/UserProfile/" + userProfile.profileId).then(async response => {
if (!response.ok) {
// handle the error
console.error("Error fetching profile");
} else {
const profile = await response.json();
if (profile) {
// avatar preview
let avatarBackgroundColor = intToRGB(hashCode(profile.displayName));
this.AvatarPreview.innerHTML = "";
this.AvatarPreview.style.backgroundImage = "";
this.AvatarPreview.style.backgroundColor = "#" + avatarBackgroundColor;
if (profile.avatar) {
this.AvatarPreview.style.backgroundImage = "url('/api/v1.1/UserProfile/" + userProfile.profileId + "/Avatar')";
} else {
this.AvatarPreview.innerHTML = profile.displayName[0].toUpperCase();
}
// background preview
this.BackgroundPreview.innerHTML = "";
this.BackgroundPreview.style.backgroundImage = "";
if (profile.profileBackground) {
this.BackgroundPreview.style.backgroundImage = "url('/api/v1.1/UserProfile/" + userProfile.profileId + "/Background')";
}
// display name preview
this.DisplayNamePreview.value = profile.displayName;
// quip preview
this.QuipPreview.value = profile.quip;
}
}
});
// set up the password change form
this.password_current = this.dialog.modalElement.querySelector('#current-password');
this.password_new = this.dialog.modalElement.querySelector('#new-password');
this.password_confirm = this.dialog.modalElement.querySelector('#confirm-new-password');
this.password_error = this.dialog.modalElement.querySelector('#password-error');
this.PasswordCheck = new PasswordCheck(this.password_new, this.password_confirm, this.password_error);
// create the ok button
let okButton = new ModalButton("OK", 1, this, async function (callingObject) {
// check if a current password has been entered
if (callingObject.password_current.value.length > 0) {
// assume user wants to change their password
// check if the new password meets the rules
if (!PasswordCheck.CheckPasswords(callingObject.PasswordCheck, callingObject.password_new, callingObject.password_confirm)) {
// display an error
let warningDialog = new MessageBox("Password Reset Error", "The new password does not meet the requirements.");
warningDialog.open();
return;
}
// requirements met, reset the password
let model = {
oldPassword: callingObject.password_current.value,
newPassword: callingObject.password_new.value,
confirmPassword: callingObject.password_confirm.value
};
let changeSuccessfull = false;
await fetch("/api/v1.1/Account/ChangePassword", {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(model)
}).then(async response => {
if (!response.ok) {
// handle the error
console.error("Error updating password:");
console.error(response);
let warningDialog = new MessageBox("Password Reset Error", "The password reset failed. Check the current password and try again.");
warningDialog.open();
changeSuccessfull = false;
return;
} else {
// clear the password fields
callingObject.password_current.value = "";
callingObject.password_new.value = "";
callingObject.password_confirm.value = "";
callingObject.password_error.innerHTML = "";
changeSuccessfull = true;
}
});
if (changeSuccessfull == false) {
return;
}
}
// create profile model
let model = {
userId: userProfile.profileId,
displayName: callingObject.DisplayNamePreview.value,
quip: callingObject.QuipPreview.value,
data: {}
};
// POST the model to the API
await fetch("/api/v1.1/UserProfile/" + userProfile.profileId, {
method: 'PUT',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(model)
}).then(async response => {
if (!response.ok) {
// handle the error
console.error("Error updating profile:");
console.error(response);
} else {
// update the avatar
if (AvatarPreviewChanged === true) {
if (callingObject.profile_avatarUpload.files.length === 0) {
await fetch("/api/v1.1/UserProfile/" + userProfile.profileId + "/Avatar", {
method: 'DELETE'
}).then(async response => {
if (!response.ok) {
// handle the error
console.error("Error deleting avatar:");
console.error(response);
}
});
} else {
let avatarFormData = new FormData();
avatarFormData.append('file', callingObject.profile_avatarUpload.files[0]);
await fetch("/api/v1.1/UserProfile/" + userProfile.profileId + "/Avatar", {
method: 'PUT',
body: avatarFormData
}).then(async response => {
if (!response.ok) {
// handle the error
console.error("Error updating avatar:");
console.error(response);
}
});
}
}
// update the background
if (BackgroundPreviewChanged === true) {
if (callingObject.profile_backgroundUpload.files.length === 0) {
await fetch("/api/v1.1/UserProfile/" + userProfile.profileId + "/Background", {
method: 'DELETE'
}).then(async response => {
if (!response.ok) {
// handle the error
console.error("Error deleting background:");
console.error(response);
}
});
} else {
let backgroundFormData = new FormData();
backgroundFormData.append('file', callingObject.profile_backgroundUpload.files[0]);
await fetch("/api/v1.1/UserProfile/" + userProfile.profileId + "/Background", {
method: 'PUT',
body: backgroundFormData
}).then(async response => {
if (!response.ok) {
// handle the error
console.error("Error updating background:");
console.error(response);
}
});
}
}
}
});
AccountWindow.#ReloadProfile();
callingObject.dialog.close();
});
this.dialog.addButton(okButton);
// create the cancel button
let cancelButton = new ModalButton("Cancel", 0, this, function (callingObject) {
callingObject.dialog.close();
});
this.dialog.addButton(cancelButton);
// show the dialog
await this.dialog.open();
}
static async #ReloadProfile() {
// set avatar
let avatarBox = document.getElementById('banner_user_image_box');
avatarBox.innerHTML = "";
let avatar = new Avatar(userProfile.profileId, 30, 30);
avatarBox.style = 'pointer-events: none;';
avatar.setAttribute('style', 'margin-top: 5px; pointer-events: none; width: 30px; height: 30px;');
avatarBox.appendChild(avatar);
// set profile card in drop down
let profileCard = document.getElementById('banner_user_profilecard');
profileCard.innerHTML = "";
let profileCardContent = new ProfileCard(userProfile.profileId, true);
profileCard.appendChild(profileCardContent);
}
}
class Avatar {
constructor(ProfileId, ElementWidth, ElementHeight, ShowProfileCard = false) {
this.ProfileId = ProfileId;
this.ElementWidth = ElementWidth;
this.ElementHeight = ElementHeight;
this.ShowProfileCard = ShowProfileCard;
this.Avatar = document.createElement('div');
const response = this.#FetchProfile(this);
if (this.ShowProfileCard === true) {
this.ProfileCard = new ProfileCard(this.ProfileId);
this.ProfileCard.style.display = "none";
this.Avatar.appendChild(this.ProfileCard);
let profileCard = this.ProfileCard;
this.Avatar.addEventListener('mouseenter', function () {
profileCard.style.position = "absolute";
profileCard.style.marginTop = "-2px";
profileCard.style.marginLeft = "-2px";
profileCard.style.display = "block";
profileCard.style.zIndex = "100";
});
this.Avatar.addEventListener('mouseleave', function () {
profileCard.style.display = "none";
});
this.ProfileCard.addEventListener('mouseleave', function () {
profileCard.style.display = "none";
});
}
return this.Avatar;
}
async Update() {
const response = this.#FetchProfile(this);
}
async #FetchProfile(callingObject) {
const response = await fetch("/api/v1.1/UserProfile/" + callingObject.ProfileId).then(async response => {
if (!response.ok) {
// handle the error
console.error("Error fetching profile");
} else {
const profile = await response.json();
if (profile) {
let newAvatarImg;
newAvatarImg = document.createElement('div');
if (profile.avatar) {
newAvatarImg.style = "background-image: url('/api/v1.1/UserProfile/" + callingObject.ProfileId + "/Avatar'); background-size: cover; background-position: center; border-radius: 50%; pointer-events: none; height: " + callingObject.ElementHeight + "px; width: " + callingObject.ElementWidth + "px;";
} else {
newAvatarImg.innerHTML = profile.displayName[0].toUpperCase();
let backgroundColor = intToRGB(hashCode(profile.displayName));
newAvatarImg.style = "background-color: #" + backgroundColor + "; font-size: 1vmax; display: flex; justify-content: center; align-items: center; border-radius: 50%; pointer-events: none; height: " + callingObject.ElementHeight + "px; width: " + callingObject.ElementWidth + "px;";
}
newAvatarImg.classList.add('avatar');
callingObject.Avatar.appendChild(newAvatarImg);
}
}
});
}
}
class ProfileCard {
constructor(ProfileId, IsMenuCard = false) {
this.ProfileId = ProfileId;
// build profile card
this.Card = document.createElement('div');
this.Card.classList.add('profile-card');
if (IsMenuCard === false) {
this.Card.classList.add('profile-card-standalone');
}
this.BackgroundImage = document.createElement('div');
this.BackgroundImage.classList.add('profile-card-background-image');
this.DisplayName = document.createElement('div');
this.DisplayName.classList.add('profile-card-display-name');
this.Quip = document.createElement('div');
this.Quip.classList.add('profile-card-quip');
this.ProfileBody = document.createElement('div');
this.ProfileBody.classList.add('profile-card-body');
this.Avatar = document.createElement('div');
this.Avatar.classList.add('profile-card-avatar');
// top half of card
// bottom half of card
this.ProfileBody.appendChild(this.DisplayName);
this.ProfileBody.appendChild(this.Quip);
// assemble card
this.Card.appendChild(this.BackgroundImage);
this.Card.appendChild(this.ProfileBody);
this.Card.appendChild(this.Avatar);
const response = this.#FetchProfile(this);
return this.Card;
}
async #FetchProfile(callingObject) {
const response = await fetch("/api/v1.1/UserProfile/" + callingObject.ProfileId).then(async response => {
if (!response.ok) {
// handle the error
console.error("Error fetching profile");
} else {
const profile = await response.json();
if (profile) {
this.Avatar.appendChild(new Avatar(callingObject.ProfileId, 50, 50));
if (profile.profileBackground) {
this.BackgroundImage.style = "background-image: url('/api/v1.1/UserProfile/" + callingObject.ProfileId + "/Background');";
}
this.DisplayName.innerHTML = profile.displayName;
this.Quip.innerHTML = profile.quip;
}
}
});
}
}
class EmailCheck {
constructor(EmailElement, ErrorElement, SkipUniqueCheck = false) {
this.EmailElement = EmailElement;
this.ErrorElement = ErrorElement;
this.SkipUniqueCheck = SkipUniqueCheck;
let CallingObject = this;
this.EmailElement.addEventListener('input', function (event) {
EmailCheck.CheckEmail(CallingObject, EmailElement);
});
this.DisplayRules(ErrorElement);
}
DisplayRules(ErrorElement) {
this.errorList = document.createElement('ul');
this.errorList.className = 'password-rules';
this.listItemInvalidEmail = document.createElement('li');
this.listItemInvalidEmail.innerHTML = "Email is a valid address";
this.listItemInvalidEmail.classList.add('listitem');
this.errorList.appendChild(this.listItemInvalidEmail);
if (this.SkipUniqueCheck === false) {
this.listItemUniqueEmail = document.createElement('li');
this.listItemUniqueEmail.innerHTML = "Email is unique";
this.listItemUniqueEmail.classList.add('listitem');
this.errorList.appendChild(this.listItemUniqueEmail);
}
ErrorElement.innerHTML = "";
ErrorElement.appendChild(this.errorList);
EmailCheck.CheckEmail(this, this.EmailElement);
}
static async CheckEmail(CallingObject, EmailElement) {
let emailMeetsRules = true;
// check if email is valid
if (EmailElement.value.match(/^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/)) {
CallingObject.listItemInvalidEmail.classList.add('listitem-green');
CallingObject.listItemInvalidEmail.classList.remove('listitem-red');
} else {
CallingObject.listItemInvalidEmail.classList.add('listitem-red');
CallingObject.listItemInvalidEmail.classList.remove('listitem-green');
emailMeetsRules = false;
}
// check if email is unique
if (CallingObject.SkipUniqueCheck === false) {
await fetch("/api/v1.1/Account/Users/Test?Email=" + EmailElement.value, {
method: 'GET'
}).then(async response => {
if (!await response.ok) {
// handle the error
console.error("Error checking email uniqueness:");
console.error(response);
CallingObject.listItemUniqueEmail.classList.add('listitem-red');
CallingObject.listItemUniqueEmail.classList.remove('listitem-green');
emailMeetsRules = false;
} else {
let responseJson = await response.json();
if (responseJson === false) {
CallingObject.listItemUniqueEmail.classList.add('listitem-green');
CallingObject.listItemUniqueEmail.classList.remove('listitem-red');
emailMeetsRules = true;
} else {
CallingObject.listItemUniqueEmail.classList.add('listitem-red');
CallingObject.listItemUniqueEmail.classList.remove('listitem-green');
emailMeetsRules = false;
}
}
});
}
return emailMeetsRules;
}
}
class PasswordCheck {
constructor(NewPasswordElement, ConfirmPasswordElement, ErrorElement) {
this.MinimumPasswordLength = 10;
this.RequireUppercase = true;
this.RequireLowercase = true;
this.RequireNumber = true;
this.RequireSpecial = false;
this.NewPasswordElement = NewPasswordElement;
this.ConfirmPasswordElement = ConfirmPasswordElement;
this.ErrorElement = ErrorElement;
let CallingObject = this;
this.NewPasswordElement.addEventListener('input', function (event) {
PasswordCheck.CheckPasswords(CallingObject, NewPasswordElement, ConfirmPasswordElement);
});
this.ConfirmPasswordElement.addEventListener('input', function (event) {
PasswordCheck.CheckPasswords(CallingObject, NewPasswordElement, ConfirmPasswordElement);
});
this.DisplayRules(ErrorElement);
}
DisplayRules(ErrorElement) {
this.errorList = document.createElement('ul');
this.errorList.className = 'password-rules';
this.listItemPasswordLength = document.createElement('li');
this.listItemPasswordLength.innerHTML = "Minimum " + this.MinimumPasswordLength + " characters";
this.listItemPasswordLength.classList.add('listitem');
this.errorList.appendChild(this.listItemPasswordLength);
if (this.RequireUppercase == true) {
this.listItemUpper = document.createElement('li');
this.listItemUpper.innerHTML = "At least one uppercase letter";
this.listItemUpper.classList.add('listitem');
this.errorList.appendChild(this.listItemUpper);
}
if (this.RequireLowercase == true) {
this.listItemLower = document.createElement('li');
this.listItemLower.innerHTML = "At least one lowercase letter";
this.listItemLower.classList.add('listitem');
this.errorList.appendChild(this.listItemLower);
}
if (this.RequireNumber == true) {
this.listItemNumber = document.createElement('li');
this.listItemNumber.innerHTML = "At least one number";
this.listItemNumber.classList.add('listitem');
this.errorList.appendChild(this.listItemNumber);
}
if (this.RequireSpecial == true) {
this.listItemSpecial = document.createElement('li');
this.listItemSpecial.innerHTML = "At least one special character.";
this.listItemSpecial.classList.add('listitem');
this.errorList.appendChild(this.listItemSpecial);
}
this.listItemMatch = document.createElement('li');
this.listItemMatch.innerHTML = "Passwords must match.";
this.listItemMatch.classList.add('listitem');
this.errorList.appendChild(this.listItemMatch);
ErrorElement.innerHTML = "";
ErrorElement.appendChild(this.errorList);
PasswordCheck.CheckPasswords(this, this.NewPasswordElement, this.ConfirmPasswordElement);
}
static CheckPasswords(CallingObject, NewPasswordElement, ConfirmPasswordElement) {
let passwordMeetsRules = true;
// check password length
if (NewPasswordElement.value.length >= CallingObject.MinimumPasswordLength) {
CallingObject.listItemPasswordLength.classList.add('listitem-green');
CallingObject.listItemPasswordLength.classList.remove('listitem-red');
} else {
CallingObject.listItemPasswordLength.classList.add('listitem-red');
CallingObject.listItemPasswordLength.classList.remove('listitem-green');
passwordMeetsRules = false;
}
if (CallingObject.RequireUppercase == true) {
// check for uppercase
if (NewPasswordElement.value.match(/[A-Z]/)) {
CallingObject.listItemUpper.classList.add('listitem-green');
CallingObject.listItemUpper.classList.remove('listitem-red');
} else {
CallingObject.listItemUpper.classList.add('listitem-red');
CallingObject.listItemUpper.classList.remove('listitem-green');
passwordMeetsRules = false;
}
}
if (CallingObject.RequireLowercase == true) {
// check for lowercase
if (NewPasswordElement.value.match(/[a-z]/)) {
CallingObject.listItemLower.classList.add('listitem-green');
CallingObject.listItemLower.classList.remove('listitem-red');
} else {
CallingObject.listItemLower.classList.add('listitem-red');
CallingObject.listItemLower.classList.remove('listitem-green');
passwordMeetsRules = false;
}
}
if (CallingObject.RequireNumber == true) {
// check for number
if (NewPasswordElement.value.match(/[0-9]/)) {
CallingObject.listItemNumber.classList.add('listitem-green');
CallingObject.listItemNumber.classList.remove('listitem-red');
} else {
CallingObject.listItemNumber.classList.add('listitem-red');
CallingObject.listItemNumber.classList.remove('listitem-green');
passwordMeetsRules = false;
}
}
if (CallingObject.RequireSpecial == true) {
// check for special character
if (NewPasswordElement.value.match(/[!@#$%^&*(),.?":{}|<>]/)) {
CallingObject.listItemSpecial.classList.add('listitem-green');
CallingObject.listItemSpecial.classList.remove('listitem-red');
} else {
CallingObject.listItemSpecial.classList.add('listitem-red');
CallingObject.listItemSpecial.classList.remove('listitem-green');
passwordMeetsRules = false;
}
}
// check if passwords match
if (NewPasswordElement.value === ConfirmPasswordElement.value) {
CallingObject.listItemMatch.classList.add('listitem-green');
CallingObject.listItemMatch.classList.remove('listitem-red');
} else {
CallingObject.listItemMatch.classList.add('listitem-red');
CallingObject.listItemMatch.classList.remove('listitem-green');
passwordMeetsRules = false;
}
return passwordMeetsRules;
}
}

View File

@@ -22,7 +22,7 @@ function formatFilterPanel(containerElement, result) {
containerPanelSearchField.id = 'filter_panel_search';
containerPanelSearchField.type = 'text';
containerPanelSearchField.placeholder = 'Search';
containerPanelSearchField.addEventListener("keypress", function(event) {
containerPanelSearchField.addEventListener("keypress", function (event) {
if (event.key === "Enter") {
// Cancel the default action, if needed
event.preventDefault();
@@ -34,24 +34,9 @@ function formatFilterPanel(containerElement, result) {
panel.appendChild(containerPanelSearch);
// user rating
panel.appendChild(buildFilterPanelHeader('userrating', 'User Rating', true, false));
var containerPanelUserRating = buildFilterRange('userrating', 0, 100);
panel.appendChild(containerPanelUserRating);
// user vote count
panel.appendChild(buildFilterPanelHeader('uservotes', 'User Votes', true, false));
var containerPanelUserVotes = buildFilterRange('uservotes', 0, 1000000);
panel.appendChild(containerPanelUserVotes);
// release year
panel.appendChild(buildFilterPanelHeader('releaseyear', 'Release Year', true, false));
var containerPanelReleaseYear = buildFilterRange('releaseyear', 1960, (new Date()).getFullYear());
panel.appendChild(containerPanelReleaseYear);
// settings
buildFilterPanel(panel, 'settings', 'Settings', [
{
{
"id": "savestatesavailable",
"name": "Game has save states avaialble",
"gameCount": 0
@@ -61,35 +46,55 @@ function formatFilterPanel(containerElement, result) {
"name": "Favourite",
"gameCount": 0
}
], true, true);
], true, false);
// server provided filters
// platforms
if (result.platforms) {
buildFilterPanel(panel, 'platform', 'Platforms', result.platforms, true, true);
}
// genres
if (result.genres) {
buildFilterPanel(panel, 'genre', 'Genres', result.genres, true, false);
}
if (result.gamemodes) {
buildFilterPanel(panel, 'gamemode', 'Players', result.gamemodes, true, false);
}
if (result.playerperspectives) {
buildFilterPanel(panel, 'playerperspective', 'Player Perspectives', result.playerperspectives, true, false);
}
// themes
if (result.themes) {
buildFilterPanel(panel, 'theme', 'Themes', result.themes, true, false);
}
// release year
panel.appendChild(buildFilterPanelHeader('releaseyear', 'Release Year', true, false));
var containerPanelReleaseYear = buildFilterRange('releaseyear', 1960, (new Date()).getFullYear(), false);
panel.appendChild(containerPanelReleaseYear);
// players
if (result.gamemodes) {
buildFilterPanel(panel, 'gamemode', 'Players', result.gamemodes, true, false);
}
// player perspectives
if (result.playerperspectives) {
buildFilterPanel(panel, 'playerperspective', 'Player Perspectives', result.playerperspectives, true, false);
}
// age groups
if (result.agegroupings) {
if (result.agegroupings.length > 1) {
buildFilterPanel(panel, 'agegroupings', 'Age Groups', result.agegroupings, true, false);
}
}
// user rating
panel.appendChild(buildFilterPanelHeader('userrating', 'User Rating', true, false));
var containerPanelUserRating = buildFilterRange('userrating', 0, 100, false);
panel.appendChild(containerPanelUserRating);
// user vote count
panel.appendChild(buildFilterPanelHeader('uservotes', 'User Votes', true, false));
var containerPanelUserVotes = buildFilterRange('uservotes', 0, 1000000, false);
panel.appendChild(containerPanelUserVotes);
targetElement.appendChild(panel);
// filter controls
@@ -112,14 +117,22 @@ function formatFilterPanel(containerElement, result) {
buttonsDiv.appendChild(resetButton);
// set page size value
var pageSizeCookie = GetPreference('LibraryPageSize', '20');
if (pageSizeCookie) {
var pageSizeSelector = document.getElementById('games_library_pagesize_select');
$(pageSizeSelector).select2('destroy');
$(pageSizeSelector).val(pageSizeCookie).select2();
}
// set order by values
var orderByCookie = getCookie('games_library_orderby_select');
var orderByCookie = GetPreference('LibraryOrderBy', 'NameThe');
if (orderByCookie) {
var orderBySelector = document.getElementById('games_library_orderby_select');
$(orderBySelector).select2('destroy');
$(orderBySelector).val(orderByCookie).select2();
}
var orderByDirectionCookie = getCookie('games_library_orderby_direction_select');
var orderByDirectionCookie = GetPreference('LibraryOrderByDirection', 'Ascending');
if (orderByDirectionCookie) {
var orderByDirectionSelector = document.getElementById('games_library_orderby_direction_select');
$(orderByDirectionSelector).select2('destroy');
@@ -130,7 +143,6 @@ function formatFilterPanel(containerElement, result) {
containerElement.appendChild(buttonsDiv);
console.log('Filter generated - execute filter');
var pageNumber = undefined;
if (getCookie('games_library_last_page') == "") {
pageNumber = undefined;
@@ -157,7 +169,7 @@ function buildFilterPanel(targetElement, headerString, friendlyHeaderString, val
}
for (var i = 0; i < valueList.length; i++) {
var tags;
if (valueList[i].gameCount) {
tags = [
{
@@ -179,7 +191,7 @@ function buildFilterPanelHeader(headerString, friendlyHeaderString, showVisibleT
} else {
headerToggle.innerHTML = '+';
}
var headerLabel = document.createElement('span');
headerLabel.innerHTML = friendlyHeaderString;
@@ -252,15 +264,26 @@ function buildFilterPanelItem(filterType, itemString, friendlyItemString, tags)
}
filterPanelItem.appendChild(filterPanelItemCheckBox);
filterPanelItem.appendChild(filterPanelItemLabel);
return filterPanelItem;
}
function buildFilterRange(name, min, max) {
function buildFilterRange(name, min, max, initialDisplay) {
var containerPanelUserRating = document.createElement('div');
containerPanelUserRating.id = 'filter_panel_box_' + name + '';
containerPanelUserRating.className = 'filter_panel_box';
var displayCookie = getCookie('filter_panel_box_' + name);
if (displayCookie) {
initialDisplay = (displayCookie === 'true');
}
if (initialDisplay == false) {
containerPanelUserRating.setAttribute('style', 'display: none;');
} else {
containerPanelUserRating.setAttribute('style', 'display: block;');
}
var containerPanelUserRatingCheckBox = document.createElement('input');
containerPanelUserRatingCheckBox.id = 'filter_panel_' + name + '_enabled';
containerPanelUserRatingCheckBox.name = 'filter_panel_range_enabled_check';
@@ -321,7 +344,7 @@ function executeFilterDelayed() {
function buildFilterTag(tags) {
// accepts an array of numbers + classes for styling (optional)
// example [ { label: "G: 13", class: "tag_Green" }, { label: "R: 17", class: "tag_Orange" } ]
var boundingDiv = document.createElement('div');
boundingDiv.className = 'tagBox';
@@ -391,7 +414,7 @@ function resetFilters() {
executeFilter1_1();
}
function executeFilter1_1(pageNumber, pageSize) {
function executeFilter1_1(pageNumber) {
var freshSearch = false;
if (!pageNumber) {
@@ -400,33 +423,20 @@ function executeFilter1_1(pageNumber, pageSize) {
existingSearchModel = undefined;
}
let pageMode = GetPreference('LibraryPagination', 'paged');
if (!pageSize) {
switch (pageMode) {
case "infinite":
pageSize = 30;
break;
case "paged":
default:
pageSize = 30;
break;
}
}
// get settings
let pageSize = Number($('#games_library_pagesize_select').val());
let orderBy = $('#games_library_orderby_select').val();
let orderByDirectionSelect = $('#games_library_orderby_direction_select').val();
var model;
// get order by
var orderBy = $('#games_library_orderby_select').val();
setCookie('games_library_orderby_select', orderBy);
var orderByDirection = true;
var orderByDirectionSelect = $('#games_library_orderby_direction_select').val();
if (orderByDirectionSelect == "Ascending") {
orderByDirection = true;
} else {
orderByDirection = false;
}
setCookie('games_library_orderby_direction_select', orderByDirectionSelect);
if (existingSearchModel == undefined || freshSearch == true) {
// search name
@@ -577,7 +587,6 @@ function executeFilter1_1(pageNumber, pageSize) {
"SortAscending": orderByDirection
}
};
console.log(model);
existingSearchModel = model;
} else {
@@ -586,8 +595,9 @@ function executeFilter1_1(pageNumber, pageSize) {
model = existingSearchModel;
}
let gamesCallURL = '/api/v1.1/Games?pageNumber=' + pageNumber + '&pageSize=' + pageSize;
ajaxCall(
'/api/v1.1/Games?pageNumber=' + pageNumber + '&pageSize=' + pageSize,
gamesCallURL,
'POST',
function (result) {
var gameElement = document.getElementById('games_library');

View File

@@ -1,40 +1,41 @@
var ClassificationBoards = {
"ESRB": "Entertainment Software Rating Board (ESRB)",
"PEGI": "Pan European Game Information (PEGI)",
"CERO": "Computer Entertainment Rating Organisation (CERO)",
"USK": "Unterhaltungssoftware Selbstkontrolle (USK)",
"GRAC": "Game Rating and Administration Committee (GRAC)",
"ESRB": "Entertainment Software Rating Board (ESRB)",
"PEGI": "Pan European Game Information (PEGI)",
"CERO": "Computer Entertainment Rating Organisation (CERO)",
"USK": "Unterhaltungssoftware Selbstkontrolle (USK)",
"GRAC": "Game Rating and Administration Committee (GRAC)",
"CLASS_IND": "Brazilian advisory rating system",
"ACB": "Australian Classification Board (ACB)"
"ACB": "Australian Classification Board (ACB)"
};
var ClassificationRatings = {
"E": "Everyone",
"E10": "Everyone 10+",
"T": "Teen",
"M": "Mature 17+",
"AO": "Adults Only 18+",
"RP": "Rating Pending",
"EC": "Early Childhood",
"E": "Everyone",
"E10": "Everyone 10+",
"T": "Teen",
"M": "Mature 17+",
"AO": "Adults Only 18+",
"RP": "Rating Pending",
"Three": "PEGI 3",
"Seven": "PEGI 7",
"Twelve": "PEGI 12",
"Sixteen": "PEGI 16",
"Eighteen": "PEGI 18",
"CERO_A": "All Ages",
"CERO_B": "Ages 12 and up",
"CERO_C": "Ages 15 and up",
"CERO_D": "Ages 17 and up",
"CERO_Z": "Ages 18 and up only",
"Three": "PEGI 3",
"Seven": "PEGI 7",
"Twelve": "PEGI 12",
"Sixteen": "PEGI 16",
"Eighteen": "PEGI 18",
"USK_0": "Approved without age restriction",
"USK_6": "Approved for children aged 6 and above",
"USK_12": "Approved for children aged 12 and above",
"USK_16": "Approved for children aged 16 and above",
"USK_18": "Not approved for young persons",
"CERO_A": "All Ages",
"CERO_B": "Ages 12 and up",
"CERO_C": "Ages 15 and up",
"CERO_D": "Ages 17 and up",
"CERO_Z": "Ages 18 and up only",
"GRAC_All": "All",
"USK_0": "Approved without age restriction",
"USK_6": "Approved for children aged 6 and above",
"USK_12": "Approved for children aged 12 and above",
"USK_16": "Approved for children aged 16 and above",
"USK_18": "Not approved for young persons",
"GRAC_All": "All",
"GRAC_Twelve": "12+",
"GRAC_Fifteen": "15+",
"GRAC_Eighteen": "18+",
@@ -47,19 +48,47 @@ var ClassificationRatings = {
"CLASS_IND_Sixteen": "Not recommended for minors under sixteen",
"CLASS_IND_Eighteen": "Not recommended for minors under eighteen",
"ACB_G": "General",
"ACB_PG": "Parental Guidance",
"ACB_M": "Mature",
"ACB_MA15": "Mature Accompanied",
"ACB_R18": "Restricted",
"ACB_RC": "Refused Classification"
"ACB_G": "General",
"ACB_PG": "Parental Guidance",
"ACB_M": "Mature",
"ACB_MA15": "Mature Accompanied",
"ACB_R18": "Restricted",
"ACB_RC": "Refused Classification"
};
var pageReloadInterval;
var firstLoad = true;
function formatGamesPanel(targetElement, result, pageNumber, pageSize, forceScrollTop) {
var pageMode = GetPreference('LibraryPagination', 'paged');
// set page mode buttons
let pageViewButton = document.getElementById('games_library_button_pagedview');
let infiniteViewButton = document.getElementById('games_library_button_infiniteview');
let pageMode = GetPreference('LibraryPagination', 'infinite');
switch (pageMode) {
case 'paged':
pageViewButton.classList.add('games_library_button_selected');
infiniteViewButton.classList.remove('games_library_button_selected');
break;
case 'infinite':
pageViewButton.classList.remove('games_library_button_selected');
infiniteViewButton.classList.add('games_library_button_selected');
break;
}
// set view mode buttons
let listViewButton = document.getElementById('games_library_button_listview');
let iconViewButton = document.getElementById('games_library_button_iconview');
let listViewRaw = GetPreference('LibraryListView', 'false');
let listView = false;
if (listViewRaw == 'true') {
listView = true;
listViewButton.classList.add('games_library_button_selected');
iconViewButton.classList.remove('games_library_button_selected');
} else {
listViewButton.classList.remove('games_library_button_selected');
iconViewButton.classList.add('games_library_button_selected');
}
if (pageNumber == 1) {
localStorage.setItem("gaseous-library-scrollpos", 0);
@@ -76,14 +105,14 @@ function formatGamesPanel(targetElement, result, pageNumber, pageSize, forceScro
}
break;
case 'infinite':
var gamePlaceholders = document.getElementsByName('GamePlaceholder');
let gamePlaceholders = document.getElementsByName('GamePlaceholder');
let currentPage = 1;
let totalPages = Math.ceil(result.count / pageSize);
let totalPages = Math.ceil(result.count / Number(pageSize));
let startIndex = 0;
let endIndex = pageSize;
let endIndex = 0 + Number(pageSize);
for (let p = currentPage; p < totalPages + 1; p++) {
//console.log("Page: " + p + " - StartIndex: " + startIndex + " - EndIndex: " + endIndex);
// console.log("Page: " + p + " - StartIndex: " + startIndex + " - EndIndex: " + endIndex);
let newPageAnchor = document.getElementById('pageAnchor' + p);
if (!newPageAnchor) {
@@ -101,14 +130,14 @@ function formatGamesPanel(targetElement, result, pageNumber, pageSize, forceScro
}
for (let i = startIndex; i < endIndex; i++) {
var placeHolderpresent = false;
for (var x = 0; x < gamePlaceholders.length; x++) {
let placeHolderpresent = false;
for (let x = 0; x < gamePlaceholders.length; x++) {
if (gamePlaceholders[x].getAttribute('data-index') == i) {
placeHolderpresent = true;
}
}
if (placeHolderpresent == false) {
var gamePlaceholder = document.createElement('div');
let gamePlaceholder = document.createElement('div');
gamePlaceholder.setAttribute('name', 'GamePlaceholder');
gamePlaceholder.id = 'GamePlaceholder' + i;
gamePlaceholder.setAttribute('data-index', i);
@@ -118,7 +147,7 @@ function formatGamesPanel(targetElement, result, pageNumber, pageSize, forceScro
}
startIndex = endIndex;
endIndex = startIndex + pageSize;
endIndex = startIndex + Number(pageSize);
if (startIndex > result.count) {
break;
@@ -130,32 +159,38 @@ function formatGamesPanel(targetElement, result, pageNumber, pageSize, forceScro
document.getElementById('games_library_recordcount').innerHTML = result.count + ' games';
var existingLoadPageButton = document.getElementById('games_library_loadmore');
let existingLoadPageButton = document.getElementById('games_library_loadmore');
if (existingLoadPageButton) {
existingLoadPageButton.parentNode.removeChild(existingLoadPageButton);
}
// setup preferences
var showTitle = GetPreference("LibraryShowGameTitle", true);
var showRatings = GetPreference("LibraryShowGameRating", true);
var showClassification = GetPreference("LibraryShowGameClassification", true);
var classificationDisplayOrderString = GetPreference("LibraryGameClassificationDisplayOrder", JSON.stringify([ "ESRB" ]));
var classificationDisplayOrder = JSON.parse(classificationDisplayOrderString);
let showTitle = GetPreference("LibraryShowGameTitle", true);
let showRatings = GetPreference("LibraryShowGameRating", true);
let showClassification = GetPreference("LibraryShowGameClassification", true);
let classificationDisplayOrder = GetRatingsBoards();
if (showTitle == "true") { showTitle = true; } else { showTitle = false; }
if (showRatings == "true") { showRatings = true; } else { showRatings = false; }
if (showClassification == "true") { showClassification = true; } else { showClassification = false; }
for (var i = 0; i < result.games.length; i++) {
var game = renderGameIcon(result.games[i], showTitle, showRatings, showClassification, classificationDisplayOrder, false);
let tileWrapperClass = '';
if (listView === true) {
tileWrapperClass = 'game_tile_wrapper_list';
} else {
tileWrapperClass = 'game_tile_wrapper_icon';
}
for (let i = 0; i < result.games.length; i++) {
let game = renderGameIcon(result.games[i], showTitle, showRatings, showClassification, classificationDisplayOrder, false, listView);
switch (pageMode) {
case "paged":
targetElement.appendChild(game);
break;
case "infinite":
var placeholderElement = document.getElementById('GamePlaceholder' + result.games[i].index);
if (placeholderElement.className != 'game_tile_wrapper') {
placeholderElement.className = 'game_tile_wrapper';
let placeholderElement = document.getElementById('GamePlaceholder' + result.games[i].index);
if (placeholderElement.className != tileWrapperClass) {
placeholderElement.className = tileWrapperClass;
placeholderElement.innerHTML = '';
placeholderElement.appendChild(game);
}
@@ -166,22 +201,22 @@ function formatGamesPanel(targetElement, result, pageNumber, pageSize, forceScro
$(game).fadeIn(500);
}
var pager = document.getElementById('games_pager');
let pager = document.getElementById('games_pager');
pager.style.display = 'none';
var alphaPager = document.getElementById('games_library_alpha_pager');
let alphaPager = document.getElementById('games_library_alpha_pager');
alphaPager.innerHTML = '';
switch(pageMode) {
switch (pageMode) {
case 'infinite':
for (const [key, value] of Object.entries(result.alphaList)) {
var letterPager = document.createElement('span');
let letterPager = document.createElement('span');
letterPager.className = 'games_library_alpha_pager_letter';
letterPager.setAttribute('onclick', 'document.location.hash = "#pageAnchor' + (value) + '"; executeFilter1_1(' + (value) + ');');
letterPager.innerHTML = key;
alphaPager.appendChild(letterPager);
}
if (firstLoad == true) {
if (localStorage.getItem("gaseous-library-scrollpos") != null) {
$(window).scrollTop(localStorage.getItem("gaseous-library-scrollpos"));
@@ -195,7 +230,7 @@ function formatGamesPanel(targetElement, result, pageNumber, pageSize, forceScro
case 'paged':
for (const [key, value] of Object.entries(result.alphaList)) {
var letterPager = document.createElement('span');
let letterPager = document.createElement('span');
letterPager.className = 'games_library_alpha_pager_letter';
letterPager.setAttribute('onclick', 'executeFilter1_1(' + value + ');');
letterPager.innerHTML = key;
@@ -203,10 +238,10 @@ function formatGamesPanel(targetElement, result, pageNumber, pageSize, forceScro
}
if (result.count > pageSize) {
var pageCount = Math.ceil(result.count / pageSize);
let pageCount = Math.ceil(result.count / pageSize);
// add first page button
var firstPage = document.createElement('span');
let firstPage = document.createElement('span');
firstPage.innerHTML = '&#124;&lt;';
if (pageNumber == 1) {
firstPage.className = 'games_pager_number_disabled';
@@ -216,7 +251,7 @@ function formatGamesPanel(targetElement, result, pageNumber, pageSize, forceScro
}
// add previous page button
var prevPage = document.createElement('span');
let prevPage = document.createElement('span');
prevPage.innerHTML = '&lt;';
if (pageNumber == 1) {
prevPage.className = 'games_pager_number_disabled';
@@ -226,11 +261,11 @@ function formatGamesPanel(targetElement, result, pageNumber, pageSize, forceScro
}
// add page numbers
var pageEitherSide = 4;
// var currentPage = Number(pagerCheck.innerHTML);
var currentPage = pageNumber;
var pageNumbers = document.createElement('span');
for (var i = 1; i <= pageCount; i++) {
let pageEitherSide = 4;
// let currentPage = Number(pagerCheck.innerHTML);
let currentPage = pageNumber;
let pageNumbers = document.createElement('span');
for (let i = 1; i <= pageCount; i++) {
if (
(
(i >= currentPage - pageEitherSide) &&
@@ -247,7 +282,7 @@ function formatGamesPanel(targetElement, result, pageNumber, pageSize, forceScro
)
)
) {
var pageNum = document.createElement('span');
let pageNum = document.createElement('span');
if (pageNumber == i) {
pageNum.className = 'games_pager_number_disabled';
} else {
@@ -260,7 +295,7 @@ function formatGamesPanel(targetElement, result, pageNumber, pageSize, forceScro
}
// add next page button
var nextPage = document.createElement('span');
let nextPage = document.createElement('span');
nextPage.innerHTML = '&gt;';
if (pageNumber == pageCount) {
nextPage.className = 'games_pager_number_disabled';
@@ -270,7 +305,7 @@ function formatGamesPanel(targetElement, result, pageNumber, pageSize, forceScro
}
// add last page button
var lastPage = document.createElement('span');
let lastPage = document.createElement('span');
lastPage.innerHTML = '&gt;&#124;';
if (pageNumber == pageCount) {
lastPage.className = 'games_pager_number_disabled';
@@ -297,7 +332,9 @@ function formatGamesPanel(targetElement, result, pageNumber, pageSize, forceScro
visibleOnly: true,
defaultImage: '/images/unknowngame.png',
delay: 250,
afterLoad: function(element) {
enableThrottle: true,
throttle: 250,
afterLoad: function (element) {
//console.log(element[0].getAttribute('data-id'));
}
});
@@ -305,11 +342,11 @@ function formatGamesPanel(targetElement, result, pageNumber, pageSize, forceScro
function isScrolledIntoView(elem) {
if (elem) {
var docViewTop = $(window).scrollTop();
var docViewBottom = docViewTop + $(window).height();
let docViewTop = $(window).scrollTop();
let docViewBottom = docViewTop + $(window).height();
var elemTop = $(elem).offset().top;
var elemBottom = elemTop + $(elem).height();
let elemTop = $(elem).offset().top;
let elemBottom = elemTop + $(elem).height();
return ((elemBottom <= docViewBottom) && (elemTop >= docViewTop));
}
@@ -319,22 +356,22 @@ const elementIsVisibleInViewport = (el, partiallyVisible = false) => {
const { top, left, bottom, right } = el.getBoundingClientRect();
const { innerHeight, innerWidth } = window;
return partiallyVisible
? ((top > 0 && top < innerHeight) ||
(bottom > 0 && bottom < innerHeight)) &&
((left > 0 && left < innerWidth) || (right > 0 && right < innerWidth))
: top >= 0 && left >= 0 && bottom <= innerHeight && right <= innerWidth;
};
? ((top > 0 && top < innerHeight) ||
(bottom > 0 && bottom < innerHeight)) &&
((left > 0 && left < innerWidth) || (right > 0 && right < innerWidth))
: top >= 0 && left >= 0 && bottom <= innerHeight && right <= innerWidth;
};
function IsInView() {
var pageMode = GetPreference('LibraryPagination', 'paged');
let pageMode = GetPreference('LibraryPagination', 'infinite');
switch (pageMode) {
case "paged":
var loadElement = document.getElementById('games_library_loadmore');
let loadElement = document.getElementById('games_library_loadmore');
if (loadElement) {
//if (isScrolledIntoView(loadElement)) {
if (elementIsVisibleInViewport(loadElement, true)) {
var pageNumber = Number(document.getElementById('games_library_loadmore').getAttribute('data-pagenumber'));
var pageSize = document.getElementById('games_library_loadmore').getAttribute('data-pagesize');
let pageNumber = Number(document.getElementById('games_library_loadmore').getAttribute('data-pagenumber'));
let pageSize = document.getElementById('games_library_loadmore').getAttribute('data-pagesize');
executeFilter1_1(pageNumber);
}
}
@@ -350,7 +387,6 @@ function IsInView() {
//if (isScrolledIntoView(anchors[i])) {
if (elementIsVisibleInViewport(anchors[i], true)) {
if (anchors[i].getAttribute('data-loaded') == "0") {
console.log("Loading page: " + anchors[i].getAttribute('data-page'));
document.getElementById(anchors[i].id).setAttribute('data-loaded', "1");
executeFilter1_1(Number(anchors[i].getAttribute('data-page')));
}
@@ -360,29 +396,31 @@ function IsInView() {
}
}
$(window).scroll(IsInView);
function renderGameIcon(gameObject, showTitle, showRatings, showClassification, classificationDisplayOrder, useSmallCover, listView) {
if (listView == undefined) {
listView = false;
}
var classes = getViewModeClasses(listView);
let classes = getViewModeClasses(listView);
var gameBox = document.createElement('div');
let gameBox = document.createElement('div');
gameBox.id = "game_tile_" + gameObject.id;
if (useSmallCover == true) {
gameBox.classList.add(...classes['game_tile game_tile_small']);
} else {
gameBox.classList.add(...classes['game_tile']);
}
gameBox.setAttribute('onclick', 'window.location.href = "/index.html?page=game&id=' + gameObject.id + '";');
gameBox.style.display = 'none';
// gameBox.style.display = 'none';
var gameImageBox = document.createElement('div');
let gameImageBox = document.createElement('div');
gameImageBox.classList.add(...classes['game_tile_box']);
if (listView == true) {
gameBox.setAttribute('onclick', 'window.location.href = "/index.html?page=game&id=' + gameObject.id + '";');
} else {
gameImageBox.setAttribute('onclick', 'window.location.href = "/index.html?page=game&id=' + gameObject.id + '";');
}
var gameImage = document.createElement('img');
let gameImage = document.createElement('img');
gameImage.id = 'game_tile_cover_' + gameObject.id;
gameImage.setAttribute('data-id', gameObject.id);
if (useSmallCover == true) {
@@ -392,20 +430,20 @@ function renderGameIcon(gameObject, showTitle, showRatings, showClassification,
}
// gameImage.src = '/images/unknowngame.png';
if (gameObject.cover) {
gameImage.setAttribute('data-src', '/api/v1.1/Games/' + gameObject.id + '/cover/image/cover_big/' + gameObject.cover.imageId + '.jpg');
gameImage.setAttribute('data-src', '/api/v1.1/Games/' + gameObject.id + '/cover/' + gameObject.cover.id + '/image/cover_big/' + gameObject.cover.id + '.jpg');
} else {
gameImage.classList.add(...classes['game_tile_image unknown']);
gameImage.setAttribute('data-src', '/images/unknowngame.png');
}
gameImageBox.appendChild(gameImage);
var classificationPath = '';
var displayClassification = false;
var shownClassificationBoard = '';
let classificationPath = '';
let displayClassification = false;
let shownClassificationBoard = '';
if (showClassification == true) {
for (var b = 0; b < classificationDisplayOrder.length; b++) {
for (let b = 0; b < classificationDisplayOrder.length; b++) {
if (shownClassificationBoard == '') {
for (var c = 0; c < gameObject.ageRatings.length; c++) {
for (let c = 0; c < gameObject.ageRatings.length; c++) {
if (gameObject.ageRatings[c].category == classificationDisplayOrder[b]) {
shownClassificationBoard = classificationDisplayOrder[b];
displayClassification = true;
@@ -420,42 +458,78 @@ function renderGameIcon(gameObject, showTitle, showRatings, showClassification,
// add save game icon
if (gameObject.hasSavedGame == true) {
var gameSaveIcon = document.createElement('img');
let gameSaveIcon = document.createElement('img');
gameSaveIcon.src = '/images/SaveStates.png';
gameSaveIcon.classList.add(...classes['game_tile_box_savedgame savedstateicon']);
gameImageBox.appendChild(gameSaveIcon);
}
// add favourite game icon
if (gameObject.isFavourite == true) {
var gameFavIcon = document.createElement('img');
gameFavIcon.src = '/images/favourite-filled.svg';
gameFavIcon.classList.add(...classes['game_tile_box_favouritegame favouriteicon']);
gameImageBox.appendChild(gameFavIcon);
}
let gameFavIconBox = document.createElement('div');
gameFavIconBox.classList.add(...classes['game_tile_box_favouritegame']);
let gameFavIcon = document.createElement('img');
gameFavIcon.classList.add(...classes['favouriteicon']);
if (gameObject.isFavourite == true) {
gameFavIcon.src = '/images/favourite-filled.svg';
gameFavIconBox.classList.add('favourite-filled');
} else {
gameFavIcon.src = '/images/favourite-empty.svg';
gameFavIconBox.classList.add('favourite-empty');
}
gameFavIconBox.appendChild(gameFavIcon);
gameFavIconBox.addEventListener('click', (e) => {
e.stopPropagation();
if (gameFavIconBox.classList.contains('favourite-filled')) {
gameFavIcon.src = '/images/favourite-empty.svg';
gameFavIconBox.classList.remove('favourite-filled');
gameFavIconBox.classList.add('favourite-empty');
gameObject.isFavourite = false;
} else {
gameFavIcon.src = '/images/favourite-filled.svg';
gameFavIconBox.classList.remove('favourite-empty');
gameFavIconBox.classList.add('favourite-filled');
gameObject.isFavourite = true;
}
fetch('/api/v1.1/Games/' + gameObject.id + '/favourite?favourite=' + gameObject.isFavourite, {
method: 'POST'
}).then(response => {
if (response.ok) {
// console.log('Favourite status updated');
} else {
// console.log('Failed to update favourite status');
}
});
});
gameImageBox.appendChild(gameFavIconBox);
// add ratings banner
if (gameObject.totalRating || displayClassification == true) {
var gameImageRatingBanner = document.createElement('div');
let gameImageRatingBanner = document.createElement('div');
gameImageRatingBanner.classList.add(...classes['game_tile_box_ratingbanner']);
if (showRatings == true || displayClassification == true) {
if (showRatings == true) {
if (gameObject.totalRating) {
var gameImageRatingBannerLogo = document.createElement('img');
let gameImageRatingBannerLogo = document.createElement('img');
gameImageRatingBannerLogo.src = '/images/IGDB_logo.svg';
gameImageRatingBannerLogo.setAttribute('style', 'filter: invert(100%); height: 10px; margin-right: 5px; padding-top: 4px;');
gameImageRatingBanner.appendChild(gameImageRatingBannerLogo);
var gameImageRatingBannerValue = document.createElement('span');
let gameImageRatingBannerValue = document.createElement('span');
gameImageRatingBannerValue.innerHTML = Math.floor(gameObject.totalRating) + '% / ' + gameObject.totalRatingCount;
gameImageRatingBanner.appendChild(gameImageRatingBannerValue);
}
}
gameImageBox.appendChild(gameImageRatingBanner);
if (displayClassification == true) {
var gameImageClassificationLogo = document.createElement('img');
let gameImageClassificationLogo = document.createElement('img');
gameImageClassificationLogo.src = classificationPath;
gameImageClassificationLogo.classList.add(...classes['rating_image_overlay']);
gameImageBox.appendChild(gameImageClassificationLogo);
@@ -465,10 +539,19 @@ function renderGameIcon(gameObject, showTitle, showRatings, showClassification,
gameBox.appendChild(gameImageBox);
if (showTitle == true) {
var gameBoxTitle = document.createElement('div');
let gameBoxTitle = document.createElement('div');
gameBoxTitle.classList.add(...classes['game_tile_label']);
gameBoxTitle.innerHTML = gameObject.name;
gameBox.appendChild(gameBoxTitle);
if (listView == true) {
if (gameObject.summary) {
let gameBoxSummary = document.createElement('div');
gameBoxSummary.classList.add(...classes['game_tile_summary']);
gameBoxSummary.innerHTML = gameObject.summary;
gameBox.appendChild(gameBoxSummary);
}
}
}
return gameBox;
@@ -477,31 +560,37 @@ function renderGameIcon(gameObject, showTitle, showRatings, showClassification,
function getViewModeClasses(listView) {
if (listView == false) {
return {
"game_tile game_tile_small": [ "game_tile", "game_tile_small" ],
"game_tile": [ "game_tile" ],
"game_tile_box": [ "game_tile_box" ],
"game_tile_image game_tile_image_small lazy": [ "game_tile_image", "game_tile_image_small", "lazy" ],
"game_tile_image lazy": [ "game_tile_image", "lazy" ],
"game_tile_image unknown": [ "game_tile_image", "unknown" ],
"game_tile_box_savedgame savedstateicon": [ "game_tile_box_savedgame", "savedstateicon" ],
"game_tile_box_favouritegame favouriteicon": [ "game_tile_box_favouritegame", "favouriteicon" ],
"game_tile_box_ratingbanner": [ "game_tile_box_ratingbanner" ],
"rating_image_overlay": [ "rating_image_overlay" ],
"game_tile_label": [ "game_tile_label" ]
"game_tile game_tile_small": ["game_tile", "game_tile_small"],
"game_tile": ["game_tile"],
"game_tile_box": ["game_tile_box"],
"game_tile_image game_tile_image_small lazy": ["game_tile_image", "game_tile_image_small", "lazy"],
"game_tile_image lazy": ["game_tile_image", "lazy"],
"game_tile_image unknown": ["game_tile_image", "unknown"],
"game_tile_box_savedgame savedstateicon": ["game_tile_box_savedgame", "savedstateicon"],
"game_tile_box_favouritegame favouriteicon": ["game_tile_box_favouritegame", "favouriteicon"],
"game_tile_box_favouritegame": ["game_tile_box_favouritegame"],
"favouriteicon": ["favouriteicon"],
"game_tile_box_ratingbanner": ["game_tile_box_ratingbanner"],
"rating_image_overlay": ["rating_image_overlay"],
"game_tile_label": ["game_tile_label"],
"game_tile_summary": ["game_tile_summary"]
};
} else {
return {
"game_tile game_tile_small": [ "game_tile_row", "game_tile_small" ],
"game_tile": [ "game_tile_row" ],
"game_tile_box": [ "game_tile_box_row" ],
"game_tile_image game_tile_image_small lazy": [ "game_tile_image_row", "game_tile_image_small", "lazy" ],
"game_tile_image lazy": [ "game_tile_image_row", "lazy" ],
"game_tile_image unknown": [ "game_tile_image_row", "unknown" ],
"game_tile_box_savedgame savedstateicon": [ "game_tile_box_savedgame_row", "savedstateicon" ],
"game_tile_box_favouritegame favouriteicon": [ "game_tile_box_favouritegame_row", "favouriteicon" ],
"game_tile_box_ratingbanner": [ "game_tile_box_ratingbanner_row" ],
"rating_image_overlay": [ "rating_image_overlay_row" ],
"game_tile_label": [ "game_tile_label_row" ]
"game_tile game_tile_small": ["game_tile_row", "game_tile_small"],
"game_tile": ["game_tile_row"],
"game_tile_box": ["game_tile_box_row"],
"game_tile_image game_tile_image_small lazy": ["game_tile_image_row", "game_tile_image_small", "lazy"],
"game_tile_image lazy": ["game_tile_image_row", "lazy"],
"game_tile_image unknown": ["game_tile_image_row", "unknown"],
"game_tile_box_savedgame savedstateicon": ["game_tile_box_savedgame_row", "savedstateicon"],
"game_tile_box_favouritegame favouriteicon": ["game_tile_box_favouritegame_row", "favouriteicon"],
"game_tile_box_favouritegame": ["game_tile_box_favouritegame_row"],
"favouriteicon": ["favouriteicon"],
"game_tile_box_ratingbanner": ["game_tile_box_ratingbanner_row"],
"rating_image_overlay": ["rating_image_overlay_row"],
"game_tile_label": ["game_tile_label_row"],
"game_tile_summary": ["game_tile_summary_row"]
};
}
}

View File

@@ -0,0 +1,140 @@
class NewLibrary {
constructor() {
}
async open() {
// Create the modal
this.dialog = await new Modal("newlibrary");
await this.dialog.BuildModal();
// override the dialog size
this.dialog.modalElement.style = 'width: 600px; height: unset; min-width: unset; min-height: 215px; max-width: unset; max-height: unset;';
// setup the dialog
this.dialog.modalElement.querySelector('#modal-header-text').innerHTML = "New Library";
// set up the library name field
this.LibraryName = this.dialog.modalElement.querySelector('#librarynew_name');
this.LibraryName.addEventListener('input', async () => {
await this.validate();
});
// set up the library path field
this.LibraryPath = this.dialog.modalElement.querySelector('#librarynew_path');
this.LibraryPath.addEventListener('input', async () => {
await this.validate();
});
// setup the path selector button
let pathSelector = this.dialog.modalElement.querySelector('#librarynew_pathSelect');
pathSelector.addEventListener('click', async () => {
let fileOpen = new FileOpen(
async () => {
this.LibraryPath.value = fileOpen.SelectedPath;
await this.validate();
},
undefined,
false
);
await fileOpen.open();
});
// setup the default platform drop down
this.defaultPlatformSelector = this.dialog.modalElement.querySelector('#librarynew_defaultPlatformId');
$(this.defaultPlatformSelector).select2({
minimumInputLength: 3,
placeholder: 'Any',
allowClear: true,
ajax: {
url: '/api/v1.1/Search/Platform',
data: function (params) {
var query = {
SearchString: params.term
}
// Query parameters will be ?SearchString=[term]
return query;
},
processResults: function (data) {
var arr = [];
for (var i = 0; i < data.length; i++) {
arr.push({
id: data[i].id,
text: data[i].name
});
}
return {
results: arr
};
}
}
});
// add ok button
let okButton = new ModalButton("OK", 1, this, async function (callingObject) {
if (await callingObject.validate()) {
// create the library
let defaultPlatform = 0;
let defaultPlatformSelector = $(callingObject.defaultPlatformSelector).select2('data');
if (defaultPlatformSelector.length > 0) {
defaultPlatform = defaultPlatformSelector[0].id;
}
ajaxCall(
'/api/v1.1/Library?Name=' + encodeURIComponent(callingObject.LibraryName.value) + '&DefaultPlatformId=' + defaultPlatform + '&Path=' + encodeURIComponent(callingObject.LibraryPath.value),
'POST',
function (result) {
// call the page drawLibrary function
drawLibrary();
// close the dialog
callingObject.dialog.close();
},
function (error) {
alert('An error occurred while creating the library:\n\n' + JSON.stringify(error.responseText));
}
);
}
});
this.dialog.addButton(okButton);
// add cancel button
let cancelButton = new ModalButton("Cancel", 0, this, async function (callingObject) {
callingObject.dialog.close();
});
this.dialog.addButton(cancelButton);
// show the dialog
this.dialog.open();
// disable the ok button
this.dialog.disableButton("OK");
}
async validate() {
let valid = true;
// check name
if (this.LibraryName.value === "") {
valid = false;
}
// check path
if (this.LibraryPath.value === "") {
valid = false;
}
if (valid) {
this.dialog.enableButton("OK");
} else {
this.dialog.disableButton("OK");
}
return valid;
}
}

View File

@@ -28,6 +28,7 @@ function ajaxCall(endpoint, method, successFunction, errorFunction, body) {
// Error handling
error: function (error) {
console.log('Error reaching URL: ' + endpoint);
console.log(`Error ${JSON.stringify(error)}`);
if (errorFunction) {
@@ -39,7 +40,7 @@ function ajaxCall(endpoint, method, successFunction, errorFunction, body) {
function getQueryString(stringName, type) {
const urlParams = new URLSearchParams(window.location.search);
var myParam = urlParams.get(stringName);
var myParam = urlParams.get(stringName);
switch (type) {
case "int":
@@ -63,9 +64,9 @@ function getQueryString(stringName, type) {
function setCookie(cname, cvalue, exdays) {
const d = new Date();
d.setTime(d.getTime() + (exdays*24*60*60*1000));
d.setTime(d.getTime() + (exdays * 24 * 60 * 60 * 1000));
if (exdays) {
let expires = "expires="+ d.toUTCString();
let expires = "expires=" + d.toUTCString();
document.cookie = cname + "=" + cvalue + ";" + expires + ";path=/";
} else {
document.cookie = cname + "=" + cvalue + ";path=/";
@@ -76,14 +77,14 @@ function getCookie(cname) {
let name = cname + "=";
let decodedCookie = decodeURIComponent(document.cookie);
let ca = decodedCookie.split(';');
for(let i = 0; i <ca.length; i++) {
let c = ca[i];
while (c.charAt(0) == ' ') {
c = c.substring(1);
}
if (c.indexOf(name) == 0) {
return c.substring(name.length, c.length);
}
for (let i = 0; i < ca.length; i++) {
let c = ca[i];
while (c.charAt(0) == ' ') {
c = c.substring(1);
}
if (c.indexOf(name) == 0) {
return c.substring(name.length, c.length);
}
}
return "";
}
@@ -207,12 +208,16 @@ function createTableRow(isHeader, row, rowClass, cellClass) {
}
var newCell = document.createElement(cellType);
if (typeof(row[i]) != "object") {
if (typeof (row[i]) != "object") {
newCell.innerHTML = row[i];
newCell.className = cellClass;
} else {
if (Array.isArray(row[i])) {
newCell.innerHTML = row[i][0];
if (typeof (row[i][0]) != "object") {
newCell.innerHTML = row[i][0];
} else {
newCell.appendChild(row[i][0]);
}
if (row[i][1]) { newCell.className = row[i][1]; }
if (row[i][2]) { newCell.setAttribute('name', row[i][2]); }
} else {
@@ -249,16 +254,18 @@ function DropDownRenderGameOption(state) {
return state;
}
var response;
let response;
var releaseDate;
let releaseDate;
if (state.releaseDate) {
releaseDate = moment(state.releaseDate).format('yyyy');
} else {
releaseDate = '';
}
if (state.cover) {
response = $(
'<table class="dropdown-div"><tr><td class="dropdown-cover"><img src="/api/v1.1/Games/' + state.id + '/cover/image/cover_small/' + state.cover.imageId + '.jpg" /></td><td class="dropdown-label"><span class="dropdown-title">' + state.text + '</span><span class="dropdown-releasedate">' + releaseDate + '</span></td></tr></table>'
'<table class="dropdown-div"><tr><td class="dropdown-cover"><img src="/api/v1.1/Games/' + state.id + '/cover/' + state.cover.id + '/image/cover_small/' + state.id + '.jpg" class="game_tile_small_search" /></td><td class="dropdown-label"><span class="dropdown-title">' + state.text + '</span><span class="dropdown-releasedate">' + releaseDate + '</span></td></tr></table>'
);
} else {
response = $(
@@ -317,8 +324,8 @@ function CreateEditableTable(TableName, Headers) {
var addButton = document.createElement('button');
addButton.value = 'Add Row';
addButton.innerHTML = 'Add Row';
$(addButton).click(function() {
$(addButton).click(function () {
eTable.appendChild(AddEditableTableRow(Headers));
});
@@ -442,6 +449,7 @@ function GetPreference(Setting, DefaultValue) {
if (userProfile.userPreferences) {
for (var i = 0; i < userProfile.userPreferences.length; i++) {
if (userProfile.userPreferences[i].setting == Setting) {
// console.log("Get Preference: " + Setting + " : " + userProfile.userPreferences[i].value.toString());
return userProfile.userPreferences[i].value.toString();
}
}
@@ -449,10 +457,12 @@ function GetPreference(Setting, DefaultValue) {
SetPreference(Setting, DefaultValue);
console.log("Get Preference: " + Setting + " : " + DefaultValue);
return DefaultValue;
}
function SetPreference(Setting, Value) {
function SetPreference(Setting, Value, callbackSuccess, callbackError) {
console.log("Set Preference: " + Setting + " : " + Value.toString());
var model = [
{
"setting": Setting,
@@ -463,33 +473,60 @@ function SetPreference(Setting, Value) {
ajaxCall(
'/api/v1.1/Account/Preferences',
'POST',
function(result) {
function (result) {
SetPreference_Local(Setting, Value);
if (callbackSuccess) {
callbackSuccess();
}
},
function(error) {
function (error) {
SetPreference_Local(Setting, Value);
if (callbackError) {
callbackError();
}
},
JSON.stringify(model)
);
}
function SetPreference_Batch(model) {
console.log(model);
ajaxCall(
'/api/v1.1/Account/Preferences',
'POST',
function(result) {
for (var i = 0; i < model.length; i++) {
async function SetPreference_Batch(model, callbackSuccess, callbackError) {
await fetch('/api/v1.1/Account/Preferences', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(model)
})
.then(response => {
for (let i = 0; i < model.length; i++) {
SetPreference_Local(model[i].setting, model[i].value.toString());
}
},
function(error) {
for (var i = 0; i < model.length; i++) {
})
.then(response => {
if (response.ok) {
console.log("SetPreference_Batch: Success");
if (callbackSuccess) {
callbackSuccess();
}
} else {
console.log("SetPreference_Batch: Error: " + response.statusText);
if (callbackError) {
callbackError();
}
}
})
.catch(error => {
for (let i = 0; i < model.length; i++) {
SetPreference_Local(model[i].setting, model[i].value.toString());
}
},
JSON.stringify(model)
);
console.log("SetPreference_Batch: Error: " + error);
if (callbackError) {
callbackError();
}
});
}
function SetPreference_Local(Setting, Value) {
@@ -509,11 +546,11 @@ function SetPreference_Local(Setting, Value) {
}
}
function Uint8ToString(u8a){
function Uint8ToString(u8a) {
var CHUNK_SZ = 0x8000;
var c = [];
for (var i=0; i < u8a.length; i+=CHUNK_SZ) {
c.push(String.fromCharCode.apply(null, u8a.subarray(i, i+CHUNK_SZ)));
for (var i = 0; i < u8a.length; i += CHUNK_SZ) {
c.push(String.fromCharCode.apply(null, u8a.subarray(i, i + CHUNK_SZ)));
}
return c.join("");
}
@@ -538,4 +575,149 @@ function loadAvatar(AvatarId) {
bannerAvatarButton.classList.add('banner_button');
}
}
}
function GetRatingsBoards() {
let ratingsBoards = JSON.parse(GetPreference("LibraryGameClassificationDisplayOrder", JSON.stringify(["ESRB"])));
// add fallback ratings boards
if (!ratingsBoards.includes("ESRB")) { ratingsBoards.push("ESRB"); }
if (!ratingsBoards.includes("ACB")) { ratingsBoards.push("ACB"); }
if (!ratingsBoards.includes("PEGI")) { ratingsBoards.push("PEGI"); }
if (!ratingsBoards.includes("USK")) { ratingsBoards.push("USK"); }
if (!ratingsBoards.includes("CERO")) { ratingsBoards.push("CERO"); }
if (!ratingsBoards.includes("CLASS_IND")) { ratingsBoards.push("CLASS_IND"); }
if (!ratingsBoards.includes("GRAC")) { ratingsBoards.push("GRAC"); }
return ratingsBoards;
}
class BackgroundImageRotator {
constructor(URLList, CustomClass, Randomise) {
this.URLList = URLList;
if (Randomise == true) {
this.CurrentIndex = randomIntFromInterval(0, this.URLList.length - 1);
} else {
this.CurrentIndex = 0;
}
this.RotationTimer = undefined;
if (CustomClass) {
this.CustomClass = CustomClass;
this.CustomClassSet = true;
} else {
this.CustomClass = '';
this.CustomClassSet = false;
}
this.bgImages = document.getElementById('bgImages');
this.bgImages.innerHTML = '';
// apply default background image
let defaultBgImage = this.#CreateBackgroundImage('DefaultBgImage', '/images/librarybg.jpg');
if (this.URLList) {
if (this.URLList.length > 1) {
// handle multiple supplied images
// create the first image
let bgImage = this.#CreateBackgroundImage('bgImage0', this.URLList[this.CurrentIndex]);
this.bgImages.appendChild(bgImage);
// start the rotation
this.StartRotation();
} else if (this.URLList.length == 1) {
// handle only a single supplied image
this.CurrentIndex = 0;
// create the image
let bgImage = this.#CreateBackgroundImage('bgImage0', this.URLList[0]);
this.bgImages.appendChild(bgImage);
} else {
// no supplied images, but URLList is defined
this.CurrentIndex = 0;
// apply default background image
this.bgImages.appendChild(defaultBgImage);
}
} else {
// no supplied images, and URLList is not defined
this.CurrentIndex = 0;
// apply default background image
this.bgImages.appendChild(defaultBgImage);
}
}
#CreateBackgroundImage(Id, URL) {
let BgImage = document.createElement('div');
BgImage.id = Id;
BgImage.classList.add('bgImage');
if (this.CustomClassSet == true) {
BgImage.classList.add(this.CustomClass);
}
BgImage.style.backgroundImage = "url('" + URL + "')";
return BgImage;
}
// rotate each image in URLList using a JQuery fade in/out effect every 10 seconds
StartRotation() {
this.RotationTimer = setInterval(this.RotateImage.bind(this), 10000);
}
// stop the rotation
StopRotation() {
clearInterval(this.RotationTimer);
}
// rotate the image
RotateImage() {
// get the current background image
let currentImage = this.bgImages.querySelector('#bgImage' + this.CurrentIndex);
// increment the index
this.CurrentIndex += 1;
if (this.CurrentIndex >= this.URLList.length) {
this.CurrentIndex = 0;
}
// create a new background image
let bgImage = this.#CreateBackgroundImage('bgImage' + this.CurrentIndex, this.URLList[this.CurrentIndex]);
bgImage.style.display = 'none';
this.bgImages.appendChild(bgImage);
// fade out the current image
$(bgImage).fadeIn(1000, function () {
// remove the old image
currentImage.remove();
});
// clear the timer
clearInterval(this.RotationTimer);
// restart the timer
this.StartRotation();
}
}
function BuildLaunchLink(engine, core, platformId, gameId, romId, isMediaGroup, filename) {
let launchLink = '/index.html?page=emulator&engine=<ENGINE>&core=<CORE>&platformid=<PLATFORMID>&gameid=<GAMEID>&romid=<ROMID>&mediagroup=<ISMEDIAGROUP>&rompath=<FILENAME>';
// http://localhost:5198/index.html?page=emulator&engine=EmulatorJS&core=amiga&platformid=16&gameid=5519&romid=19&mediagroup=1&rompath=%2Fapi%2Fv1.1%2FGames%2F5519%2Fromgroup%2F19%2FCannon%20Fodder.zip
// http://localhost:5198/index.html?page=emulator&engine=EmulatorJS&core=amiga&platformid=16&gameid=5519&romid=102&mediagroup=0&rompath=%2Fapi%2Fv1.1%2FGames%2F5519%2Froms%2F102%2FCannon%20Fodder%20(1993)(Virgin)(Disk%201%20of%203)%5Bcr%20CSL%5D.adf
launchLink = launchLink.replace('<ENGINE>', engine);
launchLink = launchLink.replace('<CORE>', core);
launchLink = launchLink.replace('<PLATFORMID>', platformId);
launchLink = launchLink.replace('<GAMEID>', gameId);
launchLink = launchLink.replace('<ROMID>', romId);
if (isMediaGroup == true) {
launchLink = launchLink.replace('<ISMEDIAGROUP>', 1);
launchLink = launchLink.replace('<FILENAME>', '/api/v1.1/Games/' + encodeURI(gameId) + '/romgroup/' + encodeURI(romId) + '/' + encodeURI(filename) + '.zip');
} else {
launchLink = launchLink.replace('<ISMEDIAGROUP>', 0);
launchLink = launchLink.replace('<FILENAME>', '/api/v1.1/Games/' + encodeURI(gameId) + '/roms/' + encodeURI(romId) + '/' + encodeURI(filename));
}
return launchLink;
}

Some files were not shown because too many files have changed in this diff Show More