Added support for custom user avatars
* Added support for custom user avatars
This commit is contained in:
@@ -12,5 +12,6 @@ namespace Authentication
|
|||||||
{
|
{
|
||||||
public SecurityProfileViewModel SecurityProfile { get; set; }
|
public SecurityProfileViewModel SecurityProfile { get; set; }
|
||||||
public List<UserPreferenceViewModel> UserPreferences { get; set; }
|
public List<UserPreferenceViewModel> UserPreferences { get; set; }
|
||||||
|
public Guid Avatar { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -75,7 +75,7 @@ namespace Authentication
|
|||||||
public TUser GetUserById(string userId)
|
public TUser GetUserById(string userId)
|
||||||
{
|
{
|
||||||
TUser user = null;
|
TUser user = null;
|
||||||
string commandText = "Select * from Users where Id = @id";
|
string commandText = "Select * from Users LEFT JOIN (SELECT UserId, Id AS AvatarId FROM UserAvatars) UserAvatars ON users.Id = UserAvatars.UserId where Id = @id";
|
||||||
Dictionary<string, object> parameters = new Dictionary<string, object>() { { "@id", userId } };
|
Dictionary<string, object> parameters = new Dictionary<string, object>() { { "@id", userId } };
|
||||||
|
|
||||||
var rows = _database.ExecuteCMDDict(commandText, parameters);
|
var rows = _database.ExecuteCMDDict(commandText, parameters);
|
||||||
@@ -100,6 +100,7 @@ namespace Authentication
|
|||||||
user.TwoFactorEnabled = row["TwoFactorEnabled"] == "1" ? true:false;
|
user.TwoFactorEnabled = row["TwoFactorEnabled"] == "1" ? true:false;
|
||||||
user.SecurityProfile = GetSecurityProfile(user);
|
user.SecurityProfile = GetSecurityProfile(user);
|
||||||
user.UserPreferences = GetPreferences(user);
|
user.UserPreferences = GetPreferences(user);
|
||||||
|
user.Avatar = string.IsNullOrEmpty((string?)row["AvatarId"]) ? Guid.Empty : Guid.Parse((string?)row["AvatarId"]);
|
||||||
}
|
}
|
||||||
|
|
||||||
return user;
|
return user;
|
||||||
@@ -113,7 +114,7 @@ namespace Authentication
|
|||||||
public List<TUser> GetUserByName(string normalizedUserName)
|
public List<TUser> GetUserByName(string normalizedUserName)
|
||||||
{
|
{
|
||||||
List<TUser> users = new List<TUser>();
|
List<TUser> users = new List<TUser>();
|
||||||
string commandText = "Select * from Users where NormalizedEmail = @name";
|
string commandText = "Select * from Users LEFT JOIN (SELECT UserId, Id AS AvatarId FROM UserAvatars) UserAvatars ON users.Id = UserAvatars.UserId where NormalizedEmail = @name";
|
||||||
Dictionary<string, object> parameters = new Dictionary<string, object>() { { "@name", normalizedUserName } };
|
Dictionary<string, object> parameters = new Dictionary<string, object>() { { "@name", normalizedUserName } };
|
||||||
|
|
||||||
var rows = _database.ExecuteCMDDict(commandText, parameters);
|
var rows = _database.ExecuteCMDDict(commandText, parameters);
|
||||||
@@ -137,6 +138,7 @@ namespace Authentication
|
|||||||
user.TwoFactorEnabled = row["TwoFactorEnabled"] == "1" ? true:false;
|
user.TwoFactorEnabled = row["TwoFactorEnabled"] == "1" ? true:false;
|
||||||
user.SecurityProfile = GetSecurityProfile(user);
|
user.SecurityProfile = GetSecurityProfile(user);
|
||||||
user.UserPreferences = GetPreferences(user);
|
user.UserPreferences = GetPreferences(user);
|
||||||
|
user.Avatar = string.IsNullOrEmpty((string?)row["AvatarId"]) ? Guid.Empty : Guid.Parse((string?)row["AvatarId"]);
|
||||||
users.Add(user);
|
users.Add(user);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -146,7 +148,7 @@ namespace Authentication
|
|||||||
public List<TUser> GetUsers()
|
public List<TUser> GetUsers()
|
||||||
{
|
{
|
||||||
List<TUser> users = new List<TUser>();
|
List<TUser> users = new List<TUser>();
|
||||||
string commandText = "Select * from Users order by NormalizedUserName";
|
string commandText = "Select * from Users LEFT JOIN (SELECT UserId, Id AS AvatarId FROM UserAvatars) UserAvatars ON users.Id = UserAvatars.UserId order by NormalizedUserName";
|
||||||
|
|
||||||
var rows = _database.ExecuteCMDDict(commandText);
|
var rows = _database.ExecuteCMDDict(commandText);
|
||||||
foreach(Dictionary<string, object> row in rows)
|
foreach(Dictionary<string, object> row in rows)
|
||||||
@@ -169,6 +171,7 @@ namespace Authentication
|
|||||||
user.TwoFactorEnabled = row["TwoFactorEnabled"] == "1" ? true:false;
|
user.TwoFactorEnabled = row["TwoFactorEnabled"] == "1" ? true:false;
|
||||||
user.SecurityProfile = GetSecurityProfile(user);
|
user.SecurityProfile = GetSecurityProfile(user);
|
||||||
user.UserPreferences = GetPreferences(user);
|
user.UserPreferences = GetPreferences(user);
|
||||||
|
user.Avatar = string.IsNullOrEmpty((string?)row["AvatarId"]) ? Guid.Empty : Guid.Parse((string?)row["AvatarId"]);
|
||||||
users.Add(user);
|
users.Add(user);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -437,5 +440,30 @@ namespace Authentication
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Guid SetAvatar(TUser user, byte[] bytes)
|
||||||
|
{
|
||||||
|
Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
||||||
|
string sql;
|
||||||
|
Dictionary<string, object> dbDict = new Dictionary<string, object>
|
||||||
|
{
|
||||||
|
{ "userid", user.Id }
|
||||||
|
};
|
||||||
|
|
||||||
|
if (bytes.Length == 0)
|
||||||
|
{
|
||||||
|
sql = "DELETE FROM UserAvatars WHERE UserId = @userid";
|
||||||
|
db.ExecuteNonQuery(sql, dbDict);
|
||||||
|
return Guid.Empty;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sql = "DELETE FROM UserAvatars WHERE UserId = @userid; INSERT INTO UserAvatars (UserId, Id, Avatar) VALUES (@userid, @id, @avatar);";
|
||||||
|
dbDict.Add("id", Guid.NewGuid());
|
||||||
|
dbDict.Add("avatar", bytes);
|
||||||
|
db.ExecuteNonQuery(sql, dbDict);
|
||||||
|
return (Guid)dbDict["id"];
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -8,6 +8,7 @@ namespace Authentication
|
|||||||
public List<String> Roles { get; set; }
|
public List<String> Roles { get; set; }
|
||||||
public SecurityProfileViewModel SecurityProfile { get; set; }
|
public SecurityProfileViewModel SecurityProfile { get; set; }
|
||||||
public List<UserPreferenceViewModel> UserPreferences { get; set; }
|
public List<UserPreferenceViewModel> UserPreferences { get; set; }
|
||||||
|
public Guid Avatar { get; set; }
|
||||||
public string HighestRole {
|
public string HighestRole {
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
|
@@ -8,6 +8,7 @@ namespace Authentication
|
|||||||
public DateTimeOffset? LockoutEnd { get; set; }
|
public DateTimeOffset? LockoutEnd { get; set; }
|
||||||
public List<string> Roles { get; set; }
|
public List<string> Roles { get; set; }
|
||||||
public SecurityProfileViewModel SecurityProfile { get; set; }
|
public SecurityProfileViewModel SecurityProfile { get; set; }
|
||||||
|
public Guid Avatar { get; set; }
|
||||||
public string HighestRole {
|
public string HighestRole {
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
|
@@ -9,6 +9,7 @@ using Microsoft.AspNetCore.Identity.UI.Services;
|
|||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Microsoft.AspNetCore.Mvc.Rendering;
|
using Microsoft.AspNetCore.Mvc.Rendering;
|
||||||
using Asp.Versioning;
|
using Asp.Versioning;
|
||||||
|
using IGDB;
|
||||||
|
|
||||||
namespace gaseous_server.Controllers
|
namespace gaseous_server.Controllers
|
||||||
{
|
{
|
||||||
@@ -98,6 +99,7 @@ namespace gaseous_server.Controllers
|
|||||||
profile.Roles = new List<string>(await _userManager.GetRolesAsync(user));
|
profile.Roles = new List<string>(await _userManager.GetRolesAsync(user));
|
||||||
profile.SecurityProfile = user.SecurityProfile;
|
profile.SecurityProfile = user.SecurityProfile;
|
||||||
profile.UserPreferences = user.UserPreferences;
|
profile.UserPreferences = user.UserPreferences;
|
||||||
|
profile.Avatar = user.Avatar;
|
||||||
profile.Roles.Sort();
|
profile.Roles.Sort();
|
||||||
|
|
||||||
return Ok(profile);
|
return Ok(profile);
|
||||||
@@ -186,6 +188,7 @@ namespace gaseous_server.Controllers
|
|||||||
user.LockoutEnabled = rawUser.LockoutEnabled;
|
user.LockoutEnabled = rawUser.LockoutEnabled;
|
||||||
user.LockoutEnd = rawUser.LockoutEnd;
|
user.LockoutEnd = rawUser.LockoutEnd;
|
||||||
user.SecurityProfile = rawUser.SecurityProfile;
|
user.SecurityProfile = rawUser.SecurityProfile;
|
||||||
|
user.Avatar = rawUser.Avatar;
|
||||||
|
|
||||||
// get roles
|
// get roles
|
||||||
ApplicationUser? aUser = await _userManager.FindByIdAsync(rawUser.Id);
|
ApplicationUser? aUser = await _userManager.FindByIdAsync(rawUser.Id);
|
||||||
@@ -414,5 +417,115 @@ namespace gaseous_server.Controllers
|
|||||||
return Ok();
|
return Ok();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[HttpPost]
|
||||||
|
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||||
|
[RequestSizeLimit(long.MaxValue)]
|
||||||
|
[Consumes("multipart/form-data")]
|
||||||
|
[DisableRequestSizeLimit, RequestFormLimits(MultipartBodyLengthLimit = long.MaxValue, ValueLengthLimit = int.MaxValue)]
|
||||||
|
[Route("Avatar")]
|
||||||
|
public async Task<IActionResult> UploadAvatar(IFormFile file)
|
||||||
|
{
|
||||||
|
ApplicationUser? user = await _userManager.GetUserAsync(User);
|
||||||
|
if (user == null)
|
||||||
|
{
|
||||||
|
return Unauthorized();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Guid avatarId = Guid.Empty;
|
||||||
|
|
||||||
|
if (file.Length > 0)
|
||||||
|
{
|
||||||
|
using (var ms = new MemoryStream())
|
||||||
|
{
|
||||||
|
file.CopyTo(ms);
|
||||||
|
byte[] fileBytes = ms.ToArray();
|
||||||
|
byte[] targetBytes;
|
||||||
|
|
||||||
|
using (var image = new ImageMagick.MagickImage(fileBytes))
|
||||||
|
{
|
||||||
|
ImageMagick.MagickGeometry size = new ImageMagick.MagickGeometry(256, 256);
|
||||||
|
|
||||||
|
// This will resize the image to a fixed size without maintaining the aspect ratio.
|
||||||
|
// Normally an image will be resized to fit inside the specified size.
|
||||||
|
size.IgnoreAspectRatio = true;
|
||||||
|
|
||||||
|
image.Resize(size);
|
||||||
|
var newMs = new MemoryStream();
|
||||||
|
image.Resize(size);
|
||||||
|
image.Strip();
|
||||||
|
image.Write(newMs, ImageMagick.MagickFormat.Jpg);
|
||||||
|
|
||||||
|
targetBytes = newMs.ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
||||||
|
UserTable<ApplicationUser> userTable = new UserTable<ApplicationUser>(db);
|
||||||
|
avatarId = userTable.SetAvatar(user, targetBytes);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Ok(avatarId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpGet]
|
||||||
|
[Route("Avatar/{id}.jpg")]
|
||||||
|
[ProducesResponseType(typeof(FileStreamResult), StatusCodes.Status200OK)]
|
||||||
|
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
||||||
|
public ActionResult GetAvatar(Guid id)
|
||||||
|
{
|
||||||
|
if (id == Guid.Empty)
|
||||||
|
{
|
||||||
|
return NotFound();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
||||||
|
string sql = "SELECT * FROM UserAvatars WHERE Id = @id";
|
||||||
|
Dictionary<string, object> dbDict = new Dictionary<string, object>{
|
||||||
|
{ "id", id }
|
||||||
|
};
|
||||||
|
|
||||||
|
DataTable data = db.ExecuteCMD(sql, dbDict);
|
||||||
|
|
||||||
|
if (data.Rows.Count > 0)
|
||||||
|
{
|
||||||
|
string filename = id.ToString() + ".jpg";
|
||||||
|
byte[] filedata = (byte[])data.Rows[0]["Avatar"];
|
||||||
|
string contentType = "image/jpg";
|
||||||
|
|
||||||
|
var cd = new System.Net.Mime.ContentDisposition
|
||||||
|
{
|
||||||
|
FileName = filename,
|
||||||
|
Inline = true,
|
||||||
|
};
|
||||||
|
|
||||||
|
Response.Headers.Add("Content-Disposition", cd.ToString());
|
||||||
|
Response.Headers.Add("Cache-Control", "public, max-age=604800");
|
||||||
|
|
||||||
|
return File(filedata, contentType);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return NotFound();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpDelete]
|
||||||
|
[Route("Avatar/{id}.jpg")]
|
||||||
|
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||||
|
public async Task<ActionResult> DeleteAvatarAsync()
|
||||||
|
{
|
||||||
|
ApplicationUser? user = await _userManager.GetUserAsync(User);
|
||||||
|
|
||||||
|
Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
||||||
|
UserTable<ApplicationUser> userTable = new UserTable<ApplicationUser>(db);
|
||||||
|
userTable.SetAvatar(user, new byte[0]);
|
||||||
|
|
||||||
|
return Ok();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
11
gaseous-server/Support/Database/MySQL/gaseous-1019.sql
Normal file
11
gaseous-server/Support/Database/MySQL/gaseous-1019.sql
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
CREATE TABLE `UserAvatars` (
|
||||||
|
`UserId` VARCHAR(128) NOT NULL,
|
||||||
|
`Id` VARCHAR(45) NOT NULL,
|
||||||
|
`Avatar` LONGBLOB NULL,
|
||||||
|
PRIMARY KEY (`UserId`),
|
||||||
|
INDEX `idx_AvatarId` (`Id` ASC) VISIBLE,
|
||||||
|
CONSTRAINT `ApplicationUser_Avatar`
|
||||||
|
FOREIGN KEY (`UserId`)
|
||||||
|
REFERENCES `Users` (`Id`)
|
||||||
|
ON DELETE CASCADE
|
||||||
|
ON UPDATE NO ACTION);
|
@@ -1590,18 +1590,18 @@
|
|||||||
"retroPieDirectoryName": "mastersystem",
|
"retroPieDirectoryName": "mastersystem",
|
||||||
"webEmulator": {
|
"webEmulator": {
|
||||||
"type": "EmulatorJS",
|
"type": "EmulatorJS",
|
||||||
"core": "segaMS",
|
"core": "picodrive",
|
||||||
"availableWebEmulators": [
|
"availableWebEmulators": [
|
||||||
{
|
{
|
||||||
"emulatorType": "EmulatorJS",
|
"emulatorType": "EmulatorJS",
|
||||||
"availableWebEmulatorCores": [
|
"availableWebEmulatorCores": [
|
||||||
{
|
{
|
||||||
"core": "segaMS",
|
"core": "picodrive",
|
||||||
"alternateCoreName": "picodrive",
|
|
||||||
"default": true
|
"default": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"core": "genesis_plus_gx"
|
"core": "segaMS",
|
||||||
|
"alternateCoreName": "genesis_plus_gx"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
@@ -130,6 +130,8 @@
|
|||||||
console.log("User is logged in");
|
console.log("User is logged in");
|
||||||
userProfile = result;
|
userProfile = result;
|
||||||
|
|
||||||
|
loadAvatar(userProfile.avatar);
|
||||||
|
|
||||||
// hide the upload button if it's not permitted
|
// hide the upload button if it's not permitted
|
||||||
var uploadButton = document.getElementById('banner_upload');
|
var uploadButton = document.getElementById('banner_upload');
|
||||||
if (!userProfile.roles.includes("Admin") && !userProfile.roles.includes("Gamer")) {
|
if (!userProfile.roles.includes("Admin") && !userProfile.roles.includes("Gamer")) {
|
||||||
|
@@ -1,5 +1,6 @@
|
|||||||
<div id="properties_toc">
|
<div id="properties_toc">
|
||||||
<div id="properties_profile_toc_general" name="properties_profile_toc_item" onclick="ProfileSelectTab('general');">Preferences</div>
|
<div id="properties_profile_toc_general" name="properties_profile_toc_item" onclick="ProfileSelectTab('general');">Preferences</div>
|
||||||
|
<div id="properties_profile_toc_avatar" name="properties_profile_toc_item" onclick="ProfileSelectTab('avatar');">Avatar</div>
|
||||||
<div id="properties_profile_toc_account" name="properties_profile_toc_item" onclick="ProfileSelectTab('account');">Account</div>
|
<div id="properties_profile_toc_account" name="properties_profile_toc_item" onclick="ProfileSelectTab('account');">Account</div>
|
||||||
</div>
|
</div>
|
||||||
<div id="properties_bodypanel">
|
<div id="properties_bodypanel">
|
||||||
@@ -78,6 +79,17 @@
|
|||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
|
<div id="properties_bodypanel_avatar" name="properties_profile_tab" style="display: none;">
|
||||||
|
<h3>Avatar</h3>
|
||||||
|
<div style="width: 100%; text-align: center;">
|
||||||
|
<div>
|
||||||
|
<img id="properties_bodypanel_avatar_image" style="width: 200px; height: 200px;" src="/images/user.svg"/>
|
||||||
|
</div>
|
||||||
|
<form id="properties_bodypanel_avatar_form" onsubmit="return false">
|
||||||
|
<input type="file" name="file" id="properties_bodypanel_avatar_upload" accept="image/*" /><button value="Save" onclick="SaveAvatar();">Save</button><button value="Delete" onclick="SaveAvatar(true);">Delete</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div id="properties_bodypanel_account" name="properties_profile_tab" style="display: none;">
|
<div id="properties_bodypanel_account" name="properties_profile_tab" style="display: none;">
|
||||||
<h3>Reset Password</h3>
|
<h3>Reset Password</h3>
|
||||||
<table style="width: 100%;">
|
<table style="width: 100%;">
|
||||||
@@ -344,8 +356,86 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function SaveAvatar(DeleteExisting) {
|
||||||
|
if (DeleteExisting == true) {
|
||||||
|
ajaxCall(
|
||||||
|
'/api/v1.1/Account/Avatar/' + userProfile.avatar + '.jpg',
|
||||||
|
'DELETE',
|
||||||
|
function (success) {
|
||||||
|
userProfile.avatar = "00000000-0000-0000-0000-000000000000";
|
||||||
|
loadAvatar(userProfile.avatar);
|
||||||
|
displayAvatarPreview("/images/user.svg");
|
||||||
|
},
|
||||||
|
function (error) {
|
||||||
|
userProfile.avatar = "00000000-0000-0000-0000-000000000000";
|
||||||
|
loadAvatar(userProfile.avatar);
|
||||||
|
displayAvatarPreview("/images/user.svg");
|
||||||
|
}
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
var form = $('#properties_bodypanel_avatar_form')[0];
|
||||||
|
var formData = new FormData(form);
|
||||||
|
formData.append("file", document.getElementById("properties_bodypanel_avatar_upload").files[0]);
|
||||||
|
|
||||||
|
$.ajax({
|
||||||
|
|
||||||
|
// Our sample url to make request
|
||||||
|
url:
|
||||||
|
'/api/v1.1/Account/Avatar',
|
||||||
|
|
||||||
|
// Type of Request
|
||||||
|
type: 'POST',
|
||||||
|
|
||||||
|
// data to send to the server
|
||||||
|
data: formData,
|
||||||
|
|
||||||
|
contentType: false,
|
||||||
|
processData: false,
|
||||||
|
|
||||||
|
// Function to call when to
|
||||||
|
// request is ok
|
||||||
|
success: function (data) {
|
||||||
|
var x = JSON.stringify(data);
|
||||||
|
console.log(x);
|
||||||
|
|
||||||
|
loadAvatar(data);
|
||||||
|
userProfile.avatar = data;
|
||||||
|
displayAvatarPreview("/api/v1.1/Account/Avatar/" + data + ".jpg");
|
||||||
|
},
|
||||||
|
|
||||||
|
// Error handling
|
||||||
|
error: function (error) {
|
||||||
|
console.log(`Error ${JSON.stringify(error)}`);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function displayAvatarPreview(previewImg) {
|
||||||
|
var previewPath;
|
||||||
|
if (previewImg) {
|
||||||
|
previewPath = previewImg;
|
||||||
|
} else {
|
||||||
|
if (userProfile.avatar == "00000000-0000-0000-0000-000000000000") {
|
||||||
|
previewPath = "/images/user.svg";
|
||||||
|
} else {
|
||||||
|
previewPath = "/api/v1.1/Account/Avatar/" + userProfile.avatar + ".jpg";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var previewElement = document.getElementById('properties_bodypanel_avatar_image')
|
||||||
|
previewElement.setAttribute("src", previewPath);
|
||||||
|
|
||||||
|
if (previewPath != "/images/user.svg") {
|
||||||
|
previewElement.style.filter = "";
|
||||||
|
} else {
|
||||||
|
previewElement.style.filter = "invert(100%)";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ProfileSelectTab('general');
|
ProfileSelectTab('general');
|
||||||
GetPrefInitialValues();
|
GetPrefInitialValues();
|
||||||
|
displayAvatarPreview();
|
||||||
|
|
||||||
$('#profile_pref-LibraryPagination').select2();
|
$('#profile_pref-LibraryPagination').select2();
|
||||||
$('#profile_pref_LibraryPrimaryClassificationBadge').select2();
|
$('#profile_pref_LibraryPrimaryClassificationBadge').select2();
|
||||||
|
@@ -26,6 +26,7 @@
|
|||||||
createTableRow(
|
createTableRow(
|
||||||
true,
|
true,
|
||||||
[
|
[
|
||||||
|
'',
|
||||||
'Email',
|
'Email',
|
||||||
'Role',
|
'Role',
|
||||||
'Age Restriction',
|
'Age Restriction',
|
||||||
@@ -37,16 +38,16 @@
|
|||||||
);
|
);
|
||||||
|
|
||||||
for (var i = 0; i < result.length; i++) {
|
for (var i = 0; i < result.length; i++) {
|
||||||
|
var userAvatar = document.createElement('img');
|
||||||
|
userAvatar.className = "user_list_icon";
|
||||||
|
if (result[i].avatar != "00000000-0000-0000-0000-000000000000") {
|
||||||
|
userAvatar.setAttribute("src", "/api/v1.1/Account/Avatar/" + result[i].avatar + ".jpg");
|
||||||
|
} else {
|
||||||
|
userAvatar.setAttribute("src", "/images/user.svg");
|
||||||
|
userAvatar.classList.add("user_list_icon_reversed");
|
||||||
|
}
|
||||||
|
|
||||||
var roleDiv = document.createElement('div');
|
var roleDiv = document.createElement('div');
|
||||||
// for (var r = 0; r < result[i].roles.length; r++) {
|
|
||||||
// var roleItem = document.createElement('div');
|
|
||||||
// roleItem.className = 'dropdownroleitem';
|
|
||||||
// roleItem.innerHTML = result[i].roles[r].toUpperCase();
|
|
||||||
// var colorVal = intToRGB(hashCode(result[i].roles[r]));
|
|
||||||
// roleItem.style.backgroundColor = '#' + colorVal;
|
|
||||||
// roleItem.style.borderColor = '#' + colorVal;
|
|
||||||
// roleDiv.appendChild(roleItem);
|
|
||||||
// }
|
|
||||||
|
|
||||||
var roleItem = CreateBadge(result[i].highestRole);
|
var roleItem = CreateBadge(result[i].highestRole);
|
||||||
roleDiv.appendChild(roleItem);
|
roleDiv.appendChild(roleItem);
|
||||||
@@ -79,6 +80,7 @@
|
|||||||
createTableRow(
|
createTableRow(
|
||||||
false,
|
false,
|
||||||
[
|
[
|
||||||
|
userAvatar,
|
||||||
result[i].emailAddress,
|
result[i].emailAddress,
|
||||||
roleDiv,
|
roleDiv,
|
||||||
ageRestrictionPolicyDescription,
|
ageRestrictionPolicyDescription,
|
||||||
|
@@ -517,3 +517,25 @@ function Uint8ToString(u8a){
|
|||||||
}
|
}
|
||||||
return c.join("");
|
return c.join("");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function loadAvatar(AvatarId) {
|
||||||
|
// load user avatar
|
||||||
|
var bannerAvatar = document.getElementById('banner_user_image');
|
||||||
|
var bannerAvatarButton = document.getElementById('banner_user');
|
||||||
|
|
||||||
|
if (bannerAvatar && bannerAvatarButton) {
|
||||||
|
if (AvatarId != "00000000-0000-0000-0000-000000000000") {
|
||||||
|
bannerAvatar.setAttribute("src", "/api/v1.1/Account/Avatar/" + AvatarId + ".jpg");
|
||||||
|
bannerAvatar.className = "banner_button_avatar";
|
||||||
|
|
||||||
|
bannerAvatarButton.classList.add('banner_button_avatar_image');
|
||||||
|
bannerAvatarButton.classList.remove('banner_button');
|
||||||
|
} else {
|
||||||
|
bannerAvatar.setAttribute("src", "/images/user.svg");
|
||||||
|
bannerAvatar.className = "banner_button_image";
|
||||||
|
|
||||||
|
bannerAvatarButton.classList.remove('banner_button_avatar_image');
|
||||||
|
bannerAvatarButton.classList.add('banner_button');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -146,12 +146,33 @@ h3 {
|
|||||||
filter: invert(100%);
|
filter: invert(100%);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.user_list_icon {
|
||||||
|
width: 35px;
|
||||||
|
height: 35px;
|
||||||
|
margin-bottom: -5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.user_list_icon_reversed {
|
||||||
|
filter: invert(100%);
|
||||||
|
}
|
||||||
|
|
||||||
.banner_button_image_smaller {
|
.banner_button_image_smaller {
|
||||||
height: 16px;
|
height: 16px;
|
||||||
width: 16px;
|
width: 16px;
|
||||||
margin-left: 5px;
|
margin-left: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.banner_button_avatar {
|
||||||
|
margin-top: -10px;
|
||||||
|
height: 40px;
|
||||||
|
width: 40px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.banner_button_avatar_image:hover {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
#banner_header {
|
#banner_header {
|
||||||
background-color: rgba(0, 22, 56, 0.8);
|
background-color: rgba(0, 22, 56, 0.8);
|
||||||
backdrop-filter: blur(8px);
|
backdrop-filter: blur(8px);
|
||||||
|
Reference in New Issue
Block a user