Library filtering and display enhancements (#214)
* Implement infinite scrolling and paging (selected via preference) (closes #202) * Display game counts on more filter types (closes #194) * Make game counts larger (closes #194) * Include age groups in filtering (closes #200) * Add sorting options (closes #145)
This commit is contained in:
@@ -11,5 +11,6 @@ namespace Authentication
|
||||
public class ApplicationUser : IdentityUser
|
||||
{
|
||||
public SecurityProfileViewModel SecurityProfile { get; set; }
|
||||
public List<UserPreferenceViewModel> UserPreferences { get; set; }
|
||||
}
|
||||
}
|
||||
|
@@ -99,6 +99,7 @@ namespace Authentication
|
||||
user.AccessFailedCount = string.IsNullOrEmpty((string?)row["AccessFailedCount"]) ? 0 : int.Parse((string?)row["AccessFailedCount"]);
|
||||
user.TwoFactorEnabled = row["TwoFactorEnabled"] == "1" ? true:false;
|
||||
user.SecurityProfile = GetSecurityProfile(user);
|
||||
user.UserPreferences = GetPreferences(user);
|
||||
}
|
||||
|
||||
return user;
|
||||
@@ -135,6 +136,7 @@ namespace Authentication
|
||||
user.AccessFailedCount = string.IsNullOrEmpty((string?)row["AccessFailedCount"]) ? 0 : int.Parse((string?)row["AccessFailedCount"]);
|
||||
user.TwoFactorEnabled = row["TwoFactorEnabled"] == "1" ? true:false;
|
||||
user.SecurityProfile = GetSecurityProfile(user);
|
||||
user.UserPreferences = GetPreferences(user);
|
||||
users.Add(user);
|
||||
}
|
||||
|
||||
@@ -166,6 +168,7 @@ namespace Authentication
|
||||
user.AccessFailedCount = string.IsNullOrEmpty((string?)row["AccessFailedCount"]) ? 0 : int.Parse((string?)row["AccessFailedCount"]);
|
||||
user.TwoFactorEnabled = row["TwoFactorEnabled"] == "1" ? true:false;
|
||||
user.SecurityProfile = GetSecurityProfile(user);
|
||||
user.UserPreferences = GetPreferences(user);
|
||||
users.Add(user);
|
||||
}
|
||||
|
||||
@@ -273,6 +276,9 @@ namespace Authentication
|
||||
// set default security profile
|
||||
SetSecurityProfile(user, new SecurityProfileViewModel());
|
||||
|
||||
// set default preferences
|
||||
SetPreferences(user, new List<UserPreferenceViewModel>());
|
||||
|
||||
return _database.ExecuteCMD(commandText, parameters).Rows.Count;
|
||||
}
|
||||
|
||||
@@ -283,7 +289,7 @@ namespace Authentication
|
||||
/// <returns></returns>
|
||||
private int Delete(string userId)
|
||||
{
|
||||
string commandText = "Delete from Users where Id = @userId";
|
||||
string commandText = "Delete from Users where Id = @userId; Delete from User_Settings where Id = @userId;";
|
||||
Dictionary<string, object> parameters = new Dictionary<string, object>();
|
||||
parameters.Add("@userId", userId);
|
||||
|
||||
@@ -328,6 +334,9 @@ namespace Authentication
|
||||
// set the security profile
|
||||
SetSecurityProfile(user, user.SecurityProfile);
|
||||
|
||||
// set preferences
|
||||
SetPreferences(user, user.UserPreferences);
|
||||
|
||||
return _database.ExecuteCMD(commandText, parameters).Rows.Count;
|
||||
}
|
||||
|
||||
@@ -367,5 +376,59 @@ namespace Authentication
|
||||
|
||||
return _database.ExecuteCMD(commandText, parameters).Rows.Count;
|
||||
}
|
||||
|
||||
public List<UserPreferenceViewModel> GetPreferences(TUser user)
|
||||
{
|
||||
Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
||||
string sql = "SELECT `Setting`, `Value` FROM User_Settings WHERE Id=@id;";
|
||||
Dictionary<string, object> dbDict = new Dictionary<string, object>();
|
||||
dbDict.Add("id", user.Id);
|
||||
|
||||
DataTable data = db.ExecuteCMD(sql, dbDict);
|
||||
|
||||
List<UserPreferenceViewModel> userPrefs = new List<UserPreferenceViewModel>();
|
||||
foreach (DataRow row in data.Rows)
|
||||
{
|
||||
UserPreferenceViewModel userPref = new UserPreferenceViewModel();
|
||||
userPref.Setting = (string)row["Setting"];
|
||||
userPref.Value = (string)row["Value"];
|
||||
userPrefs.Add(userPref);
|
||||
}
|
||||
|
||||
return userPrefs;
|
||||
}
|
||||
|
||||
public int SetPreferences(TUser user, List<UserPreferenceViewModel> model)
|
||||
{
|
||||
List<UserPreferenceViewModel> userPreferences = GetPreferences(user);
|
||||
|
||||
Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
||||
|
||||
foreach (UserPreferenceViewModel modelItem in model)
|
||||
{
|
||||
bool prefItemFound = false;
|
||||
foreach (UserPreferenceViewModel existing in userPreferences)
|
||||
{
|
||||
if (existing.Setting.ToLower() == modelItem.Setting.ToLower())
|
||||
{
|
||||
prefItemFound = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
string sql = "INSERT INTO User_Settings (`Id`, `Setting`, `Value`) VALUES (@id, @setting, @value);";
|
||||
if (prefItemFound == true)
|
||||
{
|
||||
sql = "UPDATE User_Settings SET `Value`=@value WHERE `Id`=@id AND `Setting`=@setting";
|
||||
}
|
||||
Dictionary<string, object> dbDict = new Dictionary<string, object>();
|
||||
dbDict.Add("id", user.Id);
|
||||
dbDict.Add("setting", modelItem.Setting);
|
||||
dbDict.Add("value", modelItem.Value);
|
||||
db.ExecuteNonQuery(sql, dbDict);
|
||||
}
|
||||
|
||||
return model.Count;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -7,6 +7,7 @@ namespace Authentication
|
||||
public string EmailAddress { get; set; }
|
||||
public List<String> Roles { get; set; }
|
||||
public SecurityProfileViewModel SecurityProfile { get; set; }
|
||||
public List<UserPreferenceViewModel> UserPreferences { get; set; }
|
||||
public string HighestRole {
|
||||
get
|
||||
{
|
||||
|
@@ -5,13 +5,13 @@ namespace Authentication
|
||||
public class SecurityProfileViewModel
|
||||
{
|
||||
public AgeRestrictionItem AgeRestrictionPolicy { get; set; } = new AgeRestrictionItem{
|
||||
MaximumAgeRestriction = "Adult",
|
||||
MaximumAgeRestriction = gaseous_server.Classes.Metadata.AgeRatings.AgeGroups.AgeRestrictionGroupings.Adult,
|
||||
IncludeUnrated = true
|
||||
};
|
||||
|
||||
public class AgeRestrictionItem
|
||||
{
|
||||
public string MaximumAgeRestriction { get; set; }
|
||||
public gaseous_server.Classes.Metadata.AgeRatings.AgeGroups.AgeRestrictionGroupings MaximumAgeRestriction { get; set; }
|
||||
public bool IncludeUnrated { get; set; }
|
||||
}
|
||||
}
|
||||
|
@@ -0,0 +1,8 @@
|
||||
namespace Authentication;
|
||||
|
||||
public class UserPreferenceViewModel
|
||||
{
|
||||
public string Setting { get; set; }
|
||||
|
||||
public string Value { get; set; }
|
||||
}
|
@@ -4,19 +4,27 @@ using System.IO.Compression;
|
||||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Security.Cryptography;
|
||||
using Authentication;
|
||||
using gaseous_server.Classes.Metadata;
|
||||
using gaseous_server.Controllers;
|
||||
using gaseous_server.Models;
|
||||
using IGDB.Models;
|
||||
using Microsoft.AspNetCore.Identity;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace gaseous_server.Classes
|
||||
{
|
||||
public class Collections
|
||||
{
|
||||
public Collections()
|
||||
{
|
||||
private readonly UserManager<ApplicationUser> _userManager;
|
||||
private readonly SignInManager<ApplicationUser> _signInManager;
|
||||
|
||||
public Collections(
|
||||
UserManager<ApplicationUser> userManager,
|
||||
SignInManager<ApplicationUser> signInManager)
|
||||
{
|
||||
_userManager = userManager;
|
||||
_signInManager = signInManager;
|
||||
}
|
||||
|
||||
public static List<CollectionItem> GetCollections() {
|
||||
@@ -211,8 +219,8 @@ namespace gaseous_server.Classes
|
||||
}
|
||||
} else {
|
||||
// get all platforms to pull from
|
||||
FilterController filterController = new FilterController();
|
||||
platforms.AddRange((List<FilterController.FilterPlatform>)filterController.Filter()["platforms"]);
|
||||
Dictionary<string, object> FilterDict = Filters.Filter(AgeRatings.AgeGroups.AgeRestrictionGroupings.Adult, true);
|
||||
platforms.AddRange((List<Filters.FilterPlatform>)FilterDict["platforms"]);
|
||||
}
|
||||
|
||||
// build collection
|
||||
|
225
gaseous-server/Classes/Filters.cs
Normal file
225
gaseous-server/Classes/Filters.cs
Normal file
@@ -0,0 +1,225 @@
|
||||
using System.Data;
|
||||
using System.Reflection.Metadata.Ecma335;
|
||||
using gaseous_server.Classes.Metadata;
|
||||
using IGDB.Models;
|
||||
|
||||
namespace gaseous_server.Classes
|
||||
{
|
||||
public class Filters
|
||||
{
|
||||
public static Dictionary<string, object> Filter(Metadata.AgeRatings.AgeGroups.AgeRestrictionGroupings MaximumAgeRestriction, bool IncludeUnrated)
|
||||
{
|
||||
Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
||||
|
||||
Dictionary<string, object> FilterSet = new Dictionary<string, object>();
|
||||
|
||||
// platforms
|
||||
List<FilterPlatform> platforms = new List<FilterPlatform>();
|
||||
|
||||
string ageRestriction_Platform = "Game.AgeGroupId <= " + (int)MaximumAgeRestriction;
|
||||
string ageRestriction_Generic = "view_Games.AgeGroupId <= " + (int)MaximumAgeRestriction;
|
||||
if (IncludeUnrated == true)
|
||||
{
|
||||
ageRestriction_Platform += " OR Game.AgeGroupId IS NULL";
|
||||
ageRestriction_Generic += " OR view_Games.AgeGroupId IS NULL";
|
||||
}
|
||||
|
||||
string sql = "SELECT DISTINCT Platform.Id, Platform.Abbreviation, Platform.AlternativeName, Platform.`Name`, Platform.PlatformLogo, (SELECT COUNT(*) AS GameCount FROM (SELECT DISTINCT Games_Roms.GameId AS ROMGameId, Games_Roms.PlatformId, view_Games.AgeGroupId FROM Games_Roms LEFT JOIN view_Games ON view_Games.Id = Games_Roms.GameId) Game WHERE Game.PlatformId = Platform.Id AND (" + ageRestriction_Platform + ")) AS GameCount FROM Platform LEFT JOIN Relation_Game_Platforms ON Relation_Game_Platforms.PlatformsId = Platform.Id LEFT JOIN view_Games ON view_Games.Id = Relation_Game_Platforms.GameId HAVING GameCount > 0 ORDER BY Platform.`Name`;";
|
||||
|
||||
DataTable dbResponse = db.ExecuteCMD(sql);
|
||||
|
||||
foreach (DataRow dr in dbResponse.Rows)
|
||||
{
|
||||
FilterPlatform platformItem = new FilterPlatform(Classes.Metadata.Platforms.GetPlatform((long)dr["id"]));
|
||||
platformItem.GameCount = (int)(long)dr["GameCount"];
|
||||
platforms.Add(platformItem);
|
||||
|
||||
}
|
||||
FilterSet.Add("platforms", platforms);
|
||||
|
||||
// genres
|
||||
List<FilterGenre> genres = new List<FilterGenre>();
|
||||
dbResponse = GetGenericFilterItem(db, "Genre", ageRestriction_Generic);
|
||||
|
||||
foreach (DataRow dr in dbResponse.Rows)
|
||||
{
|
||||
FilterGenre genreItem = new FilterGenre(Classes.Metadata.Genres.GetGenres((long)dr["id"]));
|
||||
genreItem.GameCount = (int)(long)dr["GameCount"];
|
||||
genres.Add(genreItem);
|
||||
}
|
||||
FilterSet.Add("genres", genres);
|
||||
|
||||
// game modes
|
||||
List<FilterGameMode> gameModes = new List<FilterGameMode>();
|
||||
dbResponse = GetGenericFilterItem(db, "GameMode", ageRestriction_Generic);
|
||||
|
||||
foreach (DataRow dr in dbResponse.Rows)
|
||||
{
|
||||
FilterGameMode gameModeItem = new FilterGameMode(Classes.Metadata.GameModes.GetGame_Modes((long)dr["id"]));
|
||||
gameModeItem.GameCount = (int)(long)dr["GameCount"];
|
||||
gameModes.Add(gameModeItem);
|
||||
}
|
||||
FilterSet.Add("gamemodes", gameModes);
|
||||
|
||||
// player perspectives
|
||||
List<FilterPlayerPerspective> playerPerspectives = new List<FilterPlayerPerspective>();
|
||||
dbResponse = GetGenericFilterItem(db, "PlayerPerspective", ageRestriction_Generic);
|
||||
|
||||
foreach (DataRow dr in dbResponse.Rows)
|
||||
{
|
||||
FilterPlayerPerspective playerPerspectiveItem = new FilterPlayerPerspective(Classes.Metadata.PlayerPerspectives.GetGame_PlayerPerspectives((long)dr["id"]));
|
||||
playerPerspectiveItem.GameCount = (int)(long)dr["GameCount"];
|
||||
playerPerspectives.Add(playerPerspectiveItem);
|
||||
}
|
||||
FilterSet.Add("playerperspectives", playerPerspectives);
|
||||
|
||||
// themes
|
||||
List<FilterTheme> themes = new List<FilterTheme>();
|
||||
dbResponse = GetGenericFilterItem(db, "Theme", ageRestriction_Generic);
|
||||
|
||||
foreach (DataRow dr in dbResponse.Rows)
|
||||
{
|
||||
FilterTheme themeItem = new FilterTheme(Classes.Metadata.Themes.GetGame_Themes((long)dr["id"]));
|
||||
themeItem.GameCount = (int)(long)dr["GameCount"];
|
||||
themes.Add(themeItem);
|
||||
}
|
||||
FilterSet.Add("themes", themes);
|
||||
|
||||
// age groups
|
||||
List<FilterAgeGrouping> agegroupings = new List<FilterAgeGrouping>();
|
||||
sql = "SELECT view_Games.Id, view_Games.AgeGroupId, COUNT(view_Games.Id) AS GameCount FROM view_Games WHERE (" + ageRestriction_Generic + ") GROUP BY view_Games.AgeGroupId ORDER BY view_Games.AgeGroupId DESC;";
|
||||
dbResponse = db.ExecuteCMD(sql);
|
||||
|
||||
foreach (DataRow dr in dbResponse.Rows)
|
||||
{
|
||||
FilterAgeGrouping filterAgeGrouping = new FilterAgeGrouping();
|
||||
if (dr["AgeGroupId"] == DBNull.Value)
|
||||
{
|
||||
filterAgeGrouping.Id = (long)AgeRatings.AgeGroups.AgeRestrictionGroupings.Unclassified;
|
||||
filterAgeGrouping.AgeGroup = AgeRatings.AgeGroups.AgeRestrictionGroupings.Unclassified;
|
||||
}
|
||||
else
|
||||
{
|
||||
filterAgeGrouping.Id = (long)(AgeRatings.AgeGroups.AgeRestrictionGroupings)dr["AgeGroupId"];
|
||||
filterAgeGrouping.AgeGroup = (AgeRatings.AgeGroups.AgeRestrictionGroupings)dr["AgeGroupId"];
|
||||
}
|
||||
filterAgeGrouping.GameCount = (int)(long)dr["GameCount"];
|
||||
agegroupings.Add(filterAgeGrouping);
|
||||
}
|
||||
FilterSet.Add("agegroupings", agegroupings);
|
||||
|
||||
return FilterSet;
|
||||
}
|
||||
|
||||
private static DataTable GetGenericFilterItem(Database db, string Name, string AgeRestriction_Generic)
|
||||
{
|
||||
string sql = "SELECT DISTINCT <ITEMNAME>.Id, <ITEMNAME>.`Name`, COUNT(view_Games.Id) AS GameCount FROM <ITEMNAME> LEFT JOIN Relation_Game_<ITEMNAME>s ON Relation_Game_<ITEMNAME>s.<ITEMNAME>sId = <ITEMNAME>.Id LEFT JOIN view_Games ON view_Games.Id = Relation_Game_<ITEMNAME>s.GameId WHERE (" + AgeRestriction_Generic + ") GROUP BY <ITEMNAME>.Id ORDER BY <ITEMNAME>.`Name`;";
|
||||
sql = sql.Replace("<ITEMNAME>", Name);
|
||||
DataTable dbResponse = db.ExecuteCMD(sql);
|
||||
|
||||
return dbResponse;
|
||||
}
|
||||
|
||||
public class FilterPlatform : IGDB.Models.Platform
|
||||
{
|
||||
public FilterPlatform(Platform obj)
|
||||
{
|
||||
var properties = obj.GetType().GetProperties();
|
||||
foreach (var prop in properties)
|
||||
{
|
||||
if (prop.GetGetMethod() != null)
|
||||
{
|
||||
this.GetType().GetProperty(prop.Name).SetValue(this, prop.GetValue(obj));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public int GameCount { get; set; }
|
||||
}
|
||||
|
||||
public class FilterGenre : IGDB.Models.Genre
|
||||
{
|
||||
public FilterGenre(Genre obj)
|
||||
{
|
||||
var properties = obj.GetType().GetProperties();
|
||||
foreach (var prop in properties)
|
||||
{
|
||||
if (prop.GetGetMethod() != null)
|
||||
{
|
||||
this.GetType().GetProperty(prop.Name).SetValue(this, prop.GetValue(obj));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public int GameCount { get; set; }
|
||||
}
|
||||
|
||||
public class FilterGameMode : IGDB.Models.GameMode
|
||||
{
|
||||
public FilterGameMode(GameMode obj)
|
||||
{
|
||||
var properties = obj.GetType().GetProperties();
|
||||
foreach (var prop in properties)
|
||||
{
|
||||
if (prop.GetGetMethod() != null)
|
||||
{
|
||||
this.GetType().GetProperty(prop.Name).SetValue(this, prop.GetValue(obj));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public int GameCount { get; set; }
|
||||
}
|
||||
|
||||
public class FilterPlayerPerspective : IGDB.Models.PlayerPerspective
|
||||
{
|
||||
public FilterPlayerPerspective(PlayerPerspective obj)
|
||||
{
|
||||
var properties = obj.GetType().GetProperties();
|
||||
foreach (var prop in properties)
|
||||
{
|
||||
if (prop.GetGetMethod() != null)
|
||||
{
|
||||
this.GetType().GetProperty(prop.Name).SetValue(this, prop.GetValue(obj));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public int GameCount { get; set; }
|
||||
}
|
||||
|
||||
public class FilterTheme : IGDB.Models.Theme
|
||||
{
|
||||
public FilterTheme(Theme obj)
|
||||
{
|
||||
var properties = obj.GetType().GetProperties();
|
||||
foreach (var prop in properties)
|
||||
{
|
||||
if (prop.GetGetMethod() != null)
|
||||
{
|
||||
this.GetType().GetProperty(prop.Name).SetValue(this, prop.GetValue(obj));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public int GameCount { get; set; }
|
||||
}
|
||||
|
||||
public class FilterAgeGrouping
|
||||
{
|
||||
public long Id { get; set; }
|
||||
|
||||
public AgeRatings.AgeGroups.AgeRestrictionGroupings AgeGroup { get ; set; }
|
||||
|
||||
public string Name
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.AgeGroup.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
public int GameCount { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
@@ -755,11 +755,11 @@ namespace gaseous_server.Classes
|
||||
string sql = "";
|
||||
if (ForceExecute == false)
|
||||
{
|
||||
sql = "SELECT * FROM Games_Roms WHERE (PlatformId = 0 OR GameId = 0 OR MetadataSource = 0) AND (LastMatchAttemptDate IS NULL OR LastMatchAttemptDate < @lastmatchattemptdate) LIMIT 100;";
|
||||
sql = "SELECT * FROM Games_Roms WHERE ((PlatformId = 0 OR GameId = 0) AND MetadataSource = 0) AND (LastMatchAttemptDate IS NULL OR LastMatchAttemptDate < @lastmatchattemptdate) LIMIT 100;";
|
||||
}
|
||||
else
|
||||
{
|
||||
sql = "SELECT * FROM Games_Roms WHERE (PlatformId = 0 OR GameId = 0 OR MetadataSource = 0);";
|
||||
sql = "SELECT * FROM Games_Roms WHERE ((PlatformId = 0 OR GameId = 0) AND MetadataSource = 0);";
|
||||
}
|
||||
Dictionary<string, object> dbDict = new Dictionary<string, object>();
|
||||
dbDict.Add("lastmatchattemptdate", DateTime.UtcNow.AddDays(-7));
|
||||
|
@@ -3,6 +3,7 @@ using System.Reflection;
|
||||
using System.Text.Json.Serialization;
|
||||
using IGDB;
|
||||
using IGDB.Models;
|
||||
using Microsoft.CodeAnalysis.Classification;
|
||||
|
||||
namespace gaseous_server.Classes.Metadata
|
||||
{
|
||||
@@ -153,6 +154,44 @@ namespace gaseous_server.Classes.Metadata
|
||||
public string[] Descriptions { get; set; }
|
||||
}
|
||||
|
||||
public static void PopulateAgeMap()
|
||||
{
|
||||
Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
||||
string sql = "DELETE FROM ClassificationMap;";
|
||||
Dictionary<string, object> dbDict = new Dictionary<string, object>();
|
||||
db.ExecuteNonQuery(sql);
|
||||
|
||||
// loop all age groups
|
||||
foreach(KeyValuePair<AgeGroups.AgeRestrictionGroupings, AgeGroups.AgeGroupItem> ageGrouping in AgeGroups.AgeGroupingsFlat)
|
||||
{
|
||||
AgeGroups.AgeGroupItem ageGroupItem = ageGrouping.Value;
|
||||
var properties = ageGroupItem.GetType().GetProperties();
|
||||
foreach (var prop in properties)
|
||||
{
|
||||
if (prop.GetGetMethod() != null)
|
||||
{
|
||||
List<string> AgeRatingCategories = new List<string>(Enum.GetNames(typeof(AgeRatingCategory)));
|
||||
if (AgeRatingCategories.Contains(prop.Name))
|
||||
{
|
||||
AgeRatingCategory ageRatingCategory = (AgeRatingCategory)Enum.Parse(typeof(AgeRatingCategory), prop.Name);
|
||||
List<AgeRatingTitle> ageRatingTitles = (List<AgeRatingTitle>)prop.GetValue(ageGroupItem);
|
||||
|
||||
foreach (AgeRatingTitle ageRatingTitle in ageRatingTitles)
|
||||
{
|
||||
dbDict.Clear();
|
||||
dbDict.Add("AgeGroupId", ageGrouping.Key);
|
||||
dbDict.Add("ClassificationBoardId", ageRatingCategory);
|
||||
dbDict.Add("RatingId", ageRatingTitle);
|
||||
|
||||
sql = "INSERT INTO ClassificationMap (AgeGroupId, ClassificationBoardId, RatingId) VALUES (@AgeGroupId, @ClassificationBoardId, @RatingId);";
|
||||
db.ExecuteCMD(sql, dbDict);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class AgeGroups
|
||||
{
|
||||
public AgeGroups()
|
||||
@@ -160,93 +199,55 @@ namespace gaseous_server.Classes.Metadata
|
||||
|
||||
}
|
||||
|
||||
public static Dictionary<string, List<AgeGroupItem>> AgeGroupings
|
||||
public static Dictionary<AgeRestrictionGroupings, List<AgeGroupItem>> AgeGroupings
|
||||
{
|
||||
get
|
||||
{
|
||||
return new Dictionary<string, List<AgeGroupItem>>{
|
||||
return new Dictionary<AgeRestrictionGroupings, List<AgeGroupItem>>{
|
||||
{
|
||||
"Adult", new List<AgeGroupItem>{ Adult_Item, Mature_Item, Teen_Item, Child_Item }
|
||||
AgeRestrictionGroupings.Adult, new List<AgeGroupItem>{ Adult_Item, Mature_Item, Teen_Item, Child_Item }
|
||||
},
|
||||
{
|
||||
"Mature", new List<AgeGroupItem>{ Mature_Item, Teen_Item, Child_Item }
|
||||
AgeRestrictionGroupings.Mature, new List<AgeGroupItem>{ Mature_Item, Teen_Item, Child_Item }
|
||||
},
|
||||
{
|
||||
"Teen", new List<AgeGroupItem>{ Teen_Item, Child_Item }
|
||||
AgeRestrictionGroupings.Teen, new List<AgeGroupItem>{ Teen_Item, Child_Item }
|
||||
},
|
||||
{
|
||||
"Child", new List<AgeGroupItem>{ Child_Item }
|
||||
AgeRestrictionGroupings.Child, new List<AgeGroupItem>{ Child_Item }
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
public static Dictionary<string, AgeGroupItem> AgeGroupingsFlat
|
||||
public static Dictionary<AgeRestrictionGroupings, AgeGroupItem> AgeGroupingsFlat
|
||||
{
|
||||
get
|
||||
{
|
||||
return new Dictionary<string, AgeGroupItem>{
|
||||
return new Dictionary<AgeRestrictionGroupings, AgeGroupItem>{
|
||||
{
|
||||
"Adult", Adult_Item
|
||||
AgeRestrictionGroupings.Adult, Adult_Item
|
||||
},
|
||||
{
|
||||
"Mature", Mature_Item
|
||||
AgeRestrictionGroupings.Mature, Mature_Item
|
||||
},
|
||||
{
|
||||
"Teen", Teen_Item
|
||||
AgeRestrictionGroupings.Teen, Teen_Item
|
||||
},
|
||||
{
|
||||
"Child", Child_Item
|
||||
AgeRestrictionGroupings.Child, Child_Item
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
public static List<ClassificationBoardItem> ClassificationBoards
|
||||
public enum AgeRestrictionGroupings
|
||||
{
|
||||
get
|
||||
{
|
||||
ClassificationBoardItem boardItem = new ClassificationBoardItem{
|
||||
Board = AgeRatingCategory.ACB,
|
||||
Classifications = new List<AgeRatingTitle>{
|
||||
AgeRatingTitle.ACB_G, AgeRatingTitle.ACB_M, AgeRatingTitle.ACB_MA15, AgeRatingTitle.ACB_R18, AgeRatingTitle.ACB_RC
|
||||
}
|
||||
};
|
||||
|
||||
return new List<ClassificationBoardItem>{
|
||||
new ClassificationBoardItem{
|
||||
Board = AgeRatingCategory.ACB,
|
||||
Classifications = new List<AgeRatingTitle>{
|
||||
AgeRatingTitle.ACB_G,
|
||||
AgeRatingTitle.ACB_M,
|
||||
AgeRatingTitle.ACB_MA15,
|
||||
AgeRatingTitle.ACB_R18,
|
||||
AgeRatingTitle.ACB_RC
|
||||
}
|
||||
},
|
||||
new ClassificationBoardItem{
|
||||
Board = AgeRatingCategory.CERO,
|
||||
Classifications = new List<AgeRatingTitle>{
|
||||
AgeRatingTitle.CERO_A,
|
||||
AgeRatingTitle.CERO_B,
|
||||
AgeRatingTitle.CERO_C,
|
||||
AgeRatingTitle.CERO_D,
|
||||
AgeRatingTitle.CERO_Z
|
||||
}
|
||||
},
|
||||
new ClassificationBoardItem{
|
||||
Board = AgeRatingCategory.CLASS_IND,
|
||||
Classifications = new List<AgeRatingTitle>{
|
||||
AgeRatingTitle.CLASS_IND_L,
|
||||
AgeRatingTitle.CLASS_IND_Ten,
|
||||
AgeRatingTitle.CLASS_IND_Twelve,
|
||||
AgeRatingTitle.CLASS_IND_Fourteen,
|
||||
AgeRatingTitle.CLASS_IND_Sixteen,
|
||||
AgeRatingTitle.CLASS_IND_Eighteen
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
Adult = 4,
|
||||
Mature = 3,
|
||||
Teen = 2,
|
||||
Child = 1,
|
||||
Unclassified = 0
|
||||
}
|
||||
|
||||
readonly static AgeGroupItem Adult_Item = new AgeGroupItem{
|
||||
@@ -341,12 +342,6 @@ namespace gaseous_server.Classes.Metadata
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class ClassificationBoardItem
|
||||
{
|
||||
public IGDB.Models.AgeRatingCategory Board { get; set; }
|
||||
public List<IGDB.Models.AgeRatingTitle> Classifications { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -174,9 +174,6 @@ namespace gaseous_server.Classes.Metadata
|
||||
}
|
||||
}
|
||||
|
||||
// optional metadata - usually downloaded as needed
|
||||
if (getAllMetadata == true)
|
||||
{
|
||||
if (Game.AgeRatings != null)
|
||||
{
|
||||
foreach (long AgeRatingId in Game.AgeRatings.Ids)
|
||||
@@ -185,6 +182,17 @@ namespace gaseous_server.Classes.Metadata
|
||||
}
|
||||
}
|
||||
|
||||
if (Game.ReleaseDates != null)
|
||||
{
|
||||
foreach (long ReleaseDateId in Game.ReleaseDates.Ids)
|
||||
{
|
||||
ReleaseDate GameReleaseDate = ReleaseDates.GetReleaseDates(ReleaseDateId);
|
||||
}
|
||||
}
|
||||
|
||||
// optional metadata - usually downloaded as needed
|
||||
if (getAllMetadata == true)
|
||||
{
|
||||
if (Game.AlternativeNames != null)
|
||||
{
|
||||
foreach (long AlternativeNameId in Game.AlternativeNames.Ids)
|
||||
@@ -334,5 +342,40 @@ namespace gaseous_server.Classes.Metadata
|
||||
search = 2,
|
||||
searchNoPlatform = 3
|
||||
}
|
||||
|
||||
public class MinimalGameItem
|
||||
{
|
||||
public MinimalGameItem(Game gameObject)
|
||||
{
|
||||
this.Id = gameObject.Id;
|
||||
this.Name = gameObject.Name;
|
||||
this.TotalRating = gameObject.TotalRating;
|
||||
this.TotalRatingCount = gameObject.TotalRatingCount;
|
||||
this.Cover = gameObject.Cover;
|
||||
this.Artworks = gameObject.Artworks;
|
||||
|
||||
// compile age ratings
|
||||
this.AgeRatings = new List<AgeRating>();
|
||||
if (gameObject.AgeRatings != null)
|
||||
{
|
||||
foreach (long ageRatingId in gameObject.AgeRatings.Ids)
|
||||
{
|
||||
AgeRating? rating = Classes.Metadata.AgeRatings.GetAgeRatings(ageRatingId);
|
||||
if (rating != null)
|
||||
{
|
||||
this.AgeRatings.Add(rating);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public long? Id { get; set; }
|
||||
public string Name { get; set; }
|
||||
public double? TotalRating { get; set; }
|
||||
public int? TotalRatingCount { get; set; }
|
||||
public IGDB.IdentityOrValue<IGDB.Models.Cover> Cover { get; set; }
|
||||
public IGDB.IdentitiesOrValues<IGDB.Models.Artwork> Artworks { get; set; }
|
||||
public List<IGDB.Models.AgeRating> AgeRatings { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
113
gaseous-server/Classes/Metadata/ReleaseDates.cs
Normal file
113
gaseous-server/Classes/Metadata/ReleaseDates.cs
Normal file
@@ -0,0 +1,113 @@
|
||||
using System;
|
||||
using IGDB;
|
||||
using IGDB.Models;
|
||||
|
||||
|
||||
namespace gaseous_server.Classes.Metadata
|
||||
{
|
||||
public class ReleaseDates
|
||||
{
|
||||
const string fieldList = "fields category,checksum,created_at,date,game,human,m,platform,region,status,updated_at,y;";
|
||||
|
||||
public ReleaseDates()
|
||||
{
|
||||
}
|
||||
|
||||
private static IGDBClient igdb = new IGDBClient(
|
||||
// Found in Twitch Developer portal for your app
|
||||
Config.IGDB.ClientId,
|
||||
Config.IGDB.Secret
|
||||
);
|
||||
|
||||
public static ReleaseDate? GetReleaseDates(long? Id)
|
||||
{
|
||||
if ((Id == 0) || (Id == null))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
else
|
||||
{
|
||||
Task<ReleaseDate> RetVal = _GetReleaseDates(SearchUsing.id, Id);
|
||||
return RetVal.Result;
|
||||
}
|
||||
}
|
||||
|
||||
public static ReleaseDate GetReleaseDates(string Slug)
|
||||
{
|
||||
Task<ReleaseDate> RetVal = _GetReleaseDates(SearchUsing.slug, Slug);
|
||||
return RetVal.Result;
|
||||
}
|
||||
|
||||
private static async Task<ReleaseDate> _GetReleaseDates(SearchUsing searchUsing, object searchValue)
|
||||
{
|
||||
// check database first
|
||||
Storage.CacheStatus? cacheStatus = new Storage.CacheStatus();
|
||||
if (searchUsing == SearchUsing.id)
|
||||
{
|
||||
cacheStatus = Storage.GetCacheStatus("ReleaseDate", (long)searchValue);
|
||||
}
|
||||
else
|
||||
{
|
||||
cacheStatus = Storage.GetCacheStatus("ReleaseDate", (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");
|
||||
}
|
||||
|
||||
ReleaseDate returnValue = new ReleaseDate();
|
||||
switch (cacheStatus)
|
||||
{
|
||||
case Storage.CacheStatus.NotPresent:
|
||||
returnValue = await GetObjectFromServer(WhereClause);
|
||||
Storage.NewCacheValue(returnValue);
|
||||
break;
|
||||
case Storage.CacheStatus.Expired:
|
||||
try
|
||||
{
|
||||
returnValue = await GetObjectFromServer(WhereClause);
|
||||
Storage.NewCacheValue(returnValue, true);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logging.Log(Logging.LogType.Warning, "Metadata: " + returnValue.GetType().Name, "An error occurred while connecting to IGDB. WhereClause: " + WhereClause, ex);
|
||||
returnValue = Storage.GetCacheValue<ReleaseDate>(returnValue, "id", (long)searchValue);
|
||||
}
|
||||
break;
|
||||
case Storage.CacheStatus.Current:
|
||||
returnValue = Storage.GetCacheValue<ReleaseDate>(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<ReleaseDate> GetObjectFromServer(string WhereClause)
|
||||
{
|
||||
// get ReleaseDates metadata
|
||||
var results = await igdb.QueryAsync<ReleaseDate>(IGDBClient.Endpoints.ReleaseDates, query: fieldList + " " + WhereClause + ";");
|
||||
var result = results.First();
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -218,9 +218,19 @@ namespace gaseous_server.Classes.Metadata
|
||||
{
|
||||
DataRow dataRow = dt.Rows[0];
|
||||
object returnObject = BuildCacheObject<T>(EndpointType, dataRow);
|
||||
try {
|
||||
if (!ObjectCache.ContainsKey(Endpoint + SearchValue))
|
||||
{
|
||||
ObjectCache.Add(Endpoint + SearchValue, new MemoryCacheObject{
|
||||
Object = returnObject
|
||||
});
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
// unable add item to cache
|
||||
ObjectCache.Clear();
|
||||
}
|
||||
return (T)returnObject;
|
||||
}
|
||||
}
|
||||
|
@@ -30,7 +30,16 @@ namespace gaseous_server.Classes
|
||||
}
|
||||
|
||||
// update games
|
||||
if (forceRefresh == true)
|
||||
{
|
||||
// when forced, only update games with ROMs for
|
||||
sql = "SELECT Id, `Name` FROM view_GamesWithRoms;";
|
||||
}
|
||||
else
|
||||
{
|
||||
// when run normally, update all games (since this will honour cache timeouts)
|
||||
sql = "SELECT Id, `Name` FROM Game;";
|
||||
}
|
||||
dt = db.ExecuteCMD(sql);
|
||||
|
||||
foreach (DataRow dr in dt.Rows)
|
||||
@@ -38,7 +47,7 @@ namespace gaseous_server.Classes
|
||||
try
|
||||
{
|
||||
Logging.Log(Logging.LogType.Information, "Metadata Refresh", "Refreshing metadata for game " + dr["name"] + " (" + dr["id"] + ")");
|
||||
Metadata.Games.GetGame((long)dr["id"], true, true, forceRefresh);
|
||||
Metadata.Games.GetGame((long)dr["id"], true, false, forceRefresh);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
@@ -1,3 +1,4 @@
|
||||
using System.Data;
|
||||
using System.Security.Claims;
|
||||
using System.Text;
|
||||
using Authentication;
|
||||
@@ -95,6 +96,7 @@ namespace gaseous_server.Controllers
|
||||
profile.EmailAddress = await _userManager.GetEmailAsync(user);
|
||||
profile.Roles = new List<string>(await _userManager.GetRolesAsync(user));
|
||||
profile.SecurityProfile = user.SecurityProfile;
|
||||
profile.UserPreferences = user.UserPreferences;
|
||||
profile.Roles.Sort();
|
||||
|
||||
return Ok(profile);
|
||||
@@ -115,6 +117,7 @@ namespace gaseous_server.Controllers
|
||||
profile.EmailAddress = await _userManager.GetEmailAsync(user);
|
||||
profile.Roles = new List<string>(await _userManager.GetRolesAsync(user));
|
||||
profile.SecurityProfile = user.SecurityProfile;
|
||||
profile.UserPreferences = user.UserPreferences;
|
||||
profile.Roles.Sort();
|
||||
|
||||
string profileString = "var userProfile = " + Newtonsoft.Json.JsonConvert.SerializeObject(profile, Newtonsoft.Json.Formatting.Indented) + ";";
|
||||
@@ -392,5 +395,23 @@ namespace gaseous_server.Controllers
|
||||
return NotFound();
|
||||
}
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
[Route("Preferences")]
|
||||
public async Task<IActionResult> SetPreferences(List<UserPreferenceViewModel> model)
|
||||
{
|
||||
ApplicationUser? user = await _userManager.GetUserAsync(User);
|
||||
if (user == null)
|
||||
{
|
||||
return Unauthorized();
|
||||
}
|
||||
else
|
||||
{
|
||||
user.UserPreferences = model;
|
||||
await _userManager.UpdateAsync(user);
|
||||
|
||||
return Ok();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -3,10 +3,12 @@ using System.Collections.Generic;
|
||||
using System.Data;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Authentication;
|
||||
using gaseous_server.Classes;
|
||||
using IGDB.Models;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Identity;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace gaseous_server.Controllers
|
||||
@@ -18,96 +20,27 @@ namespace gaseous_server.Controllers
|
||||
[ApiController]
|
||||
public class FilterController : ControllerBase
|
||||
{
|
||||
private readonly UserManager<ApplicationUser> _userManager;
|
||||
private readonly SignInManager<ApplicationUser> _signInManager;
|
||||
|
||||
public FilterController(
|
||||
UserManager<ApplicationUser> userManager,
|
||||
SignInManager<ApplicationUser> signInManager)
|
||||
{
|
||||
_userManager = userManager;
|
||||
_signInManager = signInManager;
|
||||
}
|
||||
|
||||
[MapToApiVersion("1.0")]
|
||||
[MapToApiVersion("1.1")]
|
||||
[HttpGet]
|
||||
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||
//[ResponseCache(CacheProfileName = "5Minute")]
|
||||
public Dictionary<string, object> Filter()
|
||||
public async Task<IActionResult> FilterAsync()
|
||||
{
|
||||
Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
||||
var user = await _userManager.GetUserAsync(User);
|
||||
|
||||
Dictionary<string, object> FilterSet = new Dictionary<string, object>();
|
||||
|
||||
// platforms
|
||||
List<FilterPlatform> platforms = new List<FilterPlatform>();
|
||||
//string sql = "SELECT Platform.Id, Platform.Abbreviation, Platform.AlternativeName, Platform.`Name`, Platform.PlatformLogo, (SELECT COUNT(Games_Roms.Id) AS RomCount FROM Games_Roms WHERE Games_Roms.PlatformId = Platform.Id) AS RomCount FROM Platform HAVING RomCount > 0 ORDER BY `Name`";
|
||||
string sql = "SELECT Platform.Id, Platform.Abbreviation, Platform.AlternativeName, Platform.`Name`, Platform.PlatformLogo, (SELECT COUNT(Games_Roms.Id) AS RomCount FROM Games_Roms WHERE Games_Roms.PlatformId = Platform.Id) AS RomCount, (SELECT COUNT(*) AS GameCount FROM (SELECT DISTINCT Games_Roms.GameId AS ROMGameId, Games_Roms.PlatformId FROM Games_Roms LEFT JOIN Game ON Game.Id = Games_Roms.GameId) Game WHERE Game.PlatformId = Platform.Id) AS GameCount FROM Platform HAVING RomCount > 0 ORDER BY `Name`";
|
||||
DataTable dbResponse = db.ExecuteCMD(sql);
|
||||
|
||||
foreach (DataRow dr in dbResponse.Rows)
|
||||
{
|
||||
FilterPlatform platformItem = new FilterPlatform(Classes.Metadata.Platforms.GetPlatform((long)dr["id"]));
|
||||
platformItem.RomCount = (int)(long)dr["RomCount"];
|
||||
platformItem.GameCount = (int)(long)dr["GameCount"];
|
||||
platforms.Add(platformItem);
|
||||
|
||||
}
|
||||
FilterSet.Add("platforms", platforms);
|
||||
|
||||
// genres
|
||||
List<Genre> genres = new List<Genre>();
|
||||
sql = "SELECT DISTINCT Relation_Game_Genres.GenresId AS id, Genre.`Name` FROM Relation_Game_Genres JOIN Genre ON Relation_Game_Genres.GenresId = Genre.Id WHERE Relation_Game_Genres.GameId IN (SELECT DISTINCT GameId FROM Games_Roms) ORDER BY `Name`;";
|
||||
dbResponse = db.ExecuteCMD(sql);
|
||||
|
||||
foreach (DataRow dr in dbResponse.Rows)
|
||||
{
|
||||
genres.Add(Classes.Metadata.Genres.GetGenres((long)dr["id"]));
|
||||
}
|
||||
FilterSet.Add("genres", genres);
|
||||
|
||||
// game modes
|
||||
List<GameMode> gameModes = new List<GameMode>();
|
||||
sql = "SELECT DISTINCT Relation_Game_GameModes.GameModesId AS id, GameMode.`Name` FROM Relation_Game_GameModes JOIN GameMode ON Relation_Game_GameModes.GameModesId = GameMode.Id WHERE Relation_Game_GameModes.GameId IN (SELECT DISTINCT GameId FROM Games_Roms) ORDER BY `Name`;";
|
||||
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 Relation_Game_PlayerPerspectives.PlayerPerspectivesId AS id, PlayerPerspective.`Name` FROM Relation_Game_PlayerPerspectives JOIN PlayerPerspective ON Relation_Game_PlayerPerspectives.PlayerPerspectivesId = PlayerPerspective.Id WHERE Relation_Game_PlayerPerspectives.GameId IN (SELECT DISTINCT GameId FROM Games_Roms) ORDER BY `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 Relation_Game_Themes.ThemesId AS id, Theme.`Name` FROM Relation_Game_Themes JOIN Theme ON Relation_Game_Themes.ThemesId = Theme.Id WHERE Relation_Game_Themes.GameId IN (SELECT DISTINCT GameId FROM Games_Roms) ORDER BY `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;
|
||||
}
|
||||
|
||||
public class FilterPlatform : IGDB.Models.Platform
|
||||
{
|
||||
public FilterPlatform(Platform platform)
|
||||
{
|
||||
var properties = platform.GetType().GetProperties();
|
||||
foreach (var prop in properties)
|
||||
{
|
||||
if (prop.GetGetMethod() != null)
|
||||
{
|
||||
this.GetType().GetProperty(prop.Name).SetValue(this, prop.GetValue(platform));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public int RomCount { get; set; }
|
||||
public int GameCount { get; set; }
|
||||
return Ok(Filters.Filter(user.SecurityProfile.AgeRestrictionPolicy.MaximumAgeRestriction, user.SecurityProfile.AgeRestrictionPolicy.IncludeUnrated));
|
||||
}
|
||||
}
|
||||
}
|
@@ -181,9 +181,10 @@ namespace gaseous_server.Controllers
|
||||
List<long> AgeClassificationsList = new List<long>();
|
||||
foreach (string ratingGroup in ratinggroup.Split(','))
|
||||
{
|
||||
if (AgeGroups.AgeGroupings.ContainsKey(ratingGroup))
|
||||
AgeGroups.AgeRestrictionGroupings ageRestriction = (AgeGroups.AgeRestrictionGroupings)Enum.Parse(typeof(AgeGroups.AgeRestrictionGroupings), ratingGroup);
|
||||
if (AgeGroups.AgeGroupings.ContainsKey(ageRestriction))
|
||||
{
|
||||
List<AgeGroups.AgeGroupItem> ageGroups = AgeGroups.AgeGroupings[ratingGroup];
|
||||
List<AgeGroups.AgeGroupItem> ageGroups = AgeGroups.AgeGroupings[ageRestriction];
|
||||
foreach (AgeGroups.AgeGroupItem ageGroup in ageGroups)
|
||||
{
|
||||
AgeClassificationsList.AddRange(ageGroup.AgeGroupItemValues);
|
||||
@@ -824,6 +825,44 @@ namespace gaseous_server.Controllers
|
||||
}
|
||||
}
|
||||
|
||||
[MapToApiVersion("1.0")]
|
||||
[MapToApiVersion("1.1")]
|
||||
[HttpGet]
|
||||
[Route("{GameId}/releasedates")]
|
||||
[ProducesResponseType(typeof(List<ReleaseDate>), StatusCodes.Status200OK)]
|
||||
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
||||
[ResponseCache(CacheProfileName = "7Days")]
|
||||
public ActionResult GameReleaseDates(long GameId)
|
||||
{
|
||||
try
|
||||
{
|
||||
IGDB.Models.Game gameObject = Classes.Metadata.Games.GetGame(GameId, false, false, false);
|
||||
if (gameObject != null)
|
||||
{
|
||||
List<ReleaseDate> rdObjects = new List<ReleaseDate>();
|
||||
if (gameObject.ReleaseDates != null)
|
||||
{
|
||||
foreach (long icId in gameObject.ReleaseDates.Ids)
|
||||
{
|
||||
ReleaseDate releaseDate = Classes.Metadata.ReleaseDates.GetReleaseDates(icId);
|
||||
|
||||
rdObjects.Add(releaseDate);
|
||||
}
|
||||
}
|
||||
|
||||
return Ok(rdObjects);
|
||||
}
|
||||
else
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
}
|
||||
|
||||
[MapToApiVersion("1.0")]
|
||||
[MapToApiVersion("1.1")]
|
||||
[HttpGet]
|
||||
|
@@ -82,6 +82,12 @@ namespace gaseous_server.Controllers
|
||||
Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
||||
|
||||
// get age ratings dictionary
|
||||
Dictionary<int, string> ClassificationBoardsStrings = new Dictionary<int, string>();
|
||||
foreach(IGDB.Models.AgeRatingCategory ageRatingCategory in Enum.GetValues(typeof(IGDB.Models.AgeRatingCategory)) )
|
||||
{
|
||||
ClassificationBoardsStrings.Add((int)ageRatingCategory, ageRatingCategory.ToString());
|
||||
}
|
||||
|
||||
Dictionary<int, string> AgeRatingsStrings = new Dictionary<int, string>();
|
||||
foreach(IGDB.Models.AgeRatingTitle ageRatingTitle in Enum.GetValues(typeof(IGDB.Models.AgeRatingTitle)) )
|
||||
{
|
||||
@@ -91,6 +97,9 @@ namespace gaseous_server.Controllers
|
||||
string ver = "var AppVersion = \"" + Assembly.GetExecutingAssembly().GetName().Version.ToString() + "\";" + Environment.NewLine +
|
||||
"var DBSchemaVersion = \"" + db.GetDatabaseSchemaVersion() + "\";" + Environment.NewLine +
|
||||
"var FirstRunStatus = " + Config.ReadSetting("FirstRunStatus", "0") + ";" + Environment.NewLine +
|
||||
"var AgeRatingBoardsStrings = " + JsonSerializer.Serialize(ClassificationBoardsStrings, new JsonSerializerOptions{
|
||||
WriteIndented = true
|
||||
}) + ";" + Environment.NewLine +
|
||||
"var AgeRatingStrings = " + JsonSerializer.Serialize(AgeRatingsStrings, new JsonSerializerOptions{
|
||||
WriteIndented = true
|
||||
}) + ";" + Environment.NewLine +
|
||||
|
@@ -39,33 +39,41 @@ namespace gaseous_server.Controllers.v1_1
|
||||
|
||||
[MapToApiVersion("1.1")]
|
||||
[HttpPost]
|
||||
[ProducesResponseType(typeof(List<Game>), StatusCodes.Status200OK)]
|
||||
public async Task<IActionResult> Game_v1_1(GameSearchModel model)
|
||||
[ProducesResponseType(typeof(GameReturnPackage), StatusCodes.Status200OK)]
|
||||
public async Task<IActionResult> Game_v1_1(GameSearchModel model, int pageNumber = 0, int pageSize = 0)
|
||||
{
|
||||
var user = await _userManager.GetUserAsync(User);
|
||||
|
||||
if (user != null)
|
||||
{
|
||||
// apply security profile filtering
|
||||
List<string> RemoveAgeGroups = new List<string>();
|
||||
switch (user.SecurityProfile.AgeRestrictionPolicy.MaximumAgeRestriction.ToLower())
|
||||
if (model.GameAgeRating.AgeGroupings.Count == 0)
|
||||
{
|
||||
case "adult":
|
||||
model.GameAgeRating.AgeGroupings.Add(AgeGroups.AgeRestrictionGroupings.Adult);
|
||||
model.GameAgeRating.AgeGroupings.Add(AgeGroups.AgeRestrictionGroupings.Mature);
|
||||
model.GameAgeRating.AgeGroupings.Add(AgeGroups.AgeRestrictionGroupings.Teen);
|
||||
model.GameAgeRating.AgeGroupings.Add(AgeGroups.AgeRestrictionGroupings.Child);
|
||||
model.GameAgeRating.IncludeUnrated = true;
|
||||
}
|
||||
List<AgeGroups.AgeRestrictionGroupings> RemoveAgeGroups = new List<AgeGroups.AgeRestrictionGroupings>();
|
||||
switch (user.SecurityProfile.AgeRestrictionPolicy.MaximumAgeRestriction)
|
||||
{
|
||||
case AgeGroups.AgeRestrictionGroupings.Adult:
|
||||
break;
|
||||
case "mature":
|
||||
RemoveAgeGroups.Add("Adult");
|
||||
case AgeGroups.AgeRestrictionGroupings.Mature:
|
||||
RemoveAgeGroups.Add(AgeGroups.AgeRestrictionGroupings.Adult);
|
||||
break;
|
||||
case "teen":
|
||||
RemoveAgeGroups.Add("Adult");
|
||||
RemoveAgeGroups.Add("Mature");
|
||||
case AgeGroups.AgeRestrictionGroupings.Teen:
|
||||
RemoveAgeGroups.Add(AgeGroups.AgeRestrictionGroupings.Adult);
|
||||
RemoveAgeGroups.Add(AgeGroups.AgeRestrictionGroupings.Mature);
|
||||
break;
|
||||
case "child":
|
||||
RemoveAgeGroups.Add("Adult");
|
||||
RemoveAgeGroups.Add("Mature");
|
||||
RemoveAgeGroups.Add("Teen");
|
||||
case AgeGroups.AgeRestrictionGroupings.Child:
|
||||
RemoveAgeGroups.Add(AgeGroups.AgeRestrictionGroupings.Adult);
|
||||
RemoveAgeGroups.Add(AgeGroups.AgeRestrictionGroupings.Mature);
|
||||
RemoveAgeGroups.Add(AgeGroups.AgeRestrictionGroupings.Teen);
|
||||
break;
|
||||
}
|
||||
foreach (string RemoveAgeGroup in RemoveAgeGroups)
|
||||
foreach (AgeGroups.AgeRestrictionGroupings RemoveAgeGroup in RemoveAgeGroups)
|
||||
{
|
||||
if (model.GameAgeRating.AgeGroupings.Contains(RemoveAgeGroup))
|
||||
{
|
||||
@@ -77,7 +85,47 @@ namespace gaseous_server.Controllers.v1_1
|
||||
model.GameAgeRating.IncludeUnrated = false;
|
||||
}
|
||||
|
||||
return Ok(GetGames(model));
|
||||
return Ok(GetGames(model, pageNumber, pageSize));
|
||||
}
|
||||
else
|
||||
{
|
||||
return Unauthorized();
|
||||
}
|
||||
}
|
||||
|
||||
[MapToApiVersion("1.1")]
|
||||
[HttpGet]
|
||||
[Route("{GameId}/Related")]
|
||||
[ProducesResponseType(typeof(GameReturnPackage), StatusCodes.Status200OK)]
|
||||
public async Task<IActionResult> GameRelated(long GameId)
|
||||
{
|
||||
var user = await _userManager.GetUserAsync(User);
|
||||
|
||||
if (user != null)
|
||||
{
|
||||
string IncludeUnrated = "";
|
||||
if (user.SecurityProfile.AgeRestrictionPolicy.IncludeUnrated == true) {
|
||||
IncludeUnrated = " OR view_Games.AgeGroupId IS NULL";
|
||||
}
|
||||
|
||||
Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
||||
string sql = "SELECT view_Games.Id, view_Games.AgeGroupId, Relation_Game_SimilarGames.SimilarGamesId FROM view_Games JOIN Relation_Game_SimilarGames ON view_Games.Id = Relation_Game_SimilarGames.GameId AND Relation_Game_SimilarGames.SimilarGamesId IN (SELECT Id FROM view_Games) WHERE view_Games.Id = @id AND (view_Games.AgeGroupId <= @agegroupid" + IncludeUnrated + ")";
|
||||
Dictionary<string, object> dbDict = new Dictionary<string, object>();
|
||||
dbDict.Add("id", GameId);
|
||||
dbDict.Add("agegroupid", (int)user.SecurityProfile.AgeRestrictionPolicy.MaximumAgeRestriction);
|
||||
|
||||
List<IGDB.Models.Game> RetVal = new List<IGDB.Models.Game>();
|
||||
|
||||
DataTable dbResponse = db.ExecuteCMD(sql, dbDict);
|
||||
|
||||
foreach (DataRow dr in dbResponse.Rows)
|
||||
{
|
||||
RetVal.Add(Classes.Metadata.Games.GetGame((long)dr["SimilarGamesId"], false, false, false));
|
||||
}
|
||||
|
||||
GameReturnPackage gameReturn = new GameReturnPackage(RetVal.Count, RetVal);
|
||||
|
||||
return Ok(gameReturn);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -109,7 +157,12 @@ namespace gaseous_server.Controllers.v1_1
|
||||
|
||||
public class GameAgeRatingItem
|
||||
{
|
||||
public List<string> AgeGroupings { get; set; } = new List<string>{ "Child", "Teen", "Mature", "Adult" };
|
||||
public List<AgeGroups.AgeRestrictionGroupings> AgeGroupings { get; set; } = new List<AgeGroups.AgeRestrictionGroupings>{
|
||||
AgeGroups.AgeRestrictionGroupings.Child,
|
||||
AgeGroups.AgeRestrictionGroupings.Teen,
|
||||
AgeGroups.AgeRestrictionGroupings.Mature,
|
||||
AgeGroups.AgeRestrictionGroupings.Adult
|
||||
};
|
||||
public bool IncludeUnrated { get; set; } = true;
|
||||
}
|
||||
|
||||
@@ -128,7 +181,7 @@ namespace gaseous_server.Controllers.v1_1
|
||||
}
|
||||
}
|
||||
|
||||
public static List<Game> GetGames(GameSearchModel model)
|
||||
public static GameReturnPackage GetGames(GameSearchModel model, int pageNumber = 0, int pageSize = 0)
|
||||
{
|
||||
string whereClause = "";
|
||||
string havingClause = "";
|
||||
@@ -191,16 +244,23 @@ namespace gaseous_server.Controllers.v1_1
|
||||
}
|
||||
}
|
||||
|
||||
string unratedClause = "totalRating IS NOT NULL";
|
||||
string unratedClause = "";
|
||||
if (model.GameRating.IncludeUnrated == true)
|
||||
{
|
||||
unratedClause = "totalRating IS NULL";
|
||||
}
|
||||
|
||||
if (ratingClauseValue.Length > 0)
|
||||
{
|
||||
if (unratedClause.Length > 0)
|
||||
{
|
||||
havingClauses.Add("((" + ratingClauseValue + ") OR " + unratedClause + ")");
|
||||
}
|
||||
else
|
||||
{
|
||||
havingClauses.Add("(" + ratingClauseValue + ")");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (model.Platform.Count > 0)
|
||||
@@ -292,24 +352,8 @@ namespace gaseous_server.Controllers.v1_1
|
||||
{
|
||||
if (model.GameAgeRating.AgeGroupings.Count > 0)
|
||||
{
|
||||
List<long> AgeClassificationsList = new List<long>();
|
||||
foreach (string ratingGroup in model.GameAgeRating.AgeGroupings)
|
||||
{
|
||||
if (AgeGroups.AgeGroupings.ContainsKey(ratingGroup))
|
||||
{
|
||||
List<AgeGroups.AgeGroupItem> ageGroups = AgeGroups.AgeGroupings[ratingGroup];
|
||||
foreach (AgeGroups.AgeGroupItem ageGroup in ageGroups)
|
||||
{
|
||||
AgeClassificationsList.AddRange(ageGroup.AgeGroupItemValues);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (AgeClassificationsList.Count > 0)
|
||||
{
|
||||
AgeClassificationsList = new HashSet<long>(AgeClassificationsList).ToList();
|
||||
tempVal = "(view_AgeRatings.Rating IN (";
|
||||
for (int i = 0; i < AgeClassificationsList.Count; i++)
|
||||
tempVal = "(AgeGroupId IN (";
|
||||
for (int i = 0; i < model.GameAgeRating.AgeGroupings.Count; i++)
|
||||
{
|
||||
if (i > 0)
|
||||
{
|
||||
@@ -317,20 +361,19 @@ namespace gaseous_server.Controllers.v1_1
|
||||
}
|
||||
string themeLabel = "@Rating" + i;
|
||||
tempVal += themeLabel;
|
||||
whereParams.Add(themeLabel, AgeClassificationsList[i]);
|
||||
whereParams.Add(themeLabel, model.GameAgeRating.AgeGroupings[i]);
|
||||
}
|
||||
tempVal += ")";
|
||||
|
||||
if (model.GameAgeRating.IncludeUnrated == true)
|
||||
{
|
||||
tempVal += " OR view_AgeRatings.Rating IS NULL";
|
||||
tempVal += " OR AgeGroupId IS NULL";
|
||||
}
|
||||
tempVal += ")";
|
||||
|
||||
whereClauses.Add(tempVal);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// build where clause
|
||||
if (whereClauses.Count > 0)
|
||||
@@ -396,18 +439,66 @@ namespace gaseous_server.Controllers.v1_1
|
||||
string orderByClause = "ORDER BY `" + orderByField + "` " + orderByOrder;
|
||||
|
||||
Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
||||
string sql = "SELECT DISTINCT Games_Roms.GameId AS ROMGameId, Game.*, case when Game.`Name` like 'The %' then CONCAT(trim(substr(Game.`Name` from 4)), ', The') else Game.`Name` end as NameThe FROM Games_Roms LEFT JOIN Game ON Game.Id = Games_Roms.GameId LEFT JOIN Relation_Game_Genres ON Game.Id = Relation_Game_Genres.GameId LEFT JOIN Relation_Game_GameModes ON Game.Id = Relation_Game_GameModes.GameId LEFT JOIN Relation_Game_PlayerPerspectives ON Game.Id = Relation_Game_PlayerPerspectives.GameId LEFT JOIN Relation_Game_Themes ON Game.Id = Relation_Game_Themes.GameId LEFT JOIN (SELECT Relation_Game_AgeRatings.GameId, AgeRating.* FROM Relation_Game_AgeRatings JOIN AgeRating ON Relation_Game_AgeRatings.AgeRatingsId = AgeRating.Id) view_AgeRatings ON Game.Id = view_AgeRatings.GameId " + whereClause + " " + havingClause + " " + orderByClause;
|
||||
string sql = "SELECT DISTINCT view_Games.* FROM view_Games LEFT JOIN Games_Roms ON view_Games.Id = Games_Roms.GameId LEFT JOIN Relation_Game_Genres ON view_Games.Id = Relation_Game_Genres.GameId LEFT JOIN Relation_Game_GameModes ON view_Games.Id = Relation_Game_GameModes.GameId LEFT JOIN Relation_Game_PlayerPerspectives ON view_Games.Id = Relation_Game_PlayerPerspectives.GameId LEFT JOIN Relation_Game_Themes ON view_Games.Id = Relation_Game_Themes.GameId " + whereClause + " " + havingClause + " " + orderByClause;
|
||||
|
||||
List<IGDB.Models.Game> RetVal = new List<IGDB.Models.Game>();
|
||||
|
||||
DataTable dbResponse = db.ExecuteCMD(sql, whereParams);
|
||||
foreach (DataRow dr in dbResponse.Rows)
|
||||
|
||||
// get count
|
||||
int RecordCount = dbResponse.Rows.Count;
|
||||
|
||||
// compile data for return
|
||||
int pageOffset = pageSize * (pageNumber - 1);
|
||||
for (int i = 0; i < dbResponse.Rows.Count; i++)
|
||||
{
|
||||
//RetVal.Add(Classes.Metadata.Games.GetGame((long)dr["ROMGameId"], false, false));
|
||||
RetVal.Add(Classes.Metadata.Games.GetGame(dr));
|
||||
DataRow dr = dbResponse.Rows[i];
|
||||
|
||||
bool includeGame = false;
|
||||
|
||||
if (pageSize == 0)
|
||||
{
|
||||
// page size is full size include all
|
||||
includeGame = true;
|
||||
}
|
||||
else if (i >= pageOffset && i < (pageOffset + pageSize))
|
||||
{
|
||||
includeGame = true;
|
||||
}
|
||||
|
||||
return RetVal;
|
||||
if (includeGame == true)
|
||||
{
|
||||
RetVal.Add(Classes.Metadata.Games.GetGame(dr));
|
||||
}
|
||||
}
|
||||
|
||||
GameReturnPackage gameReturn = new GameReturnPackage(RecordCount, RetVal);
|
||||
|
||||
return gameReturn;
|
||||
}
|
||||
|
||||
public class GameReturnPackage
|
||||
{
|
||||
public GameReturnPackage()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public GameReturnPackage(int Count, List<Game> Games)
|
||||
{
|
||||
this.Count = Count;
|
||||
|
||||
List<Games.MinimalGameItem> minimalGames = new List<Games.MinimalGameItem>();
|
||||
foreach (Game game in Games)
|
||||
{
|
||||
minimalGames.Add(new Classes.Metadata.Games.MinimalGameItem(game));
|
||||
}
|
||||
|
||||
this.Games = minimalGames;
|
||||
}
|
||||
|
||||
public int Count { get; set; }
|
||||
public List<Games.MinimalGameItem> Games { get; set; } = new List<Games.MinimalGameItem>();
|
||||
}
|
||||
}
|
||||
}
|
@@ -134,7 +134,7 @@ namespace gaseous_server
|
||||
|
||||
case QueueItemType.MetadataRefresh:
|
||||
Logging.Log(Logging.LogType.Debug, "Timered Event", "Starting Metadata Refresher");
|
||||
Classes.MetadataManagement.RefreshMetadata();
|
||||
Classes.MetadataManagement.RefreshMetadata(_ForceExecute);
|
||||
|
||||
_SaveLastRunTime = true;
|
||||
|
||||
|
@@ -13,6 +13,8 @@ using Microsoft.OpenApi.Models;
|
||||
using Authentication;
|
||||
using Microsoft.AspNetCore.Identity;
|
||||
using Microsoft.AspNetCore.Identity.UI.Services;
|
||||
using IGDB.Models;
|
||||
using gaseous_server.Classes.Metadata;
|
||||
|
||||
Logging.WriteToDiskOnly = true;
|
||||
Logging.Log(Logging.LogType.Information, "Startup", "Starting Gaseous Server " + Assembly.GetExecutingAssembly().GetName().Version);
|
||||
@@ -39,6 +41,9 @@ db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.Conn
|
||||
// set up db
|
||||
db.InitDB();
|
||||
|
||||
// populate db with static data for lookups
|
||||
AgeRatings.PopulateAgeMap();
|
||||
|
||||
// load app settings
|
||||
Config.InitSettings();
|
||||
// write updated settings back to the config file
|
||||
|
66
gaseous-server/Support/Database/MySQL/gaseous-1007.sql
Normal file
66
gaseous-server/Support/Database/MySQL/gaseous-1007.sql
Normal file
@@ -0,0 +1,66 @@
|
||||
CREATE TABLE `ClassificationMap` (
|
||||
`AgeGroupId` INT NOT NULL,
|
||||
`ClassificationBoardId` INT NOT NULL,
|
||||
`RatingId` INT NOT NULL,
|
||||
PRIMARY KEY (`AgeGroupId`, `ClassificationBoardId`, `RatingId`));
|
||||
|
||||
CREATE OR REPLACE VIEW `view_GamesWithRoms` AS
|
||||
SELECT DISTINCT
|
||||
Games_Roms.GameId AS ROMGameId,
|
||||
Game.*,
|
||||
CASE
|
||||
WHEN
|
||||
Game.`Name` LIKE 'The %'
|
||||
THEN
|
||||
CONCAT(TRIM(SUBSTR(Game.`Name` FROM 4)),
|
||||
', The')
|
||||
ELSE Game.`Name`
|
||||
END AS NameThe
|
||||
FROM
|
||||
Games_Roms
|
||||
LEFT JOIN
|
||||
Game ON Game.Id = Games_Roms.GameId;
|
||||
|
||||
CREATE OR REPLACE VIEW `view_Games` AS
|
||||
SELECT
|
||||
*
|
||||
FROM
|
||||
(SELECT DISTINCT
|
||||
row_number() over (partition by Id order by AgeGroupId desc) as seqnum, view_GamesWithRoms.*,
|
||||
(SELECT
|
||||
AgeGroupId
|
||||
FROM
|
||||
ClassificationMap
|
||||
WHERE
|
||||
RatingId = AgeRating.Rating
|
||||
ORDER BY AgeGroupId DESC) AgeGroupId
|
||||
FROM
|
||||
view_GamesWithRoms
|
||||
LEFT JOIN Relation_Game_AgeRatings ON view_GamesWithRoms.Id = Relation_Game_AgeRatings.GameId
|
||||
LEFT JOIN AgeRating ON Relation_Game_AgeRatings.AgeRatingsId = AgeRating.Id
|
||||
) g
|
||||
WHERE g.seqnum = 1;
|
||||
|
||||
CREATE TABLE `ReleaseDate` (
|
||||
`Id` BIGINT NOT NULL,
|
||||
`Category` INT(11) NULL DEFAULT NULL,
|
||||
`Checksum` VARCHAR(45) NULL DEFAULT NULL,
|
||||
`CreatedAt` DATETIME NULL DEFAULT NULL,
|
||||
`Date` DATETIME NULL,
|
||||
`Game` BIGINT NULL,
|
||||
`Human` VARCHAR(100) NULL,
|
||||
`m` INT NULL,
|
||||
`Platform` BIGINT NULL,
|
||||
`Region` INT NULL,
|
||||
`Status` BIGINT NULL,
|
||||
`UpdatedAt` DATETIME NULL DEFAULT NULL,
|
||||
`y` INT NULL,
|
||||
`dateAdded` DATETIME NULL DEFAULT NULL,
|
||||
`lastUpdated` DATETIME NULL DEFAULT NULL,
|
||||
PRIMARY KEY (`Id`));
|
||||
|
||||
CREATE TABLE `User_Settings` (
|
||||
`Id` VARCHAR(128) NOT NULL,
|
||||
`Setting` VARCHAR(45) NOT NULL,
|
||||
`Value` LONGTEXT NULL DEFAULT NULL,
|
||||
PRIMARY KEY (`Id`, `Setting`));
|
@@ -46,6 +46,8 @@
|
||||
<None Remove="Support\Database\MySQL\gaseous-1003.sql" />
|
||||
<None Remove="Support\Database\MySQL\gaseous-1004.sql" />
|
||||
<None Remove="Support\Database\MySQL\gaseous-1005.sql" />
|
||||
<None Remove="Support\Database\MySQL\gaseous-1006.sql" />
|
||||
<None Remove="Support\Database\MySQL\gaseous-1007.sql" />
|
||||
<None Remove="Classes\Metadata\" />
|
||||
<None Remove="Assets\" />
|
||||
<None Remove="Assets\Ratings\" />
|
||||
@@ -174,5 +176,7 @@
|
||||
<EmbeddedResource Include="Support\Database\MySQL\gaseous-1003.sql" />
|
||||
<EmbeddedResource Include="Support\Database\MySQL\gaseous-1004.sql" />
|
||||
<EmbeddedResource Include="Support\Database\MySQL\gaseous-1005.sql" />
|
||||
<EmbeddedResource Include="Support\Database\MySQL\gaseous-1006.sql" />
|
||||
<EmbeddedResource Include="Support\Database\MySQL\gaseous-1007.sql" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
BIN
gaseous-server/wwwroot/.DS_Store
vendored
BIN
gaseous-server/wwwroot/.DS_Store
vendored
Binary file not shown.
@@ -5,7 +5,7 @@
|
||||
<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>
|
||||
<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>
|
||||
|
@@ -1,8 +1,79 @@
|
||||
<div id="properties_toc">
|
||||
<div id="properties_profile_toc_general" name="properties_profile_toc_item" onclick="ProfileSelectTab('general');">Account</div>
|
||||
<div id="properties_profile_toc_general" name="properties_profile_toc_item" onclick="ProfileSelectTab('general');">Preferences</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" onchange="SavePrefValue_Value(this);">
|
||||
<option value="infinite">Infinite scrolling</option>
|
||||
<option value="paged">Paged</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" onchange="SavePrefValue_Checkbox(this);"><label for="profile_pref_LibraryShowGameTitle"> Show title</label>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<input type="checkbox" id="profile_pref_LibraryShowGameRating" data-pref="LibraryShowGameRating" onchange="SavePrefValue_Checkbox(this);"><label for="profile_pref_LibraryShowGameRating"> Show rating</label>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<input type="checkbox" id="profile_pref_LibraryShowGameClassification" data-pref="LibraryShowGameClassification" onchange="SavePrefValue_Checkbox(this);"><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" 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);">
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<div id="properties_bodypanel_account" name="properties_profile_tab" style="display: none;">
|
||||
<h3>Reset Password</h3>
|
||||
<table style="width: 100%;">
|
||||
<tr>
|
||||
@@ -55,6 +126,125 @@
|
||||
}
|
||||
}
|
||||
|
||||
function GetPrefInitialValues() {
|
||||
var paginationMode = document.getElementById('profile_pref-LibraryPagination');
|
||||
paginationMode.value = GetPreference('LibraryPagination', 'infinite');
|
||||
|
||||
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 SavePrefValue_Checkbox(e) {
|
||||
var ValueName = e.getAttribute("data-pref");
|
||||
SetPreference(ValueName, e.checked);
|
||||
|
||||
updateDisplay(ValueName, e.checked);
|
||||
|
||||
executeFilter1_1(1);
|
||||
}
|
||||
|
||||
function SavePrefValue_Value(e) {
|
||||
var ValueName = e.getAttribute("data-pref");
|
||||
SetPreference(ValueName, e.value);
|
||||
|
||||
executeFilter1_1(1);
|
||||
}
|
||||
|
||||
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 ];
|
||||
}
|
||||
|
||||
SetPreference('LibraryGameClassificationDisplayOrder', JSON.stringify(model));
|
||||
|
||||
executeFilter1_1(1);
|
||||
}
|
||||
|
||||
function checkPasswordsMatch() {
|
||||
var oldPassword = document.getElementById('profile_oldpassword').value;
|
||||
var newPassword = document.getElementById('profile_newpassword').value;
|
||||
@@ -129,4 +319,5 @@
|
||||
}
|
||||
|
||||
ProfileSelectTab('general');
|
||||
GetPrefInitialValues();
|
||||
</script>
|
||||
|
@@ -35,6 +35,9 @@
|
||||
|
||||
<div id="gamesummary">
|
||||
<div id="gamesummary_cover"></div>
|
||||
<div id="gamesummary_firstrelease">
|
||||
<h3>First Released</h3>
|
||||
</div>
|
||||
<div id="gamesumarry_genres">
|
||||
<h3>Genres</h3>
|
||||
</div>
|
||||
@@ -83,6 +86,10 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="gamesummarysimilar">
|
||||
<h3>Similar Games</h3>
|
||||
<div id="gamesummarysimilarcontent"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -234,6 +241,16 @@
|
||||
}
|
||||
gameSummaryCover.appendChild(gameImage);
|
||||
|
||||
// load release date
|
||||
var gameSummaryRelease = document.getElementById('gamesummary_firstrelease');
|
||||
if (result.firstReleaseDate) {
|
||||
var firstRelease = document.createElement('p');
|
||||
firstRelease.innerHTML = '<p>' + moment(result.firstReleaseDate).format('LL') + ' (' + moment(result.firstReleaseDate).fromNow() + ')</p>';
|
||||
gameSummaryRelease.appendChild(firstRelease);
|
||||
} else {
|
||||
gameSummaryRelease.setAttribute('style', 'display: none;');
|
||||
}
|
||||
|
||||
// load ratings
|
||||
var gameSummaryRatings = document.getElementById('gamesummary_ratings');
|
||||
if (result.ageRatings) {
|
||||
@@ -344,6 +361,26 @@
|
||||
gamescreenshots.setAttribute('style', 'display: none;');
|
||||
}
|
||||
|
||||
// load similar
|
||||
var gameSummarySimilar = document.getElementById('gamesummarysimilar');
|
||||
ajaxCall('/api/v1.1/Games/' + gameId + '/Related', 'GET', function (result) {
|
||||
if (result.games.length > 0) {
|
||||
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);
|
||||
gameSummarySimilarContent.appendChild(similarObject);
|
||||
}
|
||||
|
||||
$('.lazy').Lazy({
|
||||
scrollDirection: 'vertical',
|
||||
effect: 'fadeIn',
|
||||
visibleOnly: true
|
||||
});
|
||||
} else {
|
||||
gameSummarySimilar.setAttribute('style', 'display: none;');
|
||||
}
|
||||
});
|
||||
|
||||
// load roms
|
||||
loadRoms();
|
||||
});
|
||||
|
@@ -2,9 +2,34 @@
|
||||
<div id="bgImage_Opacity"></div>
|
||||
</div>
|
||||
|
||||
<div id="games_home">
|
||||
<div id="games_filter_scroller">
|
||||
<div id="games_filter"></div>
|
||||
</div>
|
||||
<div id="games_home">
|
||||
<div id="games_home_box">
|
||||
<div id="games_library_controls">
|
||||
<div id="games_library_orderby" class="games_library_controlblock">
|
||||
<span>Order by: </span>
|
||||
<select id="games_library_orderby_select" onchange="executeFilter1_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" onchange="executeFilter1_1();">
|
||||
<option selected="selected" value="Ascending">Ascending</option>
|
||||
<option value="Descending">Descending</option>
|
||||
</select>
|
||||
</div>
|
||||
<div id="games_library_recordcount" class="games_library_controlblock"></div>
|
||||
</div>
|
||||
<div id="games_library"></div>
|
||||
<div id="games_library_pagerstore" style="display: none;">0</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="games_pager" style="display: none;">
|
||||
< 1 2 3 4 5 >
|
||||
</div>
|
||||
|
||||
<script type="text/javascript">
|
||||
|
@@ -19,9 +19,25 @@
|
||||
|
||||
panel.appendChild(containerPanelSearch);
|
||||
|
||||
panel.appendChild(buildFilterPanelHeader('userrating', 'User Rating'));
|
||||
panel.appendChild(buildFilterPanelHeader('userrating', 'User Rating', true, false));
|
||||
var containerPanelUserRating = document.createElement('div');
|
||||
containerPanelUserRating.id = 'filter_panel_box_userrating';
|
||||
containerPanelUserRating.className = 'filter_panel_box';
|
||||
|
||||
var containerPanelUserRatingCheckBox = document.createElement('input');
|
||||
containerPanelUserRatingCheckBox.id = 'filter_panel_userrating_enabled';
|
||||
containerPanelUserRatingCheckBox.type = 'checkbox';
|
||||
containerPanelUserRatingCheckBox.setAttribute('oninput', 'executeFilterDelayed();');
|
||||
var ratingEnabledCookie = getCookie('filter_panel_userrating_enabled');
|
||||
if (ratingEnabledCookie) {
|
||||
if (ratingEnabledCookie == "true") {
|
||||
containerPanelUserRatingCheckBox.checked = true;
|
||||
} else {
|
||||
containerPanelUserRatingCheckBox.checked = false;
|
||||
}
|
||||
}
|
||||
containerPanelUserRating.appendChild(containerPanelUserRatingCheckBox);
|
||||
|
||||
var containerPanelUserRatingMinField = document.createElement('input');
|
||||
var minRatingCookie = getCookie('filter_panel_userrating_min');
|
||||
if (minRatingCookie) {
|
||||
@@ -72,7 +88,23 @@
|
||||
buildFilterPanel(panel, 'theme', 'Themes', result.themes, true, false);
|
||||
}
|
||||
|
||||
if (result.agegroupings) {
|
||||
if (result.agegroupings.length > 1) {
|
||||
buildFilterPanel(panel, 'agegroupings', 'Age Groups', result.agegroupings, true, false);
|
||||
}
|
||||
}
|
||||
|
||||
targetElement.appendChild(panel);
|
||||
|
||||
// set order by values
|
||||
var orderByCookie = getCookie('games_library_orderby_select');
|
||||
if (orderByCookie) {
|
||||
document.getElementById('games_library_orderby_select').value = orderByCookie;
|
||||
}
|
||||
var orderByDirectionCookie = getCookie('games_library_orderby_direction_select');
|
||||
if (orderByDirectionCookie) {
|
||||
document.getElementById('games_library_orderby_direction_select').value = orderByDirectionCookie;
|
||||
}
|
||||
}
|
||||
|
||||
function buildFilterPanel(targetElement, headerString, friendlyHeaderString, valueList, showToggle, initialDisplay) {
|
||||
@@ -80,7 +112,6 @@ function buildFilterPanel(targetElement, headerString, friendlyHeaderString, val
|
||||
var displayCookie = getCookie('filter_panel_box_' + headerString);
|
||||
if (displayCookie) {
|
||||
initialDisplay = (displayCookie === 'true');
|
||||
console.log(displayCookie);
|
||||
}
|
||||
targetElement.appendChild(buildFilterPanelHeader(headerString, friendlyHeaderString, showToggle, initialDisplay));
|
||||
|
||||
@@ -92,14 +123,13 @@ function buildFilterPanel(targetElement, headerString, friendlyHeaderString, val
|
||||
}
|
||||
for (var i = 0; i < valueList.length; i++) {
|
||||
var tags;
|
||||
switch(headerString) {
|
||||
case 'platform':
|
||||
|
||||
if (valueList[i].gameCount) {
|
||||
tags = [
|
||||
{
|
||||
'label': valueList[i].gameCount
|
||||
}
|
||||
];
|
||||
break;
|
||||
}
|
||||
containerPanel.appendChild(buildFilterPanelItem(headerString, valueList[i].id, valueList[i].name, tags));
|
||||
}
|
||||
@@ -201,85 +231,6 @@ function executeFilterDelayed() {
|
||||
filterExecutor = setTimeout(executeFilter1_1, 1000);
|
||||
}
|
||||
|
||||
function executeFilter() {
|
||||
// build filter lists
|
||||
var queries = [];
|
||||
|
||||
var platforms = '';
|
||||
var genres = '';
|
||||
|
||||
var searchString = document.getElementById('filter_panel_search');
|
||||
if (searchString.value.length > 0) {
|
||||
queries.push('name=' + searchString.value);
|
||||
}
|
||||
setCookie(searchString.id, searchString.value);
|
||||
|
||||
var minUserRating = 0;
|
||||
var minUserRatingInput = document.getElementById('filter_panel_userrating_min');
|
||||
if (minUserRatingInput.value) {
|
||||
minUserRating = minUserRatingInput.value;
|
||||
queries.push('minrating=' + minUserRating);
|
||||
}
|
||||
setCookie(minUserRatingInput.id, minUserRatingInput.value);
|
||||
|
||||
var maxUserRating = 100;
|
||||
var maxUserRatingInput = document.getElementById('filter_panel_userrating_max');
|
||||
if (maxUserRatingInput.value) {
|
||||
maxUserRating = maxUserRatingInput.value;
|
||||
queries.push('maxrating=' + maxUserRating);
|
||||
}
|
||||
setCookie(maxUserRatingInput.id, maxUserRatingInput.value);
|
||||
|
||||
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 += '&';
|
||||
}
|
||||
|
||||
queryString += queries[i];
|
||||
}
|
||||
}
|
||||
|
||||
console.log('Query string = ' + queryString);
|
||||
|
||||
ajaxCall('/api/v1.0/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) {
|
||||
setCookie(Filters[i].id, true);
|
||||
if (queryString.length > 0) {
|
||||
queryString += ',';
|
||||
}
|
||||
queryString += Filters[i].getAttribute('filter_id');
|
||||
} else {
|
||||
setCookie(Filters[i].id, false);
|
||||
}
|
||||
}
|
||||
|
||||
if (queryString.length > 0) {
|
||||
queryString = filterName + '=' + queryString;
|
||||
}
|
||||
|
||||
return queryString;
|
||||
}
|
||||
|
||||
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" } ]
|
||||
@@ -301,12 +252,23 @@ function buildFilterTag(tags) {
|
||||
return boundingDiv;
|
||||
}
|
||||
|
||||
function executeFilter1_1() {
|
||||
console.log("Execute filter 1.1");
|
||||
function executeFilter1_1(pageNumber, pageSize) {
|
||||
if (!pageNumber) {
|
||||
pageNumber = 1;
|
||||
}
|
||||
|
||||
if (!pageSize) {
|
||||
pageSize = 30;
|
||||
}
|
||||
|
||||
// user ratings
|
||||
var userRatingEnabled = document.getElementById('filter_panel_userrating_enabled');
|
||||
|
||||
var minUserRating = -1;
|
||||
var minUserRatingInput = document.getElementById('filter_panel_userrating_min');
|
||||
if (minUserRatingInput.value) {
|
||||
minUserRating = minUserRatingInput.value;
|
||||
userRatingEnabled.checked = true;
|
||||
}
|
||||
setCookie(minUserRatingInput.id, minUserRatingInput.value);
|
||||
|
||||
@@ -314,15 +276,51 @@ function executeFilter1_1() {
|
||||
var maxUserRatingInput = document.getElementById('filter_panel_userrating_max');
|
||||
if (maxUserRatingInput.value) {
|
||||
maxUserRating = maxUserRatingInput.value;
|
||||
userRatingEnabled.checked = true;
|
||||
}
|
||||
setCookie(maxUserRatingInput.id, maxUserRatingInput.value);
|
||||
|
||||
if (minUserRating == -1 && maxUserRating == -1) {
|
||||
userRatingEnabled.checked = false;
|
||||
}
|
||||
|
||||
if (userRatingEnabled.checked == false) {
|
||||
setCookie("filter_panel_userrating_enabled", false);
|
||||
|
||||
minUserRating = -1;
|
||||
minUserRatingInput.value = "";
|
||||
setCookie(minUserRatingInput.id, minUserRatingInput.value);
|
||||
maxUserRating = -1;
|
||||
maxUserRatingInput.value = "";
|
||||
setCookie(maxUserRatingInput.id, maxUserRatingInput.value);
|
||||
} else {
|
||||
setCookie("filter_panel_userrating_enabled", true);
|
||||
}
|
||||
|
||||
// get order by
|
||||
var orderBy = document.getElementById('games_library_orderby_select').value;
|
||||
setCookie('games_library_orderby_select', orderBy);
|
||||
var orderByDirection = true;
|
||||
var orderByDirectionSelect = document.getElementById('games_library_orderby_direction_select').value;
|
||||
if (orderByDirectionSelect == "Ascending") {
|
||||
orderByDirection = true;
|
||||
} else {
|
||||
orderByDirection = false;
|
||||
}
|
||||
setCookie('games_library_orderby_direction_select', orderByDirectionSelect);
|
||||
|
||||
// build filter model
|
||||
var ratingAgeGroups = GetFilterQuery1_1('agegroupings');
|
||||
var ratingIncludeUnrated = false;
|
||||
if (ratingAgeGroups.includes("0")) {
|
||||
ratingIncludeUnrated = true;
|
||||
}
|
||||
|
||||
var model = {
|
||||
"Name": document.getElementById('filter_panel_search').value,
|
||||
"Platform": GetFilterQuery1_1('platform'),
|
||||
"Genre": GetFilterQuery1_1('genre'),
|
||||
"GameMode": GetFilterQuery1_1('gamemmode'),
|
||||
"GameMode": GetFilterQuery1_1('gamemode'),
|
||||
"PlayerPerspective": GetFilterQuery1_1('playerperspective'),
|
||||
"Theme": GetFilterQuery1_1('theme'),
|
||||
"GameRating": {
|
||||
@@ -330,31 +328,24 @@ function executeFilter1_1() {
|
||||
"MinimumRatingCount": -1,
|
||||
"MaximumRating": maxUserRating,
|
||||
"MaximumRatingCount": -1,
|
||||
"IncludeUnrated": true
|
||||
"IncludeUnrated": !userRatingEnabled
|
||||
},
|
||||
"GameAgeRating": {
|
||||
"AgeGroupings": [
|
||||
"Child",
|
||||
"Teen",
|
||||
"Mature",
|
||||
"Adult"
|
||||
],
|
||||
"IncludeUnrated": true
|
||||
"AgeGroupings": ratingAgeGroups,
|
||||
"IncludeUnrated": ratingIncludeUnrated
|
||||
},
|
||||
"Sorting": {
|
||||
"SortBy": "NameThe",
|
||||
"SortAscenting": true
|
||||
"SortBy": orderBy,
|
||||
"SortAscending": orderByDirection
|
||||
}
|
||||
};
|
||||
|
||||
console.log('Search model = ' + JSON.stringify(model));
|
||||
|
||||
ajaxCall(
|
||||
'/api/v1.1/Games',
|
||||
'/api/v1.1/Games?pageNumber=' + pageNumber + '&pageSize=' + pageSize,
|
||||
'POST',
|
||||
function (result) {
|
||||
var gameElement = document.getElementById('games_library');
|
||||
formatGamesPanel(gameElement, result);
|
||||
formatGamesPanel(gameElement, result, pageNumber, pageSize);
|
||||
},
|
||||
function (error) {
|
||||
console.log('An error occurred: ' + JSON.stringify(error));
|
||||
|
@@ -1,7 +1,50 @@
|
||||
function formatGamesPanel(targetElement, result) {
|
||||
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)",
|
||||
"CLASS_IND": "Brazilian advisory rating system",
|
||||
"ACB": "Australian Classification Board (ACB)"
|
||||
};
|
||||
|
||||
function formatGamesPanel(targetElement, result, pageNumber, pageSize) {
|
||||
console.log("Displaying page: " + pageNumber);
|
||||
console.log("Page size: " + pageSize);
|
||||
|
||||
var pageMode = GetPreference('LibraryPagination', 'infinite');
|
||||
|
||||
if (pageNumber == 1 || pageMode == 'paged') {
|
||||
targetElement.innerHTML = '';
|
||||
for (var i = 0; i < result.length; i++) {
|
||||
var game = renderGameIcon(result[i], true, false);
|
||||
}
|
||||
|
||||
var pagerCheck = document.getElementById('games_library_pagerstore');
|
||||
if (pageNumber == 1) {
|
||||
pagerCheck.innerHTML = "0";
|
||||
}
|
||||
|
||||
if (pageNumber > Number(pagerCheck.innerHTML) || pageMode == 'paged') {
|
||||
pagerCheck.innerHTML = pageNumber;
|
||||
|
||||
document.getElementById('games_library_recordcount').innerHTML = result.count + ' games';
|
||||
|
||||
var 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);
|
||||
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);
|
||||
targetElement.appendChild(game);
|
||||
}
|
||||
|
||||
@@ -10,22 +53,178 @@
|
||||
effect: 'fadeIn',
|
||||
visibleOnly: true
|
||||
});
|
||||
|
||||
var pager = document.getElementById('games_pager');
|
||||
pager.style.display = 'none';
|
||||
|
||||
switch(pageMode) {
|
||||
case 'infinite':
|
||||
if (result.games.length == pageSize) {
|
||||
var loadPageButton = document.createElement("div");
|
||||
loadPageButton.id = 'games_library_loadmore';
|
||||
loadPageButton.innerHTML = 'Load More';
|
||||
loadPageButton.setAttribute('onclick', 'executeFilter1_1(' + (pageNumber + 1) + ', ' + pageSize + ');');
|
||||
loadPageButton.setAttribute('data-pagenumber', Number(pageNumber + 1));
|
||||
loadPageButton.setAttribute('data-pagesize', pageSize);
|
||||
targetElement.appendChild(loadPageButton);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'paged':
|
||||
if (result.count > pageSize) {
|
||||
// add some padding to the bottom of the games list
|
||||
var loadPageButton = document.createElement("div");
|
||||
loadPageButton.id = 'games_library_padding';
|
||||
targetElement.appendChild(loadPageButton);
|
||||
|
||||
var pageCount = Math.ceil(result.count / pageSize);
|
||||
|
||||
// add previous page button
|
||||
var prevPage = document.createElement('span');
|
||||
prevPage.innerHTML = '<';
|
||||
if (pageNumber == 1) {
|
||||
prevPage.className = 'games_pager_number_disabled';
|
||||
} else {
|
||||
prevPage.className = 'games_pager_number';
|
||||
prevPage.setAttribute('onclick', 'executeFilter1_1(' + (pageNumber - 1) + ');');
|
||||
}
|
||||
|
||||
function renderGameIcon(gameObject, showTitle, showRatings) {
|
||||
// add page numbers
|
||||
var pageNumbers = document.createElement('span');
|
||||
for (var i = 1; i <= pageCount; i++) {
|
||||
var pageNum = document.createElement('span');
|
||||
if (Number(pagerCheck.innerHTML) == i) {
|
||||
pageNum.className = 'games_pager_number_disabled';
|
||||
} else {
|
||||
pageNum.className = 'games_pager_number';
|
||||
pageNum.setAttribute('onclick', 'executeFilter1_1(' + i + ');');
|
||||
}
|
||||
pageNum.innerHTML = i;
|
||||
pageNumbers.appendChild(pageNum);
|
||||
}
|
||||
|
||||
// add next page button
|
||||
var nextPage = document.createElement('span');
|
||||
nextPage.innerHTML = '>';
|
||||
if (pageNumber == pageCount) {
|
||||
nextPage.className = 'games_pager_number_disabled';
|
||||
} else {
|
||||
nextPage.className = 'games_pager_number';
|
||||
nextPage.setAttribute('onclick', 'executeFilter1_1(' + (pageNumber + 1) + ');');
|
||||
}
|
||||
|
||||
pager.innerHTML = '';
|
||||
pager.appendChild(prevPage);
|
||||
pager.appendChild(pageNumbers);
|
||||
pager.appendChild(nextPage);
|
||||
|
||||
pager.style.display = '';
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function isScrolledIntoView(elem) {
|
||||
if (elem) {
|
||||
var docViewTop = $(window).scrollTop();
|
||||
var docViewBottom = docViewTop + $(window).height();
|
||||
|
||||
var elemTop = $(elem).offset().top;
|
||||
var elemBottom = elemTop + $(elem).height();
|
||||
|
||||
return ((elemBottom <= docViewBottom) && (elemTop >= docViewTop));
|
||||
}
|
||||
}
|
||||
|
||||
function IsInView() {
|
||||
var loadElement = document.getElementById('games_library_loadmore');
|
||||
if (loadElement) {
|
||||
if (isScrolledIntoView(loadElement)) {
|
||||
var pageNumber = Number(document.getElementById('games_library_loadmore').getAttribute('data-pagenumber'));
|
||||
var pageSize = document.getElementById('games_library_loadmore').getAttribute('data-pagesize');
|
||||
executeFilter1_1(pageNumber, pageSize);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$(window).scroll(IsInView);
|
||||
|
||||
function renderGameIcon(gameObject, showTitle, showRatings, showClassification, classificationDisplayOrder, useSmallCover) {
|
||||
var gameBox = document.createElement('div');
|
||||
gameBox.id = "game_tile_" + gameObject.id;
|
||||
if (useSmallCover == true) {
|
||||
gameBox.className = 'game_tile game_tile_small';
|
||||
} else {
|
||||
gameBox.className = 'game_tile';
|
||||
}
|
||||
gameBox.setAttribute('onclick', 'window.location.href = "/index.html?page=game&id=' + gameObject.id + '";');
|
||||
|
||||
var gameImageBox = document.createElement('div');
|
||||
gameImageBox.className = 'game_tile_box';
|
||||
|
||||
var gameImage = document.createElement('img');
|
||||
if (useSmallCover == true) {
|
||||
gameImage.className = 'game_tile_image game_tile_image_small lazy';
|
||||
} else {
|
||||
gameImage.className = 'game_tile_image lazy';
|
||||
}
|
||||
gameImage.src = '/images/unknowngame.png';
|
||||
if (gameObject.cover) {
|
||||
gameImage.setAttribute('data-src', '/api/v1.1/Games/' + gameObject.id + '/cover/image');
|
||||
} else {
|
||||
gameImage.src = '/images/unknowngame.png';
|
||||
gameImage.className = 'game_tile_image unknown';
|
||||
}
|
||||
gameBox.appendChild(gameImage);
|
||||
gameImageBox.appendChild(gameImage);
|
||||
|
||||
var classificationPath = '';
|
||||
var displayClassification = false;
|
||||
var shownClassificationBoard = '';
|
||||
if (showClassification == true) {
|
||||
for (var b = 0; b < classificationDisplayOrder.length; b++) {
|
||||
if (shownClassificationBoard == '') {
|
||||
for (var c = 0; c < gameObject.ageRatings.length; c++) {
|
||||
if (gameObject.ageRatings[c].category == classificationDisplayOrder[b]) {
|
||||
shownClassificationBoard = classificationDisplayOrder[b];
|
||||
displayClassification = true;
|
||||
classificationPath = '/api/v1.1/Ratings/Images/' + classificationDisplayOrder[b] + '/' + getKeyByValue(AgeRatingStrings, gameObject.ageRatings[c].rating) + '/image.svg';
|
||||
}
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (gameObject.totalRating || displayClassification == true) {
|
||||
var gameImageRatingBanner = document.createElement('div');
|
||||
gameImageRatingBanner.className = 'game_tile_box_ratingbanner';
|
||||
|
||||
if (showRatings == true || displayClassification == true) {
|
||||
if (showRatings == true) {
|
||||
if (gameObject.totalRating) {
|
||||
var 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');
|
||||
gameImageRatingBannerValue.innerHTML = Math.floor(gameObject.totalRating) + '% / ' + gameObject.totalRatingCount;
|
||||
gameImageRatingBanner.appendChild(gameImageRatingBannerValue);
|
||||
}
|
||||
}
|
||||
|
||||
gameImageBox.appendChild(gameImageRatingBanner);
|
||||
|
||||
if (displayClassification == true) {
|
||||
var gameImageClassificationLogo = document.createElement('img');
|
||||
gameImageClassificationLogo.src = classificationPath;
|
||||
gameImageClassificationLogo.className = 'rating_image_overlay';
|
||||
gameImageBox.appendChild(gameImageClassificationLogo);
|
||||
}
|
||||
}
|
||||
}
|
||||
gameBox.appendChild(gameImageBox);
|
||||
|
||||
if (showTitle == true) {
|
||||
var gameBoxTitle = document.createElement('div');
|
||||
@@ -34,19 +233,5 @@ function renderGameIcon(gameObject, showTitle, showRatings) {
|
||||
gameBox.appendChild(gameBoxTitle);
|
||||
}
|
||||
|
||||
if (showRatings == true) {
|
||||
if (gameObject.ageRatings) {
|
||||
var ratingsSection = document.createElement('div');
|
||||
ratingsSection.id = 'ratings_section';
|
||||
for (var i = 0; i < gameObject.ageRatings.ids.length; i++) {
|
||||
var ratingImage = document.createElement('img');
|
||||
ratingImage.src = '/api/v1.1/Games/' + gameObject.id + '/agerating/' + gameObject.ageRatings.ids[i] + '/image';
|
||||
ratingImage.className = 'rating_image_mini';
|
||||
ratingsSection.appendChild(ratingImage);
|
||||
}
|
||||
gameBox.appendChild(ratingsSection);
|
||||
}
|
||||
}
|
||||
|
||||
return gameBox;
|
||||
}
|
@@ -1,4 +1,8 @@
|
||||
function ajaxCall(endpoint, method, successFunction, errorFunction, body) {
|
||||
var locale = window.navigator.userLanguage || window.navigator.language;
|
||||
console.log(locale);
|
||||
moment.locale(locale);
|
||||
|
||||
function ajaxCall(endpoint, method, successFunction, errorFunction, body) {
|
||||
$.ajax({
|
||||
|
||||
// Our sample url to make request
|
||||
@@ -410,3 +414,59 @@ function GetTaskFriendlyName(TaskName, options) {
|
||||
return TaskName;
|
||||
}
|
||||
}
|
||||
|
||||
function getKeyByValue(object, value) {
|
||||
return Object.keys(object).find(key => object[key] === value);
|
||||
}
|
||||
|
||||
function GetPreference(Setting, DefaultValue) {
|
||||
if (userProfile.userPreferences) {
|
||||
for (var i = 0; i < userProfile.userPreferences.length; i++) {
|
||||
if (userProfile.userPreferences[i].setting == Setting) {
|
||||
return userProfile.userPreferences[i].value.toString();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SetPreference(Setting, DefaultValue);
|
||||
|
||||
return DefaultValue;
|
||||
}
|
||||
|
||||
function SetPreference(Setting, Value) {
|
||||
var model = [
|
||||
{
|
||||
"setting": Setting,
|
||||
"value": Value.toString()
|
||||
}
|
||||
];
|
||||
|
||||
ajaxCall(
|
||||
'/api/v1.1/Account/Preferences',
|
||||
'POST',
|
||||
function(result) {
|
||||
SetPreference_Local(Setting, Value);
|
||||
},
|
||||
function(error) {
|
||||
SetPreference_Local(Setting, Value);
|
||||
},
|
||||
JSON.stringify(model)
|
||||
);
|
||||
}
|
||||
|
||||
function SetPreference_Local(Setting, Value) {
|
||||
if (userProfile.userPreferences) {
|
||||
var prefFound = false;
|
||||
for (var i = 0; i < userProfile.userPreferences.length; i++) {
|
||||
if (userProfile.userPreferences[i].setting == Setting) {
|
||||
userProfile.userPreferences[i].value = Value;
|
||||
prefFound = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (prefFound == false) {
|
||||
userProfile.userPreferences.push(model);
|
||||
}
|
||||
}
|
||||
}
|
2
gaseous-server/wwwroot/scripts/moment-with-locales.min.js
vendored
Normal file
2
gaseous-server/wwwroot/scripts/moment-with-locales.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
@@ -187,12 +187,28 @@ h3 {
|
||||
z-index: -100;
|
||||
}
|
||||
|
||||
#games_filter_scroller {
|
||||
position: fixed;
|
||||
width: 210px;
|
||||
overflow-y: hidden;
|
||||
overflow-x: hidden;
|
||||
overscroll-behavior: contain;
|
||||
top: 60px;
|
||||
bottom: 20px;
|
||||
/* margin-right: 10px; */
|
||||
}
|
||||
|
||||
#games_filter {
|
||||
|
||||
width: 200px;
|
||||
border-style: solid;
|
||||
/* border-style: solid;
|
||||
border-width: 1px;
|
||||
border-color: #2b2b2b;
|
||||
margin-right: 10px;
|
||||
border-color: #2b2b2b; */
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
#games_filter_scroller:hover {
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.filter_header {
|
||||
@@ -266,8 +282,51 @@ input[id='filter_panel_userrating_max'] {
|
||||
}
|
||||
|
||||
#games_home {
|
||||
display: flex;
|
||||
display: absolute;
|
||||
margin-left: 210px;
|
||||
margin-top: 20px;
|
||||
right: 20px;
|
||||
}
|
||||
|
||||
#games_home_box {
|
||||
display: relative;
|
||||
}
|
||||
|
||||
#games_pager {
|
||||
position: fixed;
|
||||
bottom: 50px;
|
||||
left: 50%;
|
||||
transform: translate(-50%, 0);
|
||||
border-style: solid;
|
||||
border-width: 1px;
|
||||
border-radius: 7px;
|
||||
border-color: rgba(0, 22, 56, 0.8);
|
||||
padding-left: 20px;
|
||||
padding-right: 20px;
|
||||
padding-top: 15px;
|
||||
padding-bottom: 15px;
|
||||
font-size: 18px;
|
||||
font-family: Commodore64;
|
||||
background-color: rgba(0, 22, 56, 0.8);
|
||||
backdrop-filter: blur(8px);
|
||||
-webkit-backdrop-filter: blur(8px);
|
||||
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);
|
||||
}
|
||||
|
||||
.games_pager_number {
|
||||
padding: 5px;
|
||||
}
|
||||
|
||||
.games_pager_number:hover {
|
||||
background-color: blue;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.games_pager_number_disabled {
|
||||
padding: 5px;
|
||||
color: grey;
|
||||
}
|
||||
|
||||
.filter_panel_item {
|
||||
@@ -285,18 +344,52 @@ input[id='filter_panel_userrating_max'] {
|
||||
margin-right: 15px;
|
||||
}
|
||||
|
||||
#games_library {
|
||||
width: 90%;
|
||||
#games_library_controls {
|
||||
display: absolute;
|
||||
border-style: solid;
|
||||
border-width: 1px;
|
||||
border-color: #2b2b2b;
|
||||
border-radius: 5px;
|
||||
margin-bottom: 10px;
|
||||
padding: 10px;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.games_library_controlblock {
|
||||
margin-left: 20px;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
#games_library {
|
||||
display: block;
|
||||
/* width: 90%; */
|
||||
/* border-style: solid;
|
||||
border-width: 1px;
|
||||
border-color: #2b2b2b; */
|
||||
/* padding: 10px; */
|
||||
}
|
||||
|
||||
#games_library_loadmore {
|
||||
display: block;
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
padding-top: 10px;
|
||||
height: 50px;
|
||||
}
|
||||
|
||||
#games_library_padding {
|
||||
display: block;
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
padding-top: 10px;
|
||||
height: 100px;
|
||||
}
|
||||
|
||||
.game_tile {
|
||||
padding: 5px;
|
||||
display: inline-block;
|
||||
width: 220px;
|
||||
min-height: 200px;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
text-align: center;
|
||||
@@ -308,6 +401,12 @@ input[id='filter_panel_userrating_max'] {
|
||||
border: 1px solid transparent;
|
||||
}
|
||||
|
||||
.game_tile_small {
|
||||
min-height: 50px;
|
||||
min-width: 50px;
|
||||
width: 105px;
|
||||
}
|
||||
|
||||
.game_tile:hover {
|
||||
cursor: pointer;
|
||||
text-decoration: underline;
|
||||
@@ -318,19 +417,57 @@ input[id='filter_panel_userrating_max'] {
|
||||
border: 1px solid #2b2b2b;
|
||||
}
|
||||
|
||||
.game_tile_image {
|
||||
.game_tile_small: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_box {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
max-width: 200px;
|
||||
max-height: 200px;
|
||||
}
|
||||
|
||||
.game_tile_box_ratingbanner {
|
||||
position: absolute;
|
||||
bottom: 0px;
|
||||
left: 0px;
|
||||
right: 0px;
|
||||
text-align: right;
|
||||
padding-top: 2px;
|
||||
padding-bottom: 2px;
|
||||
padding-left: 5px;
|
||||
padding-right: 5px;
|
||||
height: 19px;
|
||||
background-color: rgba(0, 22, 56, 0.8);
|
||||
backdrop-filter: blur(8px);
|
||||
-webkit-backdrop-filter: blur(8px);
|
||||
}
|
||||
|
||||
.game_tile_image {
|
||||
max-width: 200px;
|
||||
min-width: 150px;
|
||||
max-height: 200px;
|
||||
min-height: 200px;
|
||||
background-color: transparent;
|
||||
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);
|
||||
}
|
||||
|
||||
.game_tile_image, .unknown {
|
||||
background-color: white;
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
.game_tile_image_small {
|
||||
min-width: 50px;
|
||||
min-height: 50px;
|
||||
max-width: 100px;
|
||||
max-height: 100px;
|
||||
}
|
||||
@@ -408,10 +545,18 @@ input[id='filter_panel_userrating_max'] {
|
||||
}
|
||||
|
||||
.rating_image_mini {
|
||||
display: inline-block;
|
||||
max-width: 32px;
|
||||
max-height: 32px;
|
||||
margin-right: 10px;
|
||||
margin-right: 5px;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.rating_image_overlay {
|
||||
position: absolute;
|
||||
max-width: 32px;
|
||||
max-height: 32px;
|
||||
left: 5px;
|
||||
bottom: 5px;
|
||||
}
|
||||
|
||||
#gamescreenshots {
|
||||
@@ -947,7 +1092,7 @@ button:disabled {
|
||||
top: 0px;
|
||||
right: 0px;
|
||||
text-align: center;
|
||||
font-size: 8px;
|
||||
font-size: 10px;
|
||||
}
|
||||
|
||||
.tagBoxItem {
|
||||
|
Reference in New Issue
Block a user