Add more filter types (#50)

* feat: support for filtering by igdb rating

* fix: new user rating filter was always excluding unrated games

* feat: added metadata for game multiplayer modes

* feat: added metadata for game player perspectives

* feat: added metadata for game themes

* chore(deps): EmulatorJS version bump

* feat: all filters added

* feat: filter options now have visible toggles

* feat: jazzed up the styling of the game rating
This commit is contained in:
Michael Green
2023-08-13 17:41:56 +10:00
committed by GitHub
parent 14f836d46a
commit f7906f692d
14 changed files with 865 additions and 48 deletions

View File

@@ -0,0 +1,110 @@
using System;
using gaseous_tools;
using IGDB;
using IGDB.Models;
using MySqlX.XDevAPI.Common;
using static gaseous_tools.Config.ConfigFile;
namespace gaseous_server.Classes.Metadata
{
public class GameModes
{
const string fieldList = "fields checksum,created_at,name,slug,updated_at,url;";
public GameModes()
{
}
private static IGDBClient igdb = new IGDBClient(
// Found in Twitch Developer portal for your app
Config.IGDB.ClientId,
Config.IGDB.Secret
);
public static GameMode? GetGame_Modes(long? Id)
{
if ((Id == 0) || (Id == null))
{
return null;
}
else
{
Task<GameMode> RetVal = _GetGame_Modes(SearchUsing.id, Id);
return RetVal.Result;
}
}
public static GameMode GetGame_Modes(string Slug)
{
Task<GameMode> RetVal = _GetGame_Modes(SearchUsing.slug, Slug);
return RetVal.Result;
}
private static async Task<GameMode> _GetGame_Modes(SearchUsing searchUsing, object searchValue)
{
// check database first
Storage.CacheStatus? cacheStatus = new Storage.CacheStatus();
if (searchUsing == SearchUsing.id)
{
cacheStatus = Storage.GetCacheStatus("GameMode", (long)searchValue);
}
else
{
cacheStatus = Storage.GetCacheStatus("GameMode", (string)searchValue);
}
// set up where clause
string WhereClause = "";
switch (searchUsing)
{
case SearchUsing.id:
WhereClause = "where id = " + searchValue;
break;
case SearchUsing.slug:
WhereClause = "where slug = " + searchValue;
break;
default:
throw new Exception("Invalid search type");
}
GameMode returnValue = new GameMode();
bool forceImageDownload = false;
switch (cacheStatus)
{
case Storage.CacheStatus.NotPresent:
returnValue = await GetObjectFromServer(WhereClause);
Storage.NewCacheValue(returnValue);
forceImageDownload = true;
break;
case Storage.CacheStatus.Expired:
returnValue = await GetObjectFromServer(WhereClause);
Storage.NewCacheValue(returnValue, true);
forceImageDownload = true;
break;
case Storage.CacheStatus.Current:
returnValue = Storage.GetCacheValue<GameMode>(returnValue, "id", (long)searchValue);
break;
default:
throw new Exception("How did you get here?");
}
return returnValue;
}
private enum SearchUsing
{
id,
slug
}
private static async Task<GameMode> GetObjectFromServer(string WhereClause)
{
// get Game_Modes metadata
var results = await igdb.QueryAsync<GameMode>(IGDBClient.Endpoints.GameModes, query: fieldList + " " + WhereClause + ";");
var result = results.First();
return result;
}
}
}

View File

@@ -205,6 +205,22 @@ namespace gaseous_server.Classes.Metadata
}
}
if (Game.GameModes != null)
{
foreach (long gameModeId in Game.GameModes.Ids)
{
GameMode gameMode = GameModes.GetGame_Modes(gameModeId);
}
}
if (Game.MultiplayerModes != null)
{
foreach (long multiplayerModeId in Game.MultiplayerModes.Ids)
{
MultiplayerMode multiplayerMode = MultiplayerModes.GetGame_MultiplayerModes(multiplayerModeId);
}
}
if (Game.Platforms != null)
{
foreach (long PlatformId in Game.Platforms.Ids)
@@ -213,6 +229,14 @@ namespace gaseous_server.Classes.Metadata
}
}
if (Game.PlayerPerspectives != null)
{
foreach (long PerspectiveId in Game.PlayerPerspectives.Ids)
{
PlayerPerspective GamePlayPerspective = PlayerPerspectives.GetGame_PlayerPerspectives(PerspectiveId);
}
}
if (Game.Screenshots != null)
{
foreach (long ScreenshotId in Game.Screenshots.Ids)
@@ -221,6 +245,14 @@ namespace gaseous_server.Classes.Metadata
}
}
if (Game.Themes != null)
{
foreach (long ThemeId in Game.Themes.Ids)
{
Theme GameTheme = Themes.GetGame_Themes(ThemeId);
}
}
if (Game.Videos != null)
{
foreach (long GameVideoId in Game.Videos.Ids)

View File

@@ -0,0 +1,110 @@
using System;
using gaseous_tools;
using IGDB;
using IGDB.Models;
using MySqlX.XDevAPI.Common;
using static gaseous_tools.Config.ConfigFile;
namespace gaseous_server.Classes.Metadata
{
public class MultiplayerModes
{
const string fieldList = "fields campaigncoop,checksum,dropin,game,lancoop,offlinecoop,offlinecoopmax,offlinemax,onlinecoop,onlinecoopmax,onlinemax,platform,splitscreen,splitscreenonline;";
public MultiplayerModes()
{
}
private static IGDBClient igdb = new IGDBClient(
// Found in Twitch Developer portal for your app
Config.IGDB.ClientId,
Config.IGDB.Secret
);
public static MultiplayerMode? GetGame_MultiplayerModes(long? Id)
{
if ((Id == 0) || (Id == null))
{
return null;
}
else
{
Task<MultiplayerMode> RetVal = _GetGame_MultiplayerModes(SearchUsing.id, Id);
return RetVal.Result;
}
}
public static MultiplayerMode GetGame_MultiplayerModes(string Slug)
{
Task<MultiplayerMode> RetVal = _GetGame_MultiplayerModes(SearchUsing.slug, Slug);
return RetVal.Result;
}
private static async Task<MultiplayerMode> _GetGame_MultiplayerModes(SearchUsing searchUsing, object searchValue)
{
// check database first
Storage.CacheStatus? cacheStatus = new Storage.CacheStatus();
if (searchUsing == SearchUsing.id)
{
cacheStatus = Storage.GetCacheStatus("MultiplayerMode", (long)searchValue);
}
else
{
cacheStatus = Storage.GetCacheStatus("MultiplayerMode", (string)searchValue);
}
// set up where clause
string WhereClause = "";
switch (searchUsing)
{
case SearchUsing.id:
WhereClause = "where id = " + searchValue;
break;
case SearchUsing.slug:
WhereClause = "where slug = " + searchValue;
break;
default:
throw new Exception("Invalid search type");
}
MultiplayerMode returnValue = new MultiplayerMode();
bool forceImageDownload = false;
switch (cacheStatus)
{
case Storage.CacheStatus.NotPresent:
returnValue = await GetObjectFromServer(WhereClause);
Storage.NewCacheValue(returnValue);
forceImageDownload = true;
break;
case Storage.CacheStatus.Expired:
returnValue = await GetObjectFromServer(WhereClause);
Storage.NewCacheValue(returnValue, true);
forceImageDownload = true;
break;
case Storage.CacheStatus.Current:
returnValue = Storage.GetCacheValue<MultiplayerMode>(returnValue, "id", (long)searchValue);
break;
default:
throw new Exception("How did you get here?");
}
return returnValue;
}
private enum SearchUsing
{
id,
slug
}
private static async Task<MultiplayerMode> GetObjectFromServer(string WhereClause)
{
// get Game_MultiplayerModes metadata
var results = await igdb.QueryAsync<MultiplayerMode>(IGDBClient.Endpoints.MultiplayerModes, query: fieldList + " " + WhereClause + ";");
var result = results.First();
return result;
}
}
}

View File

@@ -0,0 +1,110 @@
using System;
using gaseous_tools;
using IGDB;
using IGDB.Models;
using MySqlX.XDevAPI.Common;
using static gaseous_tools.Config.ConfigFile;
namespace gaseous_server.Classes.Metadata
{
public class PlayerPerspectives
{
const string fieldList = "fields checksum,created_at,name,slug,updated_at,url;";
public PlayerPerspectives()
{
}
private static IGDBClient igdb = new IGDBClient(
// Found in Twitch Developer portal for your app
Config.IGDB.ClientId,
Config.IGDB.Secret
);
public static PlayerPerspective? GetGame_PlayerPerspectives(long? Id)
{
if ((Id == 0) || (Id == null))
{
return null;
}
else
{
Task<PlayerPerspective> RetVal = _GetGame_PlayerPerspectives(SearchUsing.id, Id);
return RetVal.Result;
}
}
public static PlayerPerspective GetGame_PlayerPerspectives(string Slug)
{
Task<PlayerPerspective> RetVal = _GetGame_PlayerPerspectives(SearchUsing.slug, Slug);
return RetVal.Result;
}
private static async Task<PlayerPerspective> _GetGame_PlayerPerspectives(SearchUsing searchUsing, object searchValue)
{
// check database first
Storage.CacheStatus? cacheStatus = new Storage.CacheStatus();
if (searchUsing == SearchUsing.id)
{
cacheStatus = Storage.GetCacheStatus("PlayerPerspective", (long)searchValue);
}
else
{
cacheStatus = Storage.GetCacheStatus("PlayerPerspective", (string)searchValue);
}
// set up where clause
string WhereClause = "";
switch (searchUsing)
{
case SearchUsing.id:
WhereClause = "where id = " + searchValue;
break;
case SearchUsing.slug:
WhereClause = "where slug = " + searchValue;
break;
default:
throw new Exception("Invalid search type");
}
PlayerPerspective returnValue = new PlayerPerspective();
bool forceImageDownload = false;
switch (cacheStatus)
{
case Storage.CacheStatus.NotPresent:
returnValue = await GetObjectFromServer(WhereClause);
Storage.NewCacheValue(returnValue);
forceImageDownload = true;
break;
case Storage.CacheStatus.Expired:
returnValue = await GetObjectFromServer(WhereClause);
Storage.NewCacheValue(returnValue, true);
forceImageDownload = true;
break;
case Storage.CacheStatus.Current:
returnValue = Storage.GetCacheValue<PlayerPerspective>(returnValue, "id", (long)searchValue);
break;
default:
throw new Exception("How did you get here?");
}
return returnValue;
}
private enum SearchUsing
{
id,
slug
}
private static async Task<PlayerPerspective> GetObjectFromServer(string WhereClause)
{
// get Game_PlayerPerspectives metadata
var results = await igdb.QueryAsync<PlayerPerspective>(IGDBClient.Endpoints.PlayerPerspectives, query: fieldList + " " + WhereClause + ";");
var result = results.First();
return result;
}
}
}

View File

@@ -0,0 +1,110 @@
using System;
using gaseous_tools;
using IGDB;
using IGDB.Models;
using MySqlX.XDevAPI.Common;
using static gaseous_tools.Config.ConfigFile;
namespace gaseous_server.Classes.Metadata
{
public class Themes
{
const string fieldList = "fields checksum,created_at,name,slug,updated_at,url;";
public Themes()
{
}
private static IGDBClient igdb = new IGDBClient(
// Found in Twitch Developer portal for your app
Config.IGDB.ClientId,
Config.IGDB.Secret
);
public static Theme? GetGame_Themes(long? Id)
{
if ((Id == 0) || (Id == null))
{
return null;
}
else
{
Task<Theme> RetVal = _GetGame_Themes(SearchUsing.id, Id);
return RetVal.Result;
}
}
public static Theme GetGame_Themes(string Slug)
{
Task<Theme> RetVal = _GetGame_Themes(SearchUsing.slug, Slug);
return RetVal.Result;
}
private static async Task<Theme> _GetGame_Themes(SearchUsing searchUsing, object searchValue)
{
// check database first
Storage.CacheStatus? cacheStatus = new Storage.CacheStatus();
if (searchUsing == SearchUsing.id)
{
cacheStatus = Storage.GetCacheStatus("Theme", (long)searchValue);
}
else
{
cacheStatus = Storage.GetCacheStatus("Theme", (string)searchValue);
}
// set up where clause
string WhereClause = "";
switch (searchUsing)
{
case SearchUsing.id:
WhereClause = "where id = " + searchValue;
break;
case SearchUsing.slug:
WhereClause = "where slug = " + searchValue;
break;
default:
throw new Exception("Invalid search type");
}
Theme returnValue = new Theme();
bool forceImageDownload = false;
switch (cacheStatus)
{
case Storage.CacheStatus.NotPresent:
returnValue = await GetObjectFromServer(WhereClause);
Storage.NewCacheValue(returnValue);
forceImageDownload = true;
break;
case Storage.CacheStatus.Expired:
returnValue = await GetObjectFromServer(WhereClause);
Storage.NewCacheValue(returnValue, true);
forceImageDownload = true;
break;
case Storage.CacheStatus.Current:
returnValue = Storage.GetCacheValue<Theme>(returnValue, "id", (long)searchValue);
break;
default:
throw new Exception("How did you get here?");
}
return returnValue;
}
private enum SearchUsing
{
id,
slug
}
private static async Task<Theme> GetObjectFromServer(string WhereClause)
{
// get Game_Themes metadata
var results = await igdb.QueryAsync<Theme>(IGDBClient.Endpoints.Themes, query: fieldList + " " + WhereClause + ";");
var result = results.First();
return result;
}
}
}

View File

@@ -45,6 +45,39 @@ namespace gaseous_server.Controllers
}
FilterSet.Add("genres", genres);
// game modes
List<GameMode> gameModes = new List<GameMode>();
sql = "SELECT DISTINCT t1.Id, t1.`Name` FROM GameMode AS t1 JOIN (SELECT * FROM Game WHERE (SELECT COUNT(Id) FROM Games_Roms WHERE GameId = Game.Id) > 0) AS t2 ON JSON_CONTAINS(t2.GameModes, CAST(t1.Id AS char), '$') ORDER BY t1.Id";
dbResponse = db.ExecuteCMD(sql);
foreach (DataRow dr in dbResponse.Rows)
{
gameModes.Add(Classes.Metadata.GameModes.GetGame_Modes((long)dr["id"]));
}
FilterSet.Add("gamemodes", gameModes);
// player perspectives
List<PlayerPerspective> playerPerspectives = new List<PlayerPerspective>();
sql = "SELECT DISTINCT t1.Id, t1.`Name` FROM PlayerPerspective AS t1 JOIN (SELECT * FROM Game WHERE (SELECT COUNT(Id) FROM Games_Roms WHERE GameId = Game.Id) > 0) AS t2 ON JSON_CONTAINS(t2.PlayerPerspectives, CAST(t1.Id AS char), '$') ORDER BY t1.`Name`";
dbResponse = db.ExecuteCMD(sql);
foreach (DataRow dr in dbResponse.Rows)
{
playerPerspectives.Add(Classes.Metadata.PlayerPerspectives.GetGame_PlayerPerspectives((long)dr["id"]));
}
FilterSet.Add("playerperspectives", playerPerspectives);
// themes
List<Theme> themes = new List<Theme>();
sql = "SELECT DISTINCT t1.Id, t1.`Name` FROM Theme AS t1 JOIN (SELECT * FROM Game WHERE (SELECT COUNT(Id) FROM Games_Roms WHERE GameId = Game.Id) > 0) AS t2 ON JSON_CONTAINS(t2.Themes, CAST(t1.Id AS char), '$') ORDER BY t1.`Name`";
dbResponse = db.ExecuteCMD(sql);
foreach (DataRow dr in dbResponse.Rows)
{
themes.Add(Classes.Metadata.Themes.GetGame_Themes((long)dr["id"]));
}
FilterSet.Add("themes", themes);
return FilterSet;
}
}

