From b9d9b0ea162ddb73538da3c0a394bb09c54a54a5 Mon Sep 17 00:00:00 2001 From: Michael Green <84688932+michael-j-green@users.noreply.github.com> Date: Wed, 20 Dec 2023 13:31:45 +1100 Subject: [PATCH] Filter ROMs by platform (#236) * Added paging to the ROM display on game pages * Added basic ROM filtering --- README.MD | 2 +- gaseous-server/Classes/Roms.cs | 39 ++++- .../Controllers/V1.0/GamesController.cs | 4 +- .../wwwroot/pages/dialogs/collectionedit.html | 4 +- .../pages/dialogs/settingsuseredit.html | 2 +- gaseous-server/wwwroot/pages/game.html | 137 ++++++++++++++++-- gaseous-server/wwwroot/styles/style.css | 38 +++++ 7 files changed, 199 insertions(+), 27 deletions(-) diff --git a/README.MD b/README.MD index d054465..724cdd5 100644 --- a/README.MD +++ b/README.MD @@ -1,6 +1,6 @@ # Gaseous Server -This is the server for the Gaseous system. It offers ROM and title management, as well as some basic in browser emulation of those ROM's. +This is the server for the Gaseous system. It offers ROM and title management, as well as some basic in browser emulation of those ROMs. ## Warning diff --git a/gaseous-server/Classes/Roms.cs b/gaseous-server/Classes/Roms.cs index 70fb73c..f1ee137 100644 --- a/gaseous-server/Classes/Roms.cs +++ b/gaseous-server/Classes/Roms.cs @@ -3,6 +3,7 @@ using System.Data; using gaseous_signature_parser.models.RomSignatureObject; using static gaseous_server.Classes.RomMediaGroup; using gaseous_server.Classes.Metadata; +using IGDB.Models; namespace gaseous_server.Classes { @@ -14,7 +15,7 @@ namespace gaseous_server.Classes {} } - public static GameRomObject GetRoms(long GameId, long PlatformId = -1) + public static GameRomObject GetRoms(long GameId, long PlatformId = -1, int pageNumber = 0, int pageSize = 0) { GameRomObject GameRoms = new GameRomObject(); @@ -24,23 +25,43 @@ namespace gaseous_server.Classes dbDict.Add("id", GameId); if (PlatformId == -1) { - sql = "SELECT * FROM Games_Roms WHERE GameId = @id ORDER BY `Name`"; + sql = "SELECT Games_Roms.*, Platform.`Name` AS platformname FROM Games_Roms LEFT JOIN Platform ON Games_Roms.PlatformId = Platform.Id WHERE Games_Roms.GameId = @id ORDER BY Platform.`Name`, Games_Roms.`Name`"; } else { - sql = "SELECT * FROM Games_Roms WHERE GameId = @id AND PlatformId = @platformid ORDER BY `Name`"; + sql = "SELECT Games_Roms.*, Platform.`Name` AS platformname FROM Games_Roms LEFT JOIN Platform ON Games_Roms.PlatformId = Platform.Id WHERE Games_Roms.GameId = @id AND Games_Roms.PlatformId = @platformid ORDER BY Platform.`Name`, Games_Roms.`Name`"; dbDict.Add("platformid", PlatformId); } DataTable romDT = db.ExecuteCMD(sql, dbDict); if (romDT.Rows.Count > 0) { - foreach (DataRow romDR in romDT.Rows) + // set count of roms + GameRoms.Count = romDT.Rows.Count; + + // setup platforms list + Dictionary platformDict = new Dictionary(); + + int pageOffset = pageSize * (pageNumber - 1); + for (int i = 0; i < romDT.Rows.Count; i++) { - GameRoms.GameRomItems.Add(BuildRom(romDR)); + GameRomItem gameRomItem = BuildRom(romDT.Rows[i]); + + if ((i >= pageOffset && i < pageOffset + pageSize) || pageSize == 0) + { + GameRoms.GameRomItems.Add(gameRomItem); + } + + if (!platformDict.ContainsKey(gameRomItem.PlatformId)) + { + platformDict.Add(gameRomItem.PlatformId, gameRomItem.Platform); + } } // get rom media groups GameRoms.MediaGroups = Classes.RomMediaGroup.GetMediaGroupsFromGameId(GameId); + // sort the platforms + GameRoms.Platforms = platformDict.OrderBy(x => x.Value).ToDictionary(x => x.Key, x => x.Value).ToList>(); + return GameRoms; } else @@ -52,7 +73,7 @@ namespace gaseous_server.Classes public static GameRomItem GetRom(long RomId) { Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString); - string sql = "SELECT * FROM Games_Roms WHERE Id = @id"; + string sql = "SELECT Games_Roms.*, Platform.`Name` AS platformname FROM Games_Roms LEFT JOIN Platform ON Games_Roms.PlatformId = Platform.Id WHERE Games_Roms.Id = @id"; Dictionary dbDict = new Dictionary(); dbDict.Add("id", RomId); DataTable romDT = db.ExecuteCMD(sql, dbDict); @@ -114,7 +135,7 @@ namespace gaseous_server.Classes { Id = (long)romDR["id"], PlatformId = (long)romDR["platformid"], - Platform = Classes.Metadata.Platforms.GetPlatform((long)romDR["platformid"]), + Platform = (string)romDR["platformname"], GameId = (long)romDR["gameid"], Name = (string)romDR["name"], Size = (long)romDR["size"], @@ -151,13 +172,15 @@ namespace gaseous_server.Classes { public List MediaGroups { get; set; } = new List(); public List GameRomItems { get; set; } = new List(); + public int Count { get; set; } + public List> Platforms { get; set; } } public class GameRomItem { public long Id { get; set; } public long PlatformId { get; set; } - public IGDB.Models.Platform Platform { get; set; } + public string Platform { get; set; } //public Dictionary? Emulator { get; set; } public Models.PlatformMapping.PlatformMapItem.WebEmulatorItem? Emulator { get; set; } public long GameId { get; set; } diff --git a/gaseous-server/Controllers/V1.0/GamesController.cs b/gaseous-server/Controllers/V1.0/GamesController.cs index 9c55f1b..094b6c1 100644 --- a/gaseous-server/Controllers/V1.0/GamesController.cs +++ b/gaseous-server/Controllers/V1.0/GamesController.cs @@ -870,13 +870,13 @@ namespace gaseous_server.Controllers [ProducesResponseType(typeof(Classes.Roms.GameRomObject), StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status404NotFound)] //[ResponseCache(CacheProfileName = "5Minute")] - public ActionResult GameRom(long GameId) + public ActionResult GameRom(long GameId, int pageNumber = 0, int pageSize = 0, long PlatformId = -1) { try { Game gameObject = Classes.Metadata.Games.GetGame(GameId, false, false, false); - return Ok(Classes.Roms.GetRoms(GameId)); + return Ok(Classes.Roms.GetRoms(GameId, PlatformId, pageNumber, pageSize)); } catch { diff --git a/gaseous-server/wwwroot/pages/dialogs/collectionedit.html b/gaseous-server/wwwroot/pages/dialogs/collectionedit.html index 8ca9d81..b414390 100644 --- a/gaseous-server/wwwroot/pages/dialogs/collectionedit.html +++ b/gaseous-server/wwwroot/pages/dialogs/collectionedit.html @@ -71,11 +71,11 @@ -

Standard layout: /<IGDB Platform Slug>/<IGDB Game Slug>/Game ROM's

+

Standard layout: /<IGDB Platform Slug>/<IGDB Game Slug>/Game ROMs

Example: /genesis-slash-megadrive/sonic-the-hedgehog/Sonic the Hedgehog.smd

diff --git a/gaseous-server/wwwroot/pages/dialogs/settingsuseredit.html b/gaseous-server/wwwroot/pages/dialogs/settingsuseredit.html index d559b25..e3b848a 100644 --- a/gaseous-server/wwwroot/pages/dialogs/settingsuseredit.html +++ b/gaseous-server/wwwroot/pages/dialogs/settingsuseredit.html @@ -50,7 +50,7 @@ -

Games and ROM's

+

Games and ROMs

Play games diff --git a/gaseous-server/wwwroot/pages/game.html b/gaseous-server/wwwroot/pages/game.html index 064bf57..78cb017 100644 --- a/gaseous-server/wwwroot/pages/game.html +++ b/gaseous-server/wwwroot/pages/game.html @@ -74,7 +74,7 @@
Edit -

ROM's/Images

+

ROMs/Images

-
+ @@ -365,6 +365,8 @@ var gameSummarySimilar = document.getElementById('gamesummarysimilar'); ajaxCall('/api/v1.1/Games/' + gameId + '/Related', 'GET', function (result) { if (result.games.length > 0) { + gameSummarySimilar.removeAttribute('style'); + var gameSummarySimilarContent = document.getElementById('gamesummarysimilar'); for (var i = 0; i < result.games.length; i++) { var similarObject = renderGameIcon(result.games[i], false, false, false, null, true); @@ -382,28 +384,94 @@ }); // load roms - loadRoms(); + loadRoms(false); }); - function loadRoms(displayCheckboxes) { + function loadRoms(displayCheckboxes, pageNumber, selectedPlatform) { + if (!pageNumber) { + pageNumber = 1; + } + + if (selectedPlatform == undefined) { + selectedPlatform = -1; + } + + console.log(selectedPlatform); + + var filterControlBlock = document.getElementById('games_library_controls'); + if (filterControlBlock) { + filterControlBlock.remove(); + } + var existingTable = document.getElementById('romtable'); if (existingTable) { existingTable.remove(); } + var romPager = document.getElementById('romPaginator'); + if (romPager) { + romPager.remove(); + } + var existingMgTable = document.getElementById('mediagrouptable'); if (existingMgTable) { existingMgTable.remove(); } + if (displayCheckboxes == undefined) { + if (document.getElementById('rom_edit_panel').style.display == 'none') { + displayCheckboxes = false; + } else { + displayCheckboxes = true; + } + } + var gameRoms = document.getElementById('gamesummaryroms'); - ajaxCall('/api/v1.1/Games/' + gameId + '/roms', 'GET', function (result) { + var pageSize = 20; + ajaxCall('/api/v1.1/Games/' + gameId + '/roms?pageNumber=' + pageNumber + '&pageSize=' + pageSize + '&platformId=' + selectedPlatform, 'GET', function (result) { + // display filter tools + var filterControls = document.createElement('div'); + filterControls.id = "games_library_controls"; + + var platformFilterBlock = document.createElement('div'); + platformFilterBlock.className = 'games_library_controlblock'; + + var platformFilterOpt = document.createElement('select'); + platformFilterOpt.id = "platform_filter"; + platformFilterOpt.setAttribute('onchange', 'loadRoms(' + undefined + ', ' + 1 + ', Number(document.getElementById("platform_filter").value));'); + + var platformFilterOptDefault = document.createElement('option'); + platformFilterOptDefault.value = '-1'; + platformFilterOptDefault.innerHTML = 'All Platforms'; + if (selectedPlatform == -1) { + platformFilterOptDefault.selected = 'selected'; + } + platformFilterOpt.appendChild(platformFilterOptDefault); + + for (var i = 0; i < result.platforms.length; i++) { + var platformFilterOptValue = document.createElement('option'); + platformFilterOptValue.value = result.platforms[i].key; + platformFilterOptValue.innerHTML = result.platforms[i].value; + if (selectedPlatform == Number(result.platforms[i].key)) { + platformFilterOptValue.selected = 'selected'; + } + platformFilterOpt.appendChild(platformFilterOptValue); + } + platformFilterBlock.appendChild(platformFilterOpt); + filterControls.appendChild(platformFilterBlock); + + var romCounter = document.createElement('div'); + romCounter.className = 'games_library_controlblock'; + romCounter.innerHTML = result.count + ' ROMs'; + filterControls.appendChild(romCounter); + + gameRoms.appendChild(filterControls); + if (result.gameRomItems) { var gameRomItems = result.gameRomItems; var mediaGroups = result.mediaGroups; - gameRomItems.sort((a, b) => a.platform.name.charCodeAt(0) - b.platform.name.charCodeAt(0)); - + // display roms var newTable = document.createElement('table'); newTable.id = 'romtable'; newTable.className = 'romtable'; @@ -412,23 +480,21 @@ var lastPlatform = ''; for (var i = 0; i < gameRomItems.length; i++) { - if (gameRomItems[i].platform.name != lastPlatform) { - lastPlatform = gameRomItems[i].platform.name; + if (gameRomItems[i].platform != lastPlatform) { + lastPlatform = gameRomItems[i].platform; var platformRow = document.createElement('tr'); var platformHeader = document.createElement('th'); platformHeader.setAttribute('colspan', 6); - platformHeader.innerHTML = '' + gameRomItems[i].platform.name; + platformHeader.innerHTML = '' + gameRomItems[i].platform; platformRow.appendChild(platformHeader); newTable.appendChild(platformRow); } - - var launchButton = ''; if (result.gameRomItems[i].emulator) { if (gameRomItems[i].emulator.type) { if (gameRomItems[i].emulator.type.length > 0) { - launchButton = 'Launch'; + launchButton = 'Launch'; } } } @@ -450,7 +516,52 @@ if (displayCheckboxes == true) { DisplayROMCheckboxes(true); } + + if (result.count > pageSize) { + // draw pagination + var numOfPages = Math.ceil(result.count / pageSize); + + var romPaginator = document.createElement('div'); + romPaginator.id = 'romPaginator'; + romPaginator.className = 'rom_pager'; + + // draw previous page button + var prevPage = document.createElement('span'); + prevPage.className = 'rom_pager_number_disabled'; + prevPage.innerHTML = '<'; + if (pageNumber != 1) { + prevPage.setAttribute('onclick', 'loadRoms(' + undefined + ', ' + (pageNumber - 1) + ', ' + selectedPlatform + ');'); + prevPage.className = 'rom_pager_number'; + } + romPaginator.appendChild(prevPage); + + // draw page numbers + for (var i = 0; i < numOfPages; i++) { + var romPaginatorPage = document.createElement('span'); + romPaginatorPage.className = 'rom_pager_number_disabled'; + romPaginatorPage.innerHTML = (i + 1); + if ((i + 1) != pageNumber) { + romPaginatorPage.setAttribute('onclick', 'loadRoms(' + undefined + ', ' + (i + 1) + ', ' + selectedPlatform + ');'); + romPaginatorPage.className = 'rom_pager_number'; + } + + romPaginator.appendChild(romPaginatorPage); + } + + // draw next page button + var nextPage = document.createElement('span'); + nextPage.className = 'rom_pager_number_disabled'; + nextPage.innerHTML = '>'; + if (pageNumber != numOfPages) { + nextPage.setAttribute('onclick', 'loadRoms(' + undefined + ', ' + (pageNumber + 1) + ', ' + selectedPlatform + ');'); + nextPage.className = 'rom_pager_number'; + } + romPaginator.appendChild(nextPage); + + gameRoms.appendChild(romPaginator); + } + // display media groups var mediaGroupDiv = document.getElementById('gamesummarymediagroups'); if (mediaGroups.length == 0) { mediaGroupDiv.style.display = 'none'; diff --git a/gaseous-server/wwwroot/styles/style.css b/gaseous-server/wwwroot/styles/style.css index 3bfa03a..d35f9c7 100644 --- a/gaseous-server/wwwroot/styles/style.css +++ b/gaseous-server/wwwroot/styles/style.css @@ -335,6 +335,40 @@ input[id='filter_panel_userrating_max'] { color: grey; } +.rom_pager { + position: absolute; + left: 50%; + transform: translate(-50%, 0); + padding-left: 20px; + padding-right: 20px; + padding-top: 15px; + padding-bottom: 15px; + font-size: 16px; + font-family: Commodore64; + text-align: center; + width: 80%; +} + +.rom_pager_number { + display: inline-block; + padding: 5px; + width: 40px; + text-align: center; +} + +.rom_pager_number:hover { + background-color: blue; + cursor: pointer; +} + +.rom_pager_number_disabled { + display: inline-block; + padding: 5px; + width: 40px; + text-align: center; + color: grey; +} + .filter_panel_item { display: flex; position: relative; @@ -524,6 +558,10 @@ input[id='filter_panel_userrating_max'] { width: 250px; } +#gamesummaryroms { + position: relative; +} + .game_cover_image { display: block; max-width: 250px;