View File

@@ -23,7 +23,16 @@ namespace gaseous_server.Controllers
{
[HttpGet]
[ProducesResponseType(typeof(List<Game>), StatusCodes.Status200OK)]
public ActionResult Game(string name = "", string platform = "", string genre = "", bool sortdescending = false)
public ActionResult Game(
string name = "",
string platform = "",
string genre = "",
string gamemode = "",
string playerperspective = "",
string theme = "",
int minrating = -1,
int maxrating = -1,
bool sortdescending = false)
{
string whereClause = "";
string havingClause = "";
@@ -41,6 +50,20 @@ namespace gaseous_server.Controllers
havingClauses.Add(tempVal);
}
if (minrating != -1)
{
string ratingTempMinVal = "totalRating >= @totalMinRating";
whereParams.Add("@totalMinRating", minrating);
havingClauses.Add(ratingTempMinVal);
}
if (maxrating != -1)
{
string ratingTempMaxVal = "totalRating <= @totalMaxRating";
whereParams.Add("@totalMaxRating", maxrating);
havingClauses.Add(ratingTempMaxVal);
}
if (platform.Length > 0)
{
tempVal = "Games_Roms.PlatformId IN (";
@@ -77,6 +100,60 @@ namespace gaseous_server.Controllers
whereClauses.Add(tempVal);
}
if (gamemode.Length > 0)
{
tempVal = "(";
string[] gameModeClauseItems = gamemode.Split(",");
for (int i = 0; i < gameModeClauseItems.Length; i++)
{
if (i > 0)
{
tempVal += " AND ";
}
string gameModeLabel = "@GameMode" + i;
tempVal += "JSON_CONTAINS(Game.GameModes, " + gameModeLabel + ", '$')";
whereParams.Add(gameModeLabel, gameModeClauseItems[i]);
}
tempVal += ")";
whereClauses.Add(tempVal);
}
if (playerperspective.Length > 0)
{
tempVal = "(";
string[] playerPerspectiveClauseItems = playerperspective.Split(",");
for (int i = 0; i < playerPerspectiveClauseItems.Length; i++)
{
if (i > 0)
{
tempVal += " AND ";
}
string playerPerspectiveLabel = "@PlayerPerspective" + i;
tempVal += "JSON_CONTAINS(Game.PlayerPerspectives, " + playerPerspectiveLabel + ", '$')";
whereParams.Add(playerPerspectiveLabel, playerPerspectiveClauseItems[i]);
}
tempVal += ")";
whereClauses.Add(tempVal);
}
if (theme.Length > 0)
{
tempVal = "(";
string[] themeClauseItems = theme.Split(",");
for (int i = 0; i < themeClauseItems.Length; i++)
{
if (i > 0)
{
tempVal += " AND ";
}
string themeLabel = "@Theme" + i;
tempVal += "JSON_CONTAINS(Game.Themes, " + themeLabel + ", '$')";
whereParams.Add(themeLabel, themeClauseItems[i]);
}
tempVal += ")";
whereClauses.Add(tempVal);
}
// build where clause
if (whereClauses.Count > 0)
{

View File

@@ -4,11 +4,17 @@
<div id="gamepage">
<div id="gametitle">
<div id="gametitle_criticrating">
<span id="gametitle_criticrating_value"></span>
<span id="gametitle_criticrating_label"></span>
</div>
<h1 id="gametitle_label"></h1>
<p id="gamedeveloper_label"></p>
<p id="gametitle_alts">
<span>Also known as: </span><span id="gametitle_alts_label"></span>
</p>
<p id="gamedeveloper_label"></p>
</div>
@@ -78,6 +84,17 @@
var gameTitleLabel = document.getElementById('gametitle_label');
gameTitleLabel.innerHTML = result.name;
// get critic rating
if (gameData.totalRating) {
var criticscoreval = document.getElementById('gametitle_criticrating_value');
criticscoreval.innerHTML = Math.floor(gameData.totalRating) + '%';
if (gameData.totalRatingCount) {
var criticscorelabel = document.getElementById('gametitle_criticrating_label');
criticscorelabel.innerHTML = "based on <br />" + gameData.totalRatingCount + " votes"
}
}
// get alt name
var gameTitleAltLabel = document.getElementById('gametitle_alts');
if (result.alternativeNames) {

View File

@@ -7,10 +7,12 @@
ajaxCall('/api/v1/Filter', 'GET', function (result) {
var filterElement = document.getElementById('games_filter');
formatFilterPanel(filterElement, result);
executeFilter();
});
ajaxCall('/api/v1/Games', 'GET', function (result) {
var gameElement = document.getElementById('games_library');
formatGamesPanel(gameElement, result);
});
//ajaxCall('/api/v1/Games', 'GET', function (result) {
// var gameElement = document.getElementById('games_library');
// formatGamesPanel(gameElement, result);
//});
</script>

View File

@@ -15,44 +15,111 @@
panel.appendChild(containerPanelSearch);
panel.appendChild(buildFilterPanelHeader('userrating', 'User Rating'));
var containerPanelUserRating = document.createElement('div');
containerPanelUserRating.className = 'filter_panel_box';
var containerPanelUserRatingMinField = document.createElement('input');
containerPanelUserRatingMinField.id = 'filter_panel_userrating_min';
containerPanelUserRatingMinField.type = 'number';
containerPanelUserRatingMinField.placeholder = '0';
containerPanelUserRatingMinField.setAttribute('onchange', 'executeFilterDelayed();');
containerPanelUserRatingMinField.setAttribute('onkeydown', 'executeFilterDelayed();');
containerPanelUserRatingMinField.setAttribute('min', '0');
containerPanelUserRatingMinField.setAttribute('max', '100');
containerPanelUserRating.appendChild(containerPanelUserRatingMinField);
var containerPanelUserRatingMaxField = document.createElement('input');
containerPanelUserRatingMaxField.id = 'filter_panel_userrating_max';
containerPanelUserRatingMaxField.type = 'number';
containerPanelUserRatingMaxField.placeholder = '100';
containerPanelUserRatingMaxField.setAttribute('onchange', 'executeFilterDelayed();');
containerPanelUserRatingMaxField.setAttribute('onkeydown', 'executeFilterDelayed();');
containerPanelUserRatingMaxField.setAttribute('min', '0');
containerPanelUserRatingMaxField.setAttribute('max', '100');
containerPanelUserRating.appendChild(containerPanelUserRatingMaxField);
panel.appendChild(containerPanelUserRating);
if (result.platforms) {
panel.appendChild(buildFilterPanelHeader('platforms', 'Platforms'));
var containerPanelPlatform = document.createElement('div');
containerPanelPlatform.className = 'filter_panel_box';
for (var i = 0; i < result.platforms.length; i++) {
containerPanelPlatform.appendChild(buildFilterPanelItem('platforms', result.platforms[i].id, result.platforms[i].name));
}
panel.appendChild(containerPanelPlatform);
targetElement.appendChild(panel);
buildFilterPanel(panel, 'platform', 'Platforms', result.platforms, true, true);
}
if (result.genres) {
panel.appendChild(buildFilterPanelHeader('genres', 'Genres'));
var containerPanelGenres = document.createElement('div');
containerPanelGenres.className = 'filter_panel_box';
for (var i = 0; i < result.genres.length; i++) {
containerPanelGenres.appendChild(buildFilterPanelItem('genres', result.genres[i].id, result.genres[i].name));
}
panel.appendChild(containerPanelGenres);
targetElement.appendChild(panel);
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);
}
if (result.themes) {
buildFilterPanel(panel, 'theme', 'Themes', result.themes, true, false);
}
targetElement.appendChild(panel);
}
function buildFilterPanelHeader(headerString, friendlyHeaderString) {
function buildFilterPanel(targetElement, headerString, friendlyHeaderString, valueList, showToggle, initialDisplay) {
if (showToggle == false) { initialDisplay = true; }
targetElement.appendChild(buildFilterPanelHeader(headerString, friendlyHeaderString, showToggle, initialDisplay));
var containerPanel = document.createElement('div');
containerPanel.className = 'filter_panel_box';
containerPanel.id = 'filter_panel_box_' + headerString;
if (initialDisplay == false) {
containerPanel.setAttribute('style', 'display: none;');
}
for (var i = 0; i < valueList.length; i++) {
containerPanel.appendChild(buildFilterPanelItem(headerString, valueList[i].id, valueList[i].name));
}
targetElement.appendChild(containerPanel);
}
function buildFilterPanelHeader(headerString, friendlyHeaderString, showVisibleToggle, toggleInitialValue) {
var headerToggle = document.createElement('div');
headerToggle.setAttribute('style', 'float: right;');
headerToggle.id = 'filter_panel_header_toggle_' + headerString;
if (toggleInitialValue == true) {
headerToggle.innerHTML = '-';
} else {
headerToggle.innerHTML = '+';
}
var headerLabel = document.createElement('span');
headerLabel.innerHTML = friendlyHeaderString;
var header = document.createElement('div');
header.id = 'filter_panel_header_' + headerString;
header.className = 'filter_header';
header.innerHTML = friendlyHeaderString;
if (showVisibleToggle == true) {
header.appendChild(headerToggle);
header.setAttribute('onclick', 'toggleFilterPanel("' + headerString + '");');
header.style.cursor = 'pointer';
}
header.appendChild(headerLabel);
return header;
}
function toggleFilterPanel(panelName) {
var filterPanel = document.getElementById('filter_panel_box_' + panelName);
var filterPanelToggle = document.getElementById('filter_panel_header_toggle_' + panelName);
if (filterPanel.style.display == 'none') {
filterPanelToggle.innerHTML = '-';
filterPanel.style.display = '';
} else {
filterPanelToggle.innerHTML = '+';
filterPanel.style.display = 'none';
}
}
function buildFilterPanelItem(filterType, itemString, friendlyItemString) {
var filterPanelItem = document.createElement('div');
filterPanelItem.id = 'filter_panel_item_' + itemString;
@@ -61,7 +128,7 @@ function buildFilterPanelItem(filterType, itemString, friendlyItemString) {
var filterPanelItemCheckBox = document.createElement('div');
var filterPanelItemCheckBoxItem = document.createElement('input');
filterPanelItemCheckBoxItem.id = 'filter_panel_item_checkbox_' + itemString;
filterPanelItemCheckBoxItem.id = 'filter_panel_item_' + filterType + '_checkbox_' + itemString;
filterPanelItemCheckBoxItem.type = 'checkbox';
filterPanelItemCheckBoxItem.className = 'filter_panel_item_checkbox';
filterPanelItemCheckBoxItem.name = 'filter_' + filterType;
@@ -92,33 +159,73 @@ function executeFilterDelayed() {
function executeFilter() {
// build filter lists
var queries = [];
var platforms = '';
var genres = '';
var searchString = document.getElementById('filter_panel_search').value;
var platformFilters = document.getElementsByName('filter_platforms');
var genreFilters = document.getElementsByName('filter_genres');
if (searchString.length > 0) {
queries.push('name=' + searchString);
}
for (var i = 0; i < platformFilters.length; i++) {
if (platformFilters[i].checked) {
if (platforms.length > 0) {
platforms += ',';
var minUserRating = 0;
var minUserRatingInput = document.getElementById('filter_panel_userrating_min').value;
if (minUserRatingInput) {
minUserRating = minUserRatingInput;
queries.push('minrating=' + minUserRating);
}
var maxUserRating = 100;
var maxUserRatingInput = document.getElementById('filter_panel_userrating_max').value;
if (maxUserRatingInput) {
maxUserRating = maxUserRatingInput;
queries.push('maxrating=' + maxUserRating);
}
queries.push(GetFilterQuery('platform'));
queries.push(GetFilterQuery('genre'));
queries.push(GetFilterQuery('gamemode'));
queries.push(GetFilterQuery('playerperspective'));
queries.push(GetFilterQuery('theme'));
var queryString = '';
for (var i = 0; i < queries.length; i++) {
if (queries[i].length > 0) {
if (queryString.length == 0) {
queryString = '?';
} else {
queryString += '&';
}
platforms += platformFilters[i].getAttribute('filter_id');
queryString += queries[i];
}
}
for (var i = 0; i < genreFilters.length; i++) {
if (genreFilters[i].checked) {
if (genres.length > 0) {
genres += ',';
}
genres += genreFilters[i].getAttribute('filter_id');
}
}
console.log('Query string = ' + queryString);
ajaxCall('/api/v1/Games?name=' + searchString + '&platform=' + platforms + '&genre=' + genres, 'GET', function (result) {
ajaxCall('/api/v1/Games' + queryString, 'GET', function (result) {
var gameElement = document.getElementById('games_library');
formatGamesPanel(gameElement, result);
});
}
function GetFilterQuery(filterName) {
var Filters = document.getElementsByName('filter_' + filterName);
var queryString = '';
for (var i = 0; i < Filters.length; i++) {
if (Filters[i].checked) {
if (queryString.length > 0) {
queryString += ',';
}
queryString += Filters[i].getAttribute('filter_id');
}
}
if (queryString.length > 0) {
queryString = filterName + '=' + queryString;
}
return queryString;
}

View File

@@ -13,6 +13,10 @@
src: url('/fonts/Commodore Pixelized v1.2.ttf');
}
h1 {
margin-bottom: unset;
}
h3 {
border-bottom-style: solid;
/*border-bottom-color: #916b01;*/
@@ -206,7 +210,7 @@ h3 {
padding: 10px;
}
input[type='text'] {
input[type='text'], input[type='number'] {
background-color: #2b2b2b;
color: white;
padding: 5px;
@@ -225,6 +229,15 @@ input[id='filter_panel_search'] {
width: 160px;
}
input[id='filter_panel_userrating_min'] {
width: 50px;
margin-right: 5px;
}
input[id='filter_panel_userrating_max'] {
width: 50px;
}
/* width */
::-webkit-scrollbar {
width: 10px;
@@ -286,12 +299,20 @@ input[id='filter_panel_search'] {
text-align: center;
vertical-align: top;
margin-bottom: 10px;
border-radius: 10px 10px 10px 10px;
-webkit-border-radius: 10px 10px 10px 10px;
-moz-border-radius: 10px 10px 10px 10px;
border: 1px solid transparent;
}
.game_tile:hover {
cursor: pointer;
text-decoration: underline;
background-color: #2b2b2b;
border-radius: 10px 10px 10px 10px;
-webkit-border-radius: 10px 10px 10px 10px;
-moz-border-radius: 10px 10px 10px 10px;
border: 1px solid #2b2b2b;
}
.game_tile_image {
@@ -770,4 +791,25 @@ button:disabled {
box-shadow: 5px 5px 19px 0px rgba(0,0,0,0.44);
-webkit-box-shadow: 5px 5px 19px 0px rgba(0,0,0,0.44);
-moz-box-shadow: 5px 5px 19px 0px rgba(0,0,0,0.44);
}
#gametitle_criticrating {
float: right;
}
#gametitle_alts {
margin-top: -2px;
}
#gametitle_criticrating_value {
display: inline-block;
font-family: Commodore64;
font-size: 36px;
text-align: center;
margin-right: 2px;
}
#gametitle_criticrating_label {
display: inline-block;
text-align: left;
}

View File

@@ -0,0 +1,65 @@
DROP TABLE IF EXISTS `GameMode`;
CREATE TABLE `gaseous`.`GameMode` (
`Id` BIGINT NOT NULL,
`CreatedAt` DATETIME NULL,
`Checksum` VARCHAR(45) NULL,
`Name` VARCHAR(100) NULL,
`Slug` VARCHAR(100) NULL,
`UpdatedAt` DATETIME NULL,
`Url` VARCHAR(255) NULL,
`dateAdded` DATETIME NULL,
`lastUpdated` DATETIME NULL,
PRIMARY KEY (`Id`)
);
DROP TABLE IF EXISTS `MultiplayerMode`;
CREATE TABLE `MultiplayerMode` (
`Id` bigint NOT NULL,
`CreatedAt` datetime DEFAULT NULL,
`Checksum` varchar(45) DEFAULT NULL,
`CampaignCoop` boolean DEFAULT NULL,
`DropIn` boolean DEFAULT NULL,
`Game` bigint DEFAULT NULL,
`LanCoop` boolean DEFAULT NULL,
`OfflineCoop` boolean DEFAULT NULL,
`OfflineCoopMax` int DEFAULT NULL,
`OfflineMax` int DEFAULT NULL,
`OnlineCoop` boolean DEFAULT NULL,
`OnlineCoopMax` int DEFAULT NULL,
`OnlineMax` int DEFAULT NULL,
`Platform` bigint DEFAULT NULL,
`SplitScreen` boolean DEFAULT NULL,
`SplitScreenOnline` boolean DEFAULT NULL,
`UpdatedAt` datetime DEFAULT NULL,
`dateAdded` datetime DEFAULT NULL,
`lastUpdated` datetime DEFAULT NULL,
PRIMARY KEY (`Id`)
);
DROP TABLE IF EXISTS `PlayerPerspective`;
CREATE TABLE `PlayerPerspective` (
`Id` bigint NOT NULL,
`CreatedAt` datetime DEFAULT NULL,
`Checksum` varchar(45) DEFAULT NULL,
`Name` varchar(100) DEFAULT NULL,
`Slug` varchar(45) DEFAULT NULL,
`UpdatedAt` datetime DEFAULT NULL,
`Url` varchar(255) DEFAULT NULL,
`dateAdded` datetime DEFAULT NULL,
`lastUpdated` datetime DEFAULT NULL,
PRIMARY KEY (`Id`)
);
DROP TABLE IF EXISTS `Theme`;
CREATE TABLE `Theme` (
`Id` bigint NOT NULL,
`CreatedAt` datetime DEFAULT NULL,
`Checksum` varchar(45) DEFAULT NULL,
`Name` varchar(100) DEFAULT NULL,
`Slug` varchar(45) DEFAULT NULL,
`UpdatedAt` datetime DEFAULT NULL,
`Url` varchar(255) DEFAULT NULL,
`dateAdded` datetime DEFAULT NULL,
`lastUpdated` datetime DEFAULT NULL,
PRIMARY KEY (`Id`)
);

View File

@@ -16,6 +16,7 @@
<None Remove="Database\" />
<None Remove="Database\MySQL\" />
<None Remove="Database\MySQL\gaseous-1000.sql" />
<None Remove="Database\MySQL\gaseous-1001.sql" />
</ItemGroup>
<ItemGroup>
<Folder Include="Database\" />
@@ -23,5 +24,6 @@
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="Database\MySQL\gaseous-1000.sql" />
<EmbeddedResource Include="Database\MySQL\gaseous-1001.sql" />
</ItemGroup>
</Project>