Updated site
This commit is contained in:
@@ -1,4 +0,0 @@
|
||||
[*.cs]
|
||||
|
||||
# CA1303: Do not pass literals as localized parameters
|
||||
dotnet_diagnostic.CA1303.severity = none
|
||||
@@ -1,6 +1,7 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using MyWebsite.Controllers;
|
||||
using MyWebsite.Models.Databases;
|
||||
using System.Linq;
|
||||
|
||||
namespace MyWebsite.Areas.API
|
||||
{
|
||||
@@ -8,10 +9,12 @@ namespace MyWebsite.Areas.API
|
||||
[Route("API/[controller]")]
|
||||
public class GUTScheduleController : ExtendedController
|
||||
{
|
||||
public GUTScheduleController(DatabaseContext context) : base(context) { }
|
||||
GUTScheduleDatabaseContext databaseContext;
|
||||
public GUTScheduleController(DatabaseContext context, GUTScheduleDatabaseContext db) : base(context) =>
|
||||
databaseContext = db;
|
||||
|
||||
[Route("SemesterOffsetDay")]
|
||||
public string SemesterOffsetDay() =>
|
||||
Database.CustomData.Find("gut.schedule.semester.offset")?.Value ?? "undefined";
|
||||
databaseContext.OffsetDates?.FirstOrDefault()?.Value ?? "undefined";
|
||||
}
|
||||
}
|
||||
@@ -7,6 +7,7 @@ using MyWebsite.Models.Databases;
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
|
||||
namespace MyWebsite.Areas.Admin.Controllers
|
||||
{
|
||||
@@ -16,21 +17,43 @@ namespace MyWebsite.Areas.Admin.Controllers
|
||||
{
|
||||
public BadgesController(DatabaseContext context) : base(context) { }
|
||||
|
||||
[HttpGet]
|
||||
public IActionResult Index() =>
|
||||
View(Database.Badges);
|
||||
|
||||
[HttpPost]
|
||||
public IActionResult Index(IFormFile badgeImage)
|
||||
{
|
||||
if (badgeImage == null)
|
||||
throw new ArgumentNullException(nameof(badgeImage));
|
||||
|
||||
System.Drawing.Image image = System.Drawing.Image.FromStream(badgeImage.OpenReadStream());
|
||||
if (System.IO.File.Exists(Directory.GetCurrentDirectory() + "/wwwroot/images/Badges/" + badgeImage.FileName))
|
||||
ModelState.AddModelError("Error", $"Badge image with such name ({badgeImage.FileName}) is already esists");
|
||||
else if (image.Width != 64 || image.Height != 64 || !badgeImage.FileName.EndsWith(".PNG", true, CultureInfo.InvariantCulture))
|
||||
ModelState.AddModelError("Error", "The file must be EXACTLY 64x64 pixels PNG image");
|
||||
else
|
||||
using (var stream = System.IO.File.Create(Directory.GetCurrentDirectory() + "/wwwroot/images/Badges/" + badgeImage.FileName))
|
||||
badgeImage.CopyTo(stream);
|
||||
|
||||
return View(Database.Badges);
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
public IActionResult Edit(string id) =>
|
||||
View(Database.Badges.Find(id));
|
||||
|
||||
[HttpPost]
|
||||
public IActionResult Edit(BadgeModel model, IFormFile file = null)
|
||||
public IActionResult Edit(BadgeModel model)
|
||||
{
|
||||
if (model == null)
|
||||
throw new ArgumentNullException(nameof(model));
|
||||
|
||||
if (file != null)
|
||||
UploadFile(file, model);
|
||||
if (!ModelState.IsValid)
|
||||
{
|
||||
ModelState.AddModelError("Error", "Invalid data");
|
||||
return View(model);
|
||||
}
|
||||
|
||||
Database.Badges.Update(model);
|
||||
Database.SaveChanges();
|
||||
@@ -45,6 +68,13 @@ namespace MyWebsite.Areas.Admin.Controllers
|
||||
[HttpPost]
|
||||
public IActionResult Delete(BadgeModel model)
|
||||
{
|
||||
if (Database.Projects.ToList().Any(i => i.Badges.Contains(model.Name, StringComparison.InvariantCulture)))
|
||||
{
|
||||
ModelState.Clear();
|
||||
ModelState.AddModelError("Error", "Remove badge references from projects descriptions in order to delete the badge");
|
||||
return View(Database.Badges.Find(model?.Name));
|
||||
}
|
||||
|
||||
Database.Badges.Remove(model);
|
||||
Database.SaveChanges();
|
||||
|
||||
@@ -53,41 +83,40 @@ namespace MyWebsite.Areas.Admin.Controllers
|
||||
|
||||
[HttpGet]
|
||||
public IActionResult Create() =>
|
||||
View();
|
||||
View(model: null);
|
||||
|
||||
[HttpPost]
|
||||
public IActionResult Create(BadgeModel model, IFormFile file = null)
|
||||
public IActionResult Create(BadgeModel model)
|
||||
{
|
||||
if (model == null)
|
||||
throw new ArgumentNullException(nameof(model));
|
||||
|
||||
if (file != null)
|
||||
return UploadFile(file, model);
|
||||
|
||||
if (!ModelState.IsValid)
|
||||
{
|
||||
ModelState.AddModelError("Error", "Invalid data");
|
||||
return View(model);
|
||||
}
|
||||
|
||||
if (Database.Badges.Any(i => i.Name == model.Name))
|
||||
{
|
||||
ModelState.AddModelError("Error", $"Badge '{model.Name}' is already exists");
|
||||
return View(model);
|
||||
}
|
||||
|
||||
Database.Badges.Add(model);
|
||||
Database.SaveChanges();
|
||||
|
||||
return RedirectToAction("Index");
|
||||
}
|
||||
|
||||
private IActionResult UploadFile(IFormFile file, BadgeModel model)
|
||||
[HttpGet]
|
||||
public IActionResult DeleteBadgeImage(string id)
|
||||
{
|
||||
System.Drawing.Image image = System.Drawing.Image.FromStream(file.OpenReadStream());
|
||||
if (image.Width != 64 || image.Height != 64 || !file.FileName.EndsWith(".PNG", true, CultureInfo.InvariantCulture))
|
||||
{
|
||||
ViewData["UploadException"] = "error";
|
||||
return View(model);
|
||||
}
|
||||
using (var stream = System.IO.File.Create(Directory.GetCurrentDirectory() + "/wwwroot/images/Badges/" + file.FileName))
|
||||
file.CopyTo(stream);
|
||||
string path = Directory.GetCurrentDirectory() + "/wwwroot/images/Badges/" + id;
|
||||
if (System.IO.File.Exists(path))
|
||||
System.IO.File.Delete(path);
|
||||
|
||||
return Redirect(Request.Path.Value);
|
||||
return RedirectToAction("Index");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,6 +3,8 @@ using Microsoft.AspNetCore.Mvc;
|
||||
using MyWebsite.Controllers;
|
||||
using MyWebsite.Models;
|
||||
using MyWebsite.Models.Databases;
|
||||
using System;
|
||||
using System.Linq;
|
||||
|
||||
namespace MyWebsite.Areas.Admin.Controllers
|
||||
{
|
||||
@@ -15,6 +17,23 @@ namespace MyWebsite.Areas.Admin.Controllers
|
||||
public IActionResult Index() =>
|
||||
View(Database.Links);
|
||||
|
||||
[HttpPost]
|
||||
public IActionResult Index(string[] reorderList)
|
||||
{
|
||||
if(reorderList?.Length != Database.Links.Count())
|
||||
{
|
||||
ModelState.AddModelError("Error", "Invalid or incomplete data recieved");
|
||||
return View(Database.Links);
|
||||
}
|
||||
|
||||
for (int i = 0; i < reorderList.Length; i++)
|
||||
Database.Links.Find(reorderList[i]).Order = i;
|
||||
|
||||
Database.SaveChanges();
|
||||
|
||||
return View(Database.Links);
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
public IActionResult Edit(string id) =>
|
||||
View(Database.Links.Find(id));
|
||||
@@ -22,6 +41,15 @@ namespace MyWebsite.Areas.Admin.Controllers
|
||||
[HttpPost]
|
||||
public IActionResult Edit(LinkModel model)
|
||||
{
|
||||
if (model == null)
|
||||
throw new ArgumentNullException(nameof(model));
|
||||
|
||||
if (!ModelState.IsValid)
|
||||
{
|
||||
ModelState.AddModelError("Error", "Invalid data");
|
||||
return View(model);
|
||||
}
|
||||
|
||||
Database.Links.Update(model);
|
||||
Database.SaveChanges();
|
||||
|
||||
@@ -43,16 +71,26 @@ namespace MyWebsite.Areas.Admin.Controllers
|
||||
|
||||
[HttpGet]
|
||||
public IActionResult Create() =>
|
||||
View();
|
||||
View(model: null);
|
||||
|
||||
[HttpPost]
|
||||
public IActionResult Create(LinkModel model)
|
||||
{
|
||||
if (model == null)
|
||||
throw new ArgumentNullException(nameof(model));
|
||||
|
||||
if (!ModelState.IsValid)
|
||||
{
|
||||
ModelState.AddModelError("Error", "Invalid data");
|
||||
return View(model);
|
||||
}
|
||||
model.Order = Database.Links.Count();
|
||||
|
||||
if (Database.Links.Any(i => i.Name == model.Name))
|
||||
{
|
||||
ModelState.AddModelError("Error", $"Link '{model.Name}' is already exists");
|
||||
return View(model);
|
||||
}
|
||||
|
||||
Database.Links.Add(model);
|
||||
Database.SaveChanges();
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using MyWebsite.Controllers;
|
||||
using MyWebsite.Helpers;
|
||||
using MyWebsite.Models;
|
||||
using MyWebsite.Models.Databases;
|
||||
using System.Linq;
|
||||
|
||||
@@ -20,29 +21,45 @@ namespace MyWebsite.Areas.Admin.Controllers
|
||||
View(viewPath);
|
||||
|
||||
[HttpPost]
|
||||
public IActionResult Index(Models.CredentialModel model)
|
||||
public IActionResult Index(string key, string value)
|
||||
{
|
||||
MyWebsite.Models.CredentialModel credential = Database.Users.FirstOrDefault();
|
||||
|
||||
if (model == null || model.Current.Email != credential.Email || !Encryptor.VerifyHash(model.Current.Password, credential.Password))
|
||||
if(string.IsNullOrWhiteSpace(key))
|
||||
{
|
||||
ModelState.AddModelError("Authorization error", "Invaild e-mail or password");
|
||||
return View(viewPath, model);
|
||||
ModelState.AddModelError("Validation error", "Unable to identify data to update");
|
||||
return View(viewPath);
|
||||
}
|
||||
|
||||
if(string.IsNullOrWhiteSpace(model.Updated.Email) && string.IsNullOrWhiteSpace(model.Current.Password))
|
||||
if(string.IsNullOrWhiteSpace(value))
|
||||
{
|
||||
ModelState.AddModelError("Validation error", "No data to update");
|
||||
return View(viewPath, model);
|
||||
ModelState.AddModelError("Validation error", "No data provided");
|
||||
return View(viewPath);
|
||||
}
|
||||
|
||||
Database.Users.Remove(credential);
|
||||
Database.SaveChanges();
|
||||
if(!string.IsNullOrWhiteSpace(model.Current.Email))
|
||||
credential.Email = model.Updated.Email;
|
||||
if(!string.IsNullOrWhiteSpace(model.Current.Password))
|
||||
credential.Password = Encryptor.ComputeHash(model.Updated.Password);
|
||||
Database.Users.Add(credential);
|
||||
CredentialModel credential = Database.Users.FirstOrDefault();
|
||||
Database.Users.RemoveRange(Database.Users);
|
||||
|
||||
switch (key)
|
||||
{
|
||||
case "password":
|
||||
Database.Users.Add(new CredentialModel
|
||||
{
|
||||
Email = credential.Email,
|
||||
Password = Encryptor.ComputeHash(value)
|
||||
});
|
||||
break;
|
||||
|
||||
case "email":
|
||||
Database.Users.Add(new CredentialModel
|
||||
{
|
||||
Email = value,
|
||||
Password = credential.Password
|
||||
});
|
||||
break;
|
||||
|
||||
default:
|
||||
ModelState.AddModelError("Processing error", "Provided data is missing or read-only");
|
||||
return View(viewPath);
|
||||
}
|
||||
|
||||
Database.SaveChanges();
|
||||
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace MyWebsite.Areas.Admin.Controllers
|
||||
{
|
||||
[Area("Admin")]
|
||||
[Authorize]
|
||||
public class FoxTubeController : Controller
|
||||
{
|
||||
public IActionResult Index()
|
||||
{
|
||||
return View();
|
||||
}
|
||||
|
||||
public IActionResult Screenshots()
|
||||
{
|
||||
return View();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4,6 +4,9 @@ using MyWebsite.Controllers;
|
||||
using MyWebsite.Models;
|
||||
using MyWebsite.Models.Databases;
|
||||
using System.Linq;
|
||||
using System;
|
||||
using MyWebsite.ViewModels;
|
||||
using System.Globalization;
|
||||
|
||||
namespace MyWebsite.Areas.Admin.Controllers
|
||||
{
|
||||
@@ -11,31 +14,120 @@ namespace MyWebsite.Areas.Admin.Controllers
|
||||
[Area("Admin")]
|
||||
public class GUTScheduleController : ExtendedController
|
||||
{
|
||||
const string scheduleOffsetId = "gut.schedule.semester.offset";
|
||||
const string viewPath = "Areas/Admin/Views/Shared/GUTSchedule.cshtml";
|
||||
|
||||
public GUTScheduleController(DatabaseContext context) : base(context) { }
|
||||
private GUTScheduleDatabaseContext db;
|
||||
|
||||
public GUTScheduleController(DatabaseContext context, GUTScheduleDatabaseContext databaseContext) : base(context) =>
|
||||
db = databaseContext;
|
||||
|
||||
[HttpGet]
|
||||
public IActionResult Index() =>
|
||||
View(viewPath, Database.CustomData.Find(scheduleOffsetId) ?? new CustomData { Key = scheduleOffsetId, Value = "undefined" });
|
||||
public IActionResult Index()
|
||||
{
|
||||
ViewData["Policies"] = db.PrivacyPolicies;
|
||||
return View(viewPath, db.OffsetDates.FirstOrDefault());
|
||||
}
|
||||
|
||||
|
||||
[HttpPost]
|
||||
public IActionResult Index(CustomData model)
|
||||
{
|
||||
if(!ModelState.IsValid)
|
||||
if (model == null)
|
||||
throw new ArgumentNullException(nameof(model));
|
||||
|
||||
if (!ModelState.IsValid)
|
||||
{
|
||||
ModelState.AddModelError("Error", "Invalid data");
|
||||
return View(model);
|
||||
}
|
||||
|
||||
if(Database.CustomData.Any(i => i.Key == scheduleOffsetId))
|
||||
Database.CustomData.Update(model);
|
||||
else
|
||||
Database.CustomData.Add(model);
|
||||
db.OffsetDates.RemoveRange(db.OffsetDates);
|
||||
db.OffsetDates.Add(model);
|
||||
|
||||
Database.SaveChanges();
|
||||
return View(viewPath, model);
|
||||
db.SaveChanges();
|
||||
|
||||
return Index();
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
public IActionResult CreatePolicy()
|
||||
{
|
||||
ViewData["Caption"] = "privacy policy";
|
||||
return View(viewName: "Areas/Admin/Views/Resume/Create.cshtml");
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
public IActionResult CreatePolicy(ResumeModel model)
|
||||
{
|
||||
if (model == null)
|
||||
throw new ArgumentNullException(nameof(model));
|
||||
|
||||
if (!ModelState.IsValid)
|
||||
{
|
||||
ModelState.AddModelError("Error", "Invalid data");
|
||||
return View("Areas/Admin/Views/Resume/Create.cshtml", model);
|
||||
}
|
||||
|
||||
model.LastUpdate = DateTime.Now;
|
||||
|
||||
if (db.PrivacyPolicies.Any(i => i.Language == model.Language))
|
||||
{
|
||||
ModelState.AddModelError("Error", $"Resume with this language ({model.Language}) is already exists");
|
||||
return View("Areas/Admin/Views/Resume/Create.cshtml", model);
|
||||
}
|
||||
|
||||
db.PrivacyPolicies.Add(model);
|
||||
db.SaveChanges();
|
||||
|
||||
return RedirectToAction("Index");
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
public IActionResult DeletePolicy(string id)
|
||||
{
|
||||
ViewData["Caption"] = "privacy policy";
|
||||
return View("Areas/Admin/Views/Resume/Delete.cshtml", db.PrivacyPolicies.Find(id));
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
public IActionResult DeletePolicy(ResumeModel model)
|
||||
{
|
||||
db.PrivacyPolicies.Remove(model);
|
||||
db.SaveChanges();
|
||||
|
||||
return RedirectToAction("Index");
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
public IActionResult EditPolicy(string id)
|
||||
{
|
||||
ViewData["Caption"] = "privacy policy";
|
||||
return View("Areas/Admin/Views/Resume/Edit.cshtml", db.PrivacyPolicies.Find(id));
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
public IActionResult EditPolicy(ResumeModel model)
|
||||
{
|
||||
if (model == null)
|
||||
throw new ArgumentNullException(nameof(model));
|
||||
|
||||
if (!ModelState.IsValid)
|
||||
{
|
||||
ModelState.AddModelError("Error", "Invalid data");
|
||||
return View("Areas/Admin/Views/Resume/Edit.cshtml", model);
|
||||
}
|
||||
|
||||
model.LastUpdate = DateTime.Now;
|
||||
|
||||
db.PrivacyPolicies.Update(model);
|
||||
db.SaveChanges();
|
||||
|
||||
return RedirectToAction("Index");
|
||||
}
|
||||
|
||||
[AllowAnonymous]
|
||||
[Route("/Projects/GUTSchedule/PrivacyPolicy")]
|
||||
public IActionResult PrivacyPolicy() =>
|
||||
View("Areas/Projects/Views/GUTSchedule/PrivacyPolicy.cshtml", new ResumeViewModel(db.PrivacyPolicies.Find(CultureInfo.CurrentCulture.TwoLetterISOLanguageName) ?? db.PrivacyPolicies.Find("en") ?? db.PrivacyPolicies.Find("ru"), Database));
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using MyWebsite.Areas.Admin.Models;
|
||||
using MyWebsite.Controllers;
|
||||
using MyWebsite.Models;
|
||||
using MyWebsite.Models.Databases;
|
||||
@@ -19,13 +19,8 @@ namespace MyWebsite.Areas.Admin.Controllers
|
||||
View(Database.Gallery);
|
||||
|
||||
[HttpGet]
|
||||
public IActionResult Edit(Guid id)
|
||||
{
|
||||
if (Database.Gallery.Find(id) is ImageModel model)
|
||||
return View(model);
|
||||
else
|
||||
return NotFound();
|
||||
}
|
||||
public IActionResult Edit(string id) =>
|
||||
View(Database.Gallery.Find(id));
|
||||
|
||||
[HttpPost]
|
||||
public IActionResult Edit(ImageModel model)
|
||||
@@ -43,13 +38,8 @@ namespace MyWebsite.Areas.Admin.Controllers
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
public IActionResult Delete(Guid id)
|
||||
{
|
||||
if (Database.Gallery.Find(id) is ImageModel model)
|
||||
return View(model);
|
||||
else
|
||||
return NotFound();
|
||||
}
|
||||
public IActionResult Delete(string id) =>
|
||||
View(Database.Gallery.Find(id));
|
||||
|
||||
[HttpPost]
|
||||
public IActionResult Delete(ImageModel model)
|
||||
@@ -65,31 +55,28 @@ namespace MyWebsite.Areas.Admin.Controllers
|
||||
|
||||
[HttpGet]
|
||||
public IActionResult Upload() =>
|
||||
View();
|
||||
View(model: null);
|
||||
|
||||
[HttpPost]
|
||||
public IActionResult Upload(ArtworkModel model)
|
||||
public IActionResult Upload(ImageModel model, IFormFile file)
|
||||
{
|
||||
if (model == null)
|
||||
throw new ArgumentNullException(nameof(model));
|
||||
if (file == null)
|
||||
throw new ArgumentNullException(nameof(file));
|
||||
|
||||
model.FileName = file.FileName;
|
||||
|
||||
if (!ModelState.IsValid)
|
||||
{
|
||||
ModelState.AddModelError("Error", "Invalid data");
|
||||
return View(model);
|
||||
}
|
||||
|
||||
using (var stream = System.IO.File.Create(Directory.GetCurrentDirectory() + "/wwwroot/images/Gallery/" + model?.File.FileName))
|
||||
model.File.CopyTo(stream);
|
||||
using (var stream = System.IO.File.Create(Directory.GetCurrentDirectory() + "/wwwroot/images/Gallery/" + file.FileName))
|
||||
file.CopyTo(stream);
|
||||
|
||||
ImageModel image = new ImageModel
|
||||
{
|
||||
EnglishTitle = model.EnglishTitle,
|
||||
RussianTitle = model.RussianTitle,
|
||||
EnglishDescription = model.EnglishDescription,
|
||||
RussianDescription = model.RussianDescription,
|
||||
CreationDate = model.CreationDate,
|
||||
FileName = model.File.FileName
|
||||
};
|
||||
|
||||
Database.Gallery.Add(image);
|
||||
Database.Gallery.Add(model);
|
||||
Database.SaveChanges();
|
||||
|
||||
return RedirectToAction("Index");
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
using System.Collections.Generic;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using MyWebsite.Controllers;
|
||||
@@ -13,12 +15,32 @@ namespace MyWebsite.Areas.Admin.Controllers
|
||||
{
|
||||
public ProjectsController(DatabaseContext context) : base(context) { }
|
||||
|
||||
[HttpGet]
|
||||
public IActionResult Index() =>
|
||||
View((Database.Projects as IEnumerable<ProjectModel>, Database.Badges as IEnumerable<BadgeModel>));
|
||||
|
||||
[HttpPost]
|
||||
public IActionResult Index(Guid[] reorderList)
|
||||
{
|
||||
if (reorderList?.Length != Database.Projects.Count())
|
||||
ModelState.AddModelError("Error", "Invalid or incomplete data recieved");
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < reorderList.Length; i++)
|
||||
Database.Projects.Find(reorderList[i]).Order = i;
|
||||
|
||||
Database.SaveChanges();
|
||||
}
|
||||
|
||||
return View((Database.Projects as IEnumerable<ProjectModel>, Database.Badges as IEnumerable<BadgeModel>));
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
public IActionResult Delete(decimal id) =>
|
||||
View(Database.Projects.Find(id));
|
||||
public IActionResult Delete(Guid id)
|
||||
{
|
||||
ViewData["Badges"] = Database.Badges.ToList();
|
||||
return View(Database.Projects.Find(id));
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
public IActionResult Delete(ProjectModel model)
|
||||
@@ -30,17 +52,50 @@ namespace MyWebsite.Areas.Admin.Controllers
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
public IActionResult Create() =>
|
||||
View();
|
||||
public IActionResult Edit(Guid id)
|
||||
{
|
||||
ViewData["Badges"] = Database.Badges.ToList();
|
||||
return View(Database.Projects.Find(id));
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
public IActionResult Edit(ProjectModel model)
|
||||
{
|
||||
if (model == null)
|
||||
throw new ArgumentNullException(nameof(model));
|
||||
|
||||
if (!ModelState.IsValid)
|
||||
{
|
||||
ModelState.AddModelError("Error", "Invalid data");
|
||||
ViewData["Badges"] = Database.Badges.ToList();
|
||||
return View(model);
|
||||
}
|
||||
|
||||
Database.Projects.Update(model);
|
||||
Database.SaveChanges();
|
||||
|
||||
return RedirectToAction("Index");
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
public IActionResult Create()
|
||||
{
|
||||
ViewData["Badges"] = Database.Badges.ToList();
|
||||
return View(model: null);
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
public IActionResult Create(ProjectModel model)
|
||||
{
|
||||
if (model == null)
|
||||
throw new ArgumentNullException(nameof(model));
|
||||
|
||||
if (!ModelState.IsValid)
|
||||
{
|
||||
ModelState.AddModelError("Error", "Invalid data");
|
||||
return View(model);
|
||||
}
|
||||
model.Order = Database.Projects.Count();
|
||||
|
||||
Database.Projects.Add(model);
|
||||
Database.SaveChanges();
|
||||
@@ -48,16 +103,4 @@ namespace MyWebsite.Areas.Admin.Controllers
|
||||
return RedirectToAction("Index");
|
||||
}
|
||||
}
|
||||
|
||||
public class ProjectEditorModel
|
||||
{
|
||||
public double Id { get; set; }
|
||||
public string EnglishTitle { get; set; }
|
||||
public string RussianTitle { get; set; }
|
||||
public string EnglishDescription { get; set; }
|
||||
public string RussianDescription { get; set; }
|
||||
public string Link { get; set; }
|
||||
public string EnglishLinkCaption { get; set; }
|
||||
public string RussianLinkCaption { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -4,6 +4,7 @@ using MyWebsite.Controllers;
|
||||
using MyWebsite.Models;
|
||||
using MyWebsite.Models.Databases;
|
||||
using System;
|
||||
using System.Linq;
|
||||
|
||||
namespace MyWebsite.Areas.Admin.Controllers
|
||||
{
|
||||
@@ -55,7 +56,7 @@ namespace MyWebsite.Areas.Admin.Controllers
|
||||
|
||||
[HttpGet]
|
||||
public IActionResult Create() =>
|
||||
View();
|
||||
(this as Controller).View();
|
||||
|
||||
[HttpPost]
|
||||
public IActionResult Create(ResumeModel model)
|
||||
@@ -71,6 +72,12 @@ namespace MyWebsite.Areas.Admin.Controllers
|
||||
|
||||
model.LastUpdate = DateTime.Now;
|
||||
|
||||
if(Database.Resume.Any(i => i.Language == model.Language))
|
||||
{
|
||||
ModelState.AddModelError("Error", $"Resume with this language ({model.Language}) is already exists");
|
||||
return View(model);
|
||||
}
|
||||
|
||||
Database.Resume.Add(model);
|
||||
Database.SaveChanges();
|
||||
|
||||
|
||||
@@ -1,29 +0,0 @@
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace MyWebsite.Areas.Admin.Models
|
||||
{
|
||||
public class ArtworkModel
|
||||
{
|
||||
[Required]
|
||||
[DisplayName("Title (en)")]
|
||||
public string EnglishTitle { get; set; }
|
||||
[DisplayName("Title (ru)")]
|
||||
public string RussianTitle { get; set; }
|
||||
|
||||
[Required]
|
||||
[DisplayName("Description (en)")]
|
||||
public string EnglishDescription { get; set; }
|
||||
[DisplayName("Description (ru)")]
|
||||
public string RussianDescription { get; set; }
|
||||
|
||||
[Required]
|
||||
[DisplayName("Created")]
|
||||
public DateTime CreationDate { get; set; }
|
||||
[Required]
|
||||
[DisplayName("File")]
|
||||
public IFormFile File { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
using MyWebsite.Models;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace MyWebsite.Areas.Admin.Models
|
||||
{
|
||||
public class CredentialModel
|
||||
{
|
||||
public MyWebsite.Models.CredentialModel Current { get; set; } = new MyWebsite.Models.CredentialModel();
|
||||
public MyWebsite.Models.CredentialModel Updated { get; set; } = new MyWebsite.Models.CredentialModel();
|
||||
}
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace MyWebsite.Areas.Admin.Models
|
||||
{
|
||||
public enum ReorderDirection { Up, Down }
|
||||
public class ReorderModel
|
||||
{
|
||||
public string ItemId { get; set; }
|
||||
public ReorderDirection Direction { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,31 +1,24 @@
|
||||
@model MyWebsite.Models.BadgeModel
|
||||
@using System.IO;
|
||||
@{
|
||||
ViewData["Title"] = "Create badge";
|
||||
List<SelectListItem> files = new List<SelectListItem>();
|
||||
foreach (string path in Directory.GetFiles(Directory.GetCurrentDirectory() + "/wwwroot/images/Badges"))
|
||||
{
|
||||
string fileName = System.IO.Path.GetFileNameWithoutExtension(path);
|
||||
files.Add(new SelectListItem(fileName, fileName));
|
||||
}
|
||||
}
|
||||
|
||||
<header>
|
||||
<p> <a asp-action="Index">Back to the list</a></p>
|
||||
 <a asp-action="Index">Back to the list</a>
|
||||
<h1>Create project badge</h1>
|
||||
</header>
|
||||
|
||||
<article>
|
||||
<form asp-action="Create" oninput="UpdatePreview();">
|
||||
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
|
||||
<div asp-validation-summary="All" class="text-danger"></div>
|
||||
<div>
|
||||
<label asp-for="Name"></label>
|
||||
<input asp-for="Name" type="text" />
|
||||
<input asp-for="Name" type="text" placeholder="Enter unique badge name" required />
|
||||
<span asp-validation-for="Name" class="text-danger"></span>
|
||||
</div>
|
||||
<div>
|
||||
<label asp-for="EnglishDescription"></label>
|
||||
<input asp-for="EnglishDescription" type="text" />
|
||||
<input asp-for="EnglishDescription" type="text" required />
|
||||
<span asp-validation-for="EnglishDescription" class="text-danger"></span>
|
||||
</div>
|
||||
<div>
|
||||
@@ -36,22 +29,19 @@
|
||||
<div>
|
||||
<label asp-for="Image"></label>
|
||||
<div class="image-selector">
|
||||
<select asp-for="Image" asp-items="files" onchange="UpdatePreview();"></select>
|
||||
<select asp-for="Image" onchange="UpdatePreview();" required>
|
||||
@foreach (string path in System.IO.Directory.GetFiles(System.IO.Directory.GetCurrentDirectory() + "/wwwroot/images/Badges"))
|
||||
{
|
||||
string file = System.IO.Path.GetFileNameWithoutExtension(path);
|
||||
<option value="@file">@file</option>
|
||||
}
|
||||
</select>
|
||||
<span>.png</span>
|
||||
</div>
|
||||
<span asp-validation-for="Image" class="text-danger"></span>
|
||||
</div>
|
||||
<partial name="Preview.cshtml" />
|
||||
|
||||
<input type="submit" value="Create" class="btn" />
|
||||
</form>
|
||||
<hr />
|
||||
<h2>Upload badge image</h2>
|
||||
<form method="post" enctype="multipart/form-data">
|
||||
<input type="file" accept="image/png" name="file" />
|
||||
<label for="file" style="@(ViewData.Keys.Contains("UploadException") ? "color: red" : "")">File must be a 64x64 PNG image</label>
|
||||
<input type="submit" value="Upload image" class="btn" />
|
||||
<input type="submit" value="Create" />
|
||||
</form>
|
||||
</article>
|
||||
|
||||
<link type="text/css" rel="stylesheet" href="~/css/Admin.css" />
|
||||
@@ -5,12 +5,13 @@
|
||||
}
|
||||
|
||||
<header>
|
||||
<p> <a asp-action="Index">Back to the list</a></p>
|
||||
 <a asp-action="Index">Back to the list</a>
|
||||
<h1>Delete project badge</h1>
|
||||
<h3>Are you sure you want to delete this?</h3>
|
||||
</header>
|
||||
|
||||
<article>
|
||||
<div asp-validation-summary="All" class="text-danger"></div>
|
||||
<p>
|
||||
<b>@Html.DisplayNameFor(model => model.Name):</b> @Model.Name<br />
|
||||
<b>@Html.DisplayNameFor(model => model.EnglishDescription):</b> @Model.EnglishDescription<br />
|
||||
@@ -23,15 +24,18 @@
|
||||
|
||||
<form asp-action="Delete">
|
||||
<input hidden asp-for="Name" />
|
||||
<input type="submit" value="Delete" class="btn-danger" />
|
||||
<input type="submit" value="Delete" required />
|
||||
</form>
|
||||
</article>
|
||||
|
||||
<link type="text/css" rel="stylesheet" href="~/css/Admin.css" />
|
||||
<style type="text/css">
|
||||
.badge {
|
||||
@section Imports
|
||||
{
|
||||
<style type="text/css">
|
||||
.badge
|
||||
{
|
||||
height: 50px;
|
||||
width: 50px;
|
||||
background-size: contain;
|
||||
}
|
||||
</style>
|
||||
</style>
|
||||
}
|
||||
@@ -1,31 +1,24 @@
|
||||
@using System.IO;
|
||||
@model MyWebsite.Models.BadgeModel
|
||||
@model MyWebsite.Models.BadgeModel
|
||||
@{
|
||||
ViewData["Title"] = "Edit badge";
|
||||
List<SelectListItem> files = new List<SelectListItem>();
|
||||
foreach (string path in Directory.GetFiles(Directory.GetCurrentDirectory() + "/wwwroot/images/Badges"))
|
||||
{
|
||||
string fileName = System.IO.Path.GetFileNameWithoutExtension(path);
|
||||
files.Add(new SelectListItem(fileName, fileName));
|
||||
}
|
||||
}
|
||||
|
||||
<header>
|
||||
<p> <a asp-action="Index">Back to the list</a></p>
|
||||
 <a asp-action="Index">Back to the list</a>
|
||||
<h1>Edit project badge</h1>
|
||||
</header>
|
||||
|
||||
<article>
|
||||
<form asp-action="Edit" oninput="UpdatePreview();">
|
||||
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
|
||||
<div asp-validation-summary="All" class="text-danger"></div>
|
||||
<div>
|
||||
<label asp-for="Name"></label>
|
||||
<input asp-for="Name" type="text" class="readonly" readonly />
|
||||
<input asp-for="Name" type="text" readonly />
|
||||
<span asp-validation-for="Name" class="text-danger"></span>
|
||||
</div>
|
||||
<div>
|
||||
<label asp-for="EnglishDescription"></label>
|
||||
<input asp-for="EnglishDescription" type="text" />
|
||||
<input asp-for="EnglishDescription" type="text" required />
|
||||
<span asp-validation-for="EnglishDescription" class="text-danger"></span>
|
||||
</div>
|
||||
<div>
|
||||
@@ -36,22 +29,19 @@
|
||||
<div>
|
||||
<label asp-for="Image"></label>
|
||||
<div class="image-selector">
|
||||
<select asp-for="Image" asp-items="files" onchange="UpdatePreview();"></select>
|
||||
<select asp-for="Image" onchange="UpdatePreview();" required>
|
||||
@foreach (string path in System.IO.Directory.GetFiles(System.IO.Directory.GetCurrentDirectory() + "/wwwroot/images/Badges"))
|
||||
{
|
||||
string file = System.IO.Path.GetFileNameWithoutExtension(path);
|
||||
<option value="@file">@file</option>
|
||||
}
|
||||
</select>
|
||||
<span>.png</span>
|
||||
</div>
|
||||
<span asp-validation-for="Image" class="text-danger"></span>
|
||||
</div>
|
||||
<partial name="Preview.cshtml" />
|
||||
|
||||
<input type="submit" value="Save" class="btn" />
|
||||
</form>
|
||||
<hr />
|
||||
<h2>Upload badge image</h2>
|
||||
<form method="post" enctype="multipart/form-data">
|
||||
<input type="file" accept="image/png" name="file" />
|
||||
<label for="file" style="@(ViewData.Keys.Contains("UploadException") ? "color: red" : "")">File must be a 64x64 PNG image</label>
|
||||
<input type="submit" value="Upload image" class="btn"/>
|
||||
<input type="submit" value="Update" />
|
||||
</form>
|
||||
</article>
|
||||
|
||||
<link type="text/css" rel="stylesheet" href="~/css/Admin.css" />
|
||||
@@ -4,31 +4,29 @@
|
||||
}
|
||||
|
||||
<header>
|
||||
<p> <a asp-action="Index" asp-controller="Admin" asp-area="">Back to main menu</a></p>
|
||||
 <a asp-action="Index" asp-controller="Admin" asp-area="">Back to main menu</a>
|
||||
<h1>Project badges list</h1>
|
||||
<p>
|
||||
<a asp-action="Create" class="comment">// + Create New</a>
|
||||
</p>
|
||||
</header>
|
||||
|
||||
<article>
|
||||
<table class="table">
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Preview</th>
|
||||
<th>
|
||||
<th class="hide-l2">
|
||||
@Html.DisplayNameFor(model => model.Name)
|
||||
</th>
|
||||
<th>
|
||||
@Html.DisplayNameFor(model => model.EnglishDescription)
|
||||
</th>
|
||||
<th>
|
||||
<th class="hide-l2">
|
||||
@Html.DisplayNameFor(model => model.RussianDescription)
|
||||
</th>
|
||||
<th>
|
||||
<th class="hide-l1">
|
||||
@Html.DisplayNameFor(model => model.Image)
|
||||
</th>
|
||||
<th></th>
|
||||
<th>Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@@ -38,10 +36,10 @@
|
||||
<td>
|
||||
<div class="badge" style="background-image: url(/images/Badges/@(item.Image).png)" title="@(item.Description)"></div>
|
||||
</td>
|
||||
<td>@item.Name</td>
|
||||
<td class="hide-l2">@item.Name</td>
|
||||
<td>@item.EnglishDescription</td>
|
||||
<td>@item.RussianDescription</td>
|
||||
<td>@item.Image</td>
|
||||
<td class="hide-l2">@item.RussianDescription</td>
|
||||
<td class="hide-l1">@item.Image</td>
|
||||
<td>
|
||||
<a asp-action="Edit" asp-route-id="@item.Name">Edit</a> |
|
||||
<a asp-action="Delete" asp-route-id="@item.Name">Delete</a>
|
||||
@@ -52,11 +50,110 @@
|
||||
</table>
|
||||
</article>
|
||||
|
||||
<link type="text/css" rel="stylesheet" href="~/css/Admin.css" />
|
||||
<style type="text/css">
|
||||
.badge {
|
||||
<header>
|
||||
<hr />
|
||||
<h1>Badge image files</h1>
|
||||
</header>
|
||||
|
||||
<article>
|
||||
<h2>Upload new badge image</h2>
|
||||
<form method="post" enctype="multipart/form-data">
|
||||
<div asp-validation-summary="All" class="text-danger"></div>
|
||||
<label for="badgeImage">Badge image file</label>
|
||||
<input name="badgeImage" type="file" required />
|
||||
<span>
|
||||
<b>Note:</b> Image should be exactly 64x64 pixels PNG file
|
||||
</span>
|
||||
<br />
|
||||
<button>Upload</button>
|
||||
</form>
|
||||
|
||||
<h2>Available badge images</h2>
|
||||
<table class="files-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Preview</th>
|
||||
<th>File name</th>
|
||||
<th>Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach (string path in System.IO.Directory.GetFiles(System.IO.Directory.GetCurrentDirectory() + "/wwwroot/images/Badges"))
|
||||
{
|
||||
string file = System.IO.Path.GetFileName(path);
|
||||
<tr>
|
||||
<td>
|
||||
<div class="badge" style="background-image: url(/images/Badges/@(file))" title="@(file)"></div>
|
||||
</td>
|
||||
<td>@file</td>
|
||||
<td>
|
||||
@if (Model.Any(i => i.Image + ".png" == file))
|
||||
{
|
||||
<span class="hide-l2" title="Delete or edit correlated badges linked with the image in order to delete it">No available actions</span>
|
||||
}
|
||||
else
|
||||
{
|
||||
<a asp-action="DeleteBadgeImage" asp-route-id="@file" onclick="return ConfirmDetetion('@file')">Delete</a>
|
||||
}
|
||||
</td>
|
||||
</tr>
|
||||
}
|
||||
</tbody>
|
||||
</table>
|
||||
</article>
|
||||
|
||||
|
||||
|
||||
@section Imports
|
||||
{
|
||||
<style type="text/css">
|
||||
.badge
|
||||
{
|
||||
height: 25px;
|
||||
width: 25px;
|
||||
background-size: contain;
|
||||
}
|
||||
</style>
|
||||
|
||||
.files-table
|
||||
{
|
||||
max-width: 500px;
|
||||
}
|
||||
|
||||
td span
|
||||
{
|
||||
color: gray;
|
||||
cursor: help;
|
||||
}
|
||||
td span:after
|
||||
{
|
||||
content: " (?)";
|
||||
}
|
||||
</style>
|
||||
<script type="text/javascript">
|
||||
function ConfirmDetetion(filename)
|
||||
{
|
||||
return confirm("Are you really want to delete \"" + filename + "\"? This action cannot be undone");
|
||||
}
|
||||
|
||||
function Upload()
|
||||
{
|
||||
var form = document.createElement("form");
|
||||
form.method = "post";
|
||||
form.hidden = true;
|
||||
|
||||
document.body.appendChild(form);
|
||||
|
||||
var input = document.createElement("input");
|
||||
input.type = "file";
|
||||
input.name = "badgeImage";
|
||||
input.click();
|
||||
|
||||
input.onchange = function ()
|
||||
{
|
||||
form.appendChild(input);
|
||||
|
||||
form.submit();
|
||||
}
|
||||
}
|
||||
</script>
|
||||
}
|
||||
@@ -1,30 +1,26 @@
|
||||
@model MyWebsite.Models.LinkModel
|
||||
|
||||
@{
|
||||
ViewData["Title"] = "Create link";
|
||||
}
|
||||
|
||||
<header>
|
||||
<p> <a asp-action="Index">Back to the list</a></p>
|
||||
 <a asp-action="Index">Back to the list</a>
|
||||
<h1>Create link</h1>
|
||||
</header>
|
||||
|
||||
<article>
|
||||
<form asp-action="Create">
|
||||
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
|
||||
<div asp-validation-summary="All" class="text-danger"></div>
|
||||
<input asp-for="Order" type="number" hidden value="-1" />
|
||||
<div>
|
||||
<label asp-for="Name"></label>
|
||||
<input asp-for="Name" type="text" />
|
||||
<a target="_blank" class="comment" href="//socicon.com/icons">// Socicon naming cheatsheet</a>
|
||||
<input asp-for="Name" type="text" required />
|
||||
<span asp-validation-for="Name" class="text-danger"></span>
|
||||
</div>
|
||||
<div>
|
||||
<label asp-for="Order"></label>
|
||||
<input asp-for="Order" type="number" />
|
||||
<span asp-validation-for="Order" class="text-danger"></span>
|
||||
</div>
|
||||
<div>
|
||||
<label asp-for="EnglishTitle"></label>
|
||||
<input asp-for="EnglishTitle" type="text" />
|
||||
<input asp-for="EnglishTitle" type="text" required />
|
||||
<span asp-validation-for="EnglishTitle" class="text-danger"></span>
|
||||
</div>
|
||||
<div>
|
||||
@@ -34,22 +30,23 @@
|
||||
</div>
|
||||
<div>
|
||||
<label asp-for="Username"></label>
|
||||
<input asp-for="Username" type="text" />
|
||||
<input asp-for="Username" type="text" required />
|
||||
<span asp-validation-for="Username" class="text-danger"></span>
|
||||
</div>
|
||||
<div>
|
||||
<label asp-for="Url"></label>
|
||||
<input asp-for="Url" type="text" />
|
||||
<input asp-for="Url" type="text" required />
|
||||
<span asp-validation-for="Url" class="text-danger"></span>
|
||||
</div>
|
||||
|
||||
<label asp-for="CanContactMe"></label>
|
||||
<input type="checkbox" class="checkbox" asp-for="CanContactMe" /> <br />
|
||||
<label asp-for="DisplayInFooter"></label>
|
||||
<div>
|
||||
<input type="checkbox" class="checkbox" asp-for="CanContactMe" />
|
||||
<label asp-for="CanContactMe"></label> <br />
|
||||
</div>
|
||||
<div>
|
||||
<input type="checkbox" class="checkbox" asp-for="DisplayInFooter" />
|
||||
<label asp-for="DisplayInFooter"></label>
|
||||
</div>
|
||||
|
||||
<input type="submit" value="Create" class="btn" />
|
||||
<input type="submit" value="Create" />
|
||||
</form>
|
||||
</article>
|
||||
|
||||
<link type="text/css" rel="stylesheet" href="~/css/Admin.css" />
|
||||
@@ -1,31 +1,28 @@
|
||||
@model MyWebsite.Models.LinkModel
|
||||
|
||||
@{
|
||||
ViewData["Title"] = "Delete link";
|
||||
}
|
||||
|
||||
<header>
|
||||
<p> <a asp-action="Index">Back to the list</a></p>
|
||||
 <a asp-action="Index">Back to the list</a>
|
||||
<h1>Delete link</h1>
|
||||
<h3>Are you sure you want to delete this?</h3>
|
||||
</header>
|
||||
|
||||
<article>
|
||||
<p class="form-group">
|
||||
<p>
|
||||
<b>@Html.DisplayNameFor(model => model.Name):</b> @Model.Name<br />
|
||||
<b>@Html.DisplayNameFor(model => model.Order):</b> @Model.Order<br />
|
||||
<b>@Html.DisplayNameFor(model => model.EnglishTitle):</b> @Model.EnglishTitle<br />
|
||||
<b>@Html.DisplayNameFor(model => model.RussianTitle):</b> @Model.RussianTitle<br />
|
||||
<b>@Html.DisplayNameFor(model => model.Username):</b> @Model.Username<br />
|
||||
<b>@Html.DisplayNameFor(model => model.Url):</b> @Model.Url<br />
|
||||
<b>@Html.DisplayNameFor(model => model.Url):</b> <a href="@Model.Url" target="_blank">@Model.Url</a><br />
|
||||
<b>@Html.DisplayNameFor(model => model.CanContactMe):</b> @Html.DisplayFor(model => model.CanContactMe)<br />
|
||||
<b>@Html.DisplayNameFor(model => model.DisplayInFooter):</b> @Html.DisplayFor(model => model.DisplayInFooter)
|
||||
</p>
|
||||
|
||||
<form asp-action="Delete">
|
||||
<input hidden asp-for="Name" />
|
||||
<input type="submit" value="Delete" class="btn-danger" />
|
||||
<input type="submit" value="Delete" required />
|
||||
</form>
|
||||
</article>
|
||||
|
||||
<link type="text/css" rel="stylesheet" href="~/css/Admin.css" />
|
||||
@@ -4,25 +4,21 @@
|
||||
}
|
||||
|
||||
<header>
|
||||
<p> <a asp-action="Index">Back to the list</a></p>
|
||||
 <a asp-action="Index">Back to the list</a>
|
||||
<h1>Edit link</h1>
|
||||
</header>
|
||||
|
||||
<article>
|
||||
<form asp-action="Edit">
|
||||
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
|
||||
<div asp-validation-summary="All" class="text-danger"></div>
|
||||
<input asp-for="Order" type="number" hidden />
|
||||
<div>
|
||||
<label asp-for="Name"></label>
|
||||
<input asp-for="Name" type="text" class="readonly" readonly />
|
||||
</div>
|
||||
<div>
|
||||
<label asp-for="Order"></label>
|
||||
<input asp-for="Order" type="number" />
|
||||
<span asp-validation-for="Order" class="text-danger"></span>
|
||||
<input asp-for="Name" type="text" readonly />
|
||||
</div>
|
||||
<div>
|
||||
<label asp-for="EnglishTitle"></label>
|
||||
<input asp-for="EnglishTitle" type="text" />
|
||||
<input asp-for="EnglishTitle" type="text" required />
|
||||
<span asp-validation-for="EnglishTitle" class="text-danger"></span>
|
||||
</div>
|
||||
<div>
|
||||
@@ -32,22 +28,23 @@
|
||||
</div>
|
||||
<div>
|
||||
<label asp-for="Username"></label>
|
||||
<input asp-for="Username" type="text" />
|
||||
<input asp-for="Username" type="text" required />
|
||||
<span asp-validation-for="Username" class="text-danger"></span>
|
||||
</div>
|
||||
<div>
|
||||
<label asp-for="Url"></label>
|
||||
<input asp-for="Url" type="text" />
|
||||
<input asp-for="Url" type="text" required />
|
||||
<span asp-validation-for="Url" class="text-danger"></span>
|
||||
</div>
|
||||
|
||||
<label asp-for="CanContactMe"></label>
|
||||
<input type="checkbox" class="checkbox" asp-for="CanContactMe" /> <br />
|
||||
<label asp-for="DisplayInFooter"></label>
|
||||
<div>
|
||||
<input type="checkbox" class="checkbox" asp-for="CanContactMe" />
|
||||
<label asp-for="CanContactMe"></label> <br />
|
||||
</div>
|
||||
<div>
|
||||
<input type="checkbox" class="checkbox" asp-for="DisplayInFooter" />
|
||||
<label asp-for="DisplayInFooter"></label>
|
||||
</div>
|
||||
|
||||
<input type="submit" value="Save" class="btn" />
|
||||
<input type="submit" value="Save" />
|
||||
</form>
|
||||
</article>
|
||||
|
||||
<link type="text/css" rel="stylesheet" href="~/css/Admin.css" />
|
||||
@@ -4,56 +4,58 @@
|
||||
}
|
||||
|
||||
<header>
|
||||
<p> <a asp-action="Index" asp-controller="Admin" asp-area="">Back to main menu</a></p>
|
||||
 <a asp-action="Index" asp-controller="Admin" asp-area="">Back to main menu</a>
|
||||
<h1>Links list</h1>
|
||||
<p>
|
||||
<a asp-action="Create" class="comment">// + Create New</a>
|
||||
</p>
|
||||
</header>
|
||||
|
||||
<article>
|
||||
<div asp-validation-summary="All" class="text-danger"></div>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Reorder</th>
|
||||
<th></th>
|
||||
<th>
|
||||
@Html.DisplayNameFor(model => model.Name)
|
||||
</th>
|
||||
<th>
|
||||
@Html.DisplayNameFor(model => model.EnglishTitle)
|
||||
<th class="hide-l2">
|
||||
@Html.DisplayNameFor(model => model.Title)
|
||||
</th>
|
||||
<th>
|
||||
@Html.DisplayNameFor(model => model.RussianTitle)
|
||||
</th>
|
||||
<th>
|
||||
<th class="hide-l1">
|
||||
@Html.DisplayNameFor(model => model.Username)
|
||||
</th>
|
||||
<th>
|
||||
<th class="hide-l2">
|
||||
@Html.DisplayNameFor(model => model.Url)
|
||||
</th>
|
||||
<th>
|
||||
<th class="hide-l1">
|
||||
@Html.DisplayNameFor(model => model.CanContactMe)
|
||||
</th>
|
||||
<th>
|
||||
<th class="hide-l1">
|
||||
@Html.DisplayNameFor(model => model.DisplayInFooter)
|
||||
</th>
|
||||
<th></th>
|
||||
<th>Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach (var item in Model.OrderBy(i => i.Order))
|
||||
{
|
||||
<tr draggable="true" ondragover="onDragOver(event);">
|
||||
<td></td>
|
||||
<tr id="@item.Name">
|
||||
<td class="reorderingBtns">
|
||||
<a onclick="Up(this)"></a><br />
|
||||
<span></span><br />
|
||||
<a onclick="Down(this)"></a>
|
||||
</td>
|
||||
<td>@item.Name</td>
|
||||
<td>@item.EnglishTitle</td>
|
||||
<td>@item.RussianTitle</td>
|
||||
<td>@item.Username</td>
|
||||
<td>@item.Url</td>
|
||||
<td>
|
||||
<td class="hide-l2">
|
||||
@item.EnglishTitle (en)<br />
|
||||
@(item.RussianTitle ?? "<not_set>") (ru)
|
||||
</td>
|
||||
<td class="hide-l1">@item.Username</td>
|
||||
<td class="hide-l2"><a target="_blank" href="@item.Url">@item.Url</a></td>
|
||||
<td class="hide-l1">
|
||||
@Html.DisplayFor(modelItem => item.CanContactMe)
|
||||
</td>
|
||||
<td>
|
||||
<td class="hide-l1">
|
||||
@Html.DisplayFor(modelItem => item.DisplayInFooter)
|
||||
</td>
|
||||
<td>
|
||||
@@ -64,12 +66,25 @@
|
||||
}
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<button onclick="ApplyReorder()" disabled>Apply reordering</button>
|
||||
</article>
|
||||
|
||||
<link type="text/css" rel="stylesheet" href="~/css/Admin.css" />
|
||||
<script type="text/javascript">
|
||||
function onDragOver(event)
|
||||
@section Imports
|
||||
{
|
||||
<style type="text/css">
|
||||
.reorderingBtns
|
||||
{
|
||||
this.style.marginTop = '20px';
|
||||
user-select: none;
|
||||
}
|
||||
</script>
|
||||
|
||||
.reorderingBtns a:hover
|
||||
{
|
||||
cursor: pointer;
|
||||
color: gray;
|
||||
text-decoration: underline;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script type="text/javascript" src="~/js/ReorderScript.js"></script>
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
@{
|
||||
ViewData["Title"] = "FoxTube";
|
||||
}
|
||||
|
||||
<header>
|
||||
<h1>FoxTube Backend control panel</h1>
|
||||
</header>
|
||||
|
||||
<article class="admin-menu">
|
||||
<p>
|
||||
<a asp-action="Gallery" class="comment">// Messages and changelogs</a><br />
|
||||
<a asp-action="Gallery" class="comment">// Recieved metrics</a>
|
||||
</p>
|
||||
<p>
|
||||
<a asp-action="Gallery" class="comment">// Privacy policies</a><br />
|
||||
<a asp-action="Gallery" class="comment">// Screenshots</a>
|
||||
</p>
|
||||
</article>
|
||||
@@ -4,13 +4,13 @@
|
||||
}
|
||||
|
||||
<header>
|
||||
<p> <a asp-action="Index">Back to the list</a></p>
|
||||
 <a asp-action="Index">Back to the list</a>
|
||||
<h1>Delete artwork</h1>
|
||||
<h3>Are you sure you want to delete this?</h3>
|
||||
</header>
|
||||
|
||||
<article class="image-overview-block">
|
||||
<img src="~/images/Gallery/@Model.FileName" onclick="ToggleImageSize();" id="image" />
|
||||
<img src="~/images/Gallery/@Model.FileName" onclick="ToggleImageSize();" />
|
||||
|
||||
<div>
|
||||
<p>
|
||||
@@ -25,10 +25,37 @@
|
||||
|
||||
<form asp-action="Delete">
|
||||
<input hidden asp-for="FileName" />
|
||||
<input type="submit" value="Delete" class="btn-danger" />
|
||||
<input type="submit" value="Delete" required />
|
||||
</form>
|
||||
</div>
|
||||
</article>
|
||||
|
||||
<link type="text/css" rel="stylesheet" href="~/css/Admin.css" />
|
||||
<link type="text/css" rel="stylesheet" href="~/css/Gallery.css" />
|
||||
@section Imports
|
||||
{
|
||||
<link type="text/css" rel="stylesheet" href="~/css/Gallery.css" />
|
||||
<style type="text/css">
|
||||
@@media only screen and (max-width: 500px)
|
||||
{
|
||||
.image-overview-block > div
|
||||
{
|
||||
margin: initial;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<script type="text/javascript">
|
||||
function ToggleImageSize()
|
||||
{
|
||||
var image = document.querySelector("img");
|
||||
|
||||
if (image.style.cursor == "zoom-out")
|
||||
image.style = "";
|
||||
else
|
||||
{
|
||||
image.style.maxHeight = "none";
|
||||
image.style.maxWidth = "none";
|
||||
image.style.cursor = "zoom-out";
|
||||
}
|
||||
}
|
||||
</script>
|
||||
}
|
||||
@@ -4,20 +4,20 @@
|
||||
}
|
||||
|
||||
<header>
|
||||
<p>
|
||||
 <a asp-action="Index">Back to the list</a> <br />
|
||||
 <a asp-action="Index">Back to the list</a>
|
||||
<h1>Edit artwork</h1>
|
||||
<a class="comment" href="~/images/Gallery/@(Model.FileName)" target="_blank">// Open artwork</a>
|
||||
</p>
|
||||
<a class="comment" href="~/images/Gallery/@(Model.FileName)" target="_blank">// Open artwork file</a>
|
||||
</header>
|
||||
|
||||
<article>
|
||||
<img src="~/images/Gallery/@Model.FileName" onclick="ToggleImageSize();" />
|
||||
|
||||
<form asp-action="Edit">
|
||||
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
|
||||
<input asp-for="FileName" hidden/>
|
||||
<div asp-validation-summary="All" class="text-danger"></div>
|
||||
<input asp-for="FileName" hidden />
|
||||
<div>
|
||||
<label asp-for="EnglishTitle"></label>
|
||||
<input asp-for="EnglishTitle" type="text" />
|
||||
<input asp-for="EnglishTitle" type="text" required/>
|
||||
<span asp-validation-for="EnglishTitle" class="text-danger"></span>
|
||||
</div>
|
||||
<div>
|
||||
@@ -37,12 +37,61 @@
|
||||
</div>
|
||||
<div>
|
||||
<label asp-for="CreationDate"></label>
|
||||
<input asp-for="CreationDate" type="date" />
|
||||
<input asp-for="CreationDate" type="date" required/>
|
||||
<span asp-validation-for="CreationDate" class="text-danger"></span>
|
||||
</div>
|
||||
|
||||
<input type="submit" value="Save" class="btn" />
|
||||
<input type="submit" value="Save" />
|
||||
</form>
|
||||
</article>
|
||||
|
||||
<link type="text/css" rel="stylesheet" href="~/css/Admin.css" />
|
||||
@section Imports
|
||||
{
|
||||
<script type="text/javascript">
|
||||
function ToggleImageSize()
|
||||
{
|
||||
var image = document.querySelector("img");
|
||||
|
||||
if (image.style.cursor == "zoom-out")
|
||||
image.style = "";
|
||||
else
|
||||
{
|
||||
image.style.maxHeight = "none";
|
||||
image.style.maxWidth = "none";
|
||||
image.style.cursor = "zoom-out";
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style type="text/css">
|
||||
article
|
||||
{
|
||||
display: grid;
|
||||
grid-template-columns: 500px 1fr;
|
||||
grid-column-gap: 20px;
|
||||
}
|
||||
|
||||
article img
|
||||
{
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
@@media only screen and (max-width: 1000px)
|
||||
{
|
||||
article
|
||||
{
|
||||
display: inherit;
|
||||
}
|
||||
}
|
||||
|
||||
form
|
||||
{
|
||||
max-width: initial;
|
||||
}
|
||||
|
||||
textarea
|
||||
{
|
||||
max-height: 250px;
|
||||
}
|
||||
</style>
|
||||
}
|
||||
@@ -4,11 +4,9 @@
|
||||
}
|
||||
|
||||
<header>
|
||||
<p> <a asp-action="Index" asp-controller="Admin" asp-area="">Back to main menu</a></p>
|
||||
 <a asp-action="Index" asp-controller="Admin" asp-area="">Back to main menu</a>
|
||||
<h1>Gallery</h1>
|
||||
<p>
|
||||
<a asp-action="Upload" class="comment">// + Upload new</a>
|
||||
</p>
|
||||
<a asp-action="Upload" class="comment">//  Upload new</a>
|
||||
</header>
|
||||
|
||||
<article>
|
||||
@@ -17,7 +15,9 @@
|
||||
{
|
||||
<tr>
|
||||
<td>
|
||||
<a asp-area="" asp-controller="Gallery" asp-action="Details" asp-route-id="@item.FileName" target="_blank">
|
||||
<img title="@item.Title" src="~/images/Gallery/@item.FileName" />
|
||||
</a>
|
||||
</td>
|
||||
<td>
|
||||
<p>
|
||||
@@ -25,8 +25,9 @@
|
||||
<span>File name: @item.FileName</span><br />
|
||||
<span>Creation date: @item.CreationDate.ToShortDateString()</span><br />
|
||||
<span>
|
||||
@Html.ActionLink("Edit", "Edit", new { id = item.FileName }) |
|
||||
@Html.ActionLink("Delete", "Delete", new { id = item.FileName })
|
||||
<a asp-action="Edit" asp-route-id="@item.FileName">Edit</a> |
|
||||
<a asp-action="Delete" asp-route-id="@item.FileName">Delete</a> |
|
||||
<a asp-area="" asp-controller="Gallery" asp-action="Details" asp-route-id="@item.FileName" target="_blank">View</a>
|
||||
</span>
|
||||
</p>
|
||||
</td>
|
||||
@@ -35,13 +36,18 @@
|
||||
</table>
|
||||
</article>
|
||||
|
||||
<link type="text/css" rel="stylesheet" href="~/css/Admin.css" />
|
||||
<style type="text/css">
|
||||
img {
|
||||
@section Imports
|
||||
{
|
||||
<style type="text/css">
|
||||
img
|
||||
{
|
||||
height: 200px;
|
||||
margin-right: 20px;
|
||||
}
|
||||
table {
|
||||
|
||||
table
|
||||
{
|
||||
width: initial;
|
||||
}
|
||||
</style>
|
||||
</style>
|
||||
}
|
||||
@@ -1,19 +1,23 @@
|
||||
@model ArtworkModel
|
||||
@model ImageModel
|
||||
@{
|
||||
ViewData["Title"] = "Upload artwork";
|
||||
}
|
||||
|
||||
<header>
|
||||
<p> <a asp-action="Index">Back to the list</a></p>
|
||||
 <a asp-action="Index">Back to the list</a>
|
||||
<h1>Upload an artwork</h1>
|
||||
</header>
|
||||
|
||||
<article>
|
||||
<form asp-action="Upload">
|
||||
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
|
||||
<form asp-action="Upload" enctype="multipart/form-data">
|
||||
<div>
|
||||
<label for="file">Artwork file</label>
|
||||
<input type="file" accept="image" name="File" required />
|
||||
</div>
|
||||
<div asp-validation-summary="All" class="text-danger"></div>
|
||||
<div>
|
||||
<label asp-for="EnglishTitle"></label>
|
||||
<input asp-for="EnglishTitle" type="text" />
|
||||
<input asp-for="EnglishTitle" type="text" required />
|
||||
<span asp-validation-for="EnglishTitle" class="text-danger"></span>
|
||||
</div>
|
||||
<div>
|
||||
@@ -33,17 +37,25 @@
|
||||
</div>
|
||||
<div>
|
||||
<label asp-for="CreationDate"></label>
|
||||
<input asp-for="CreationDate" type="date" />
|
||||
<input asp-for="CreationDate" type="date" required />
|
||||
<span asp-validation-for="CreationDate" class="text-danger"></span>
|
||||
</div>
|
||||
<div>
|
||||
<label asp-for="File"></label>
|
||||
<input type="file" accept="image" asp-for="File" />
|
||||
<span asp-validation-for="File" class="text-danger"></span>
|
||||
</div>
|
||||
|
||||
<input type="submit" value="Upload" class="btn" />
|
||||
<input type="submit" value="Upload" />
|
||||
</form>
|
||||
</article>
|
||||
|
||||
<link type="text/css" rel="stylesheet" href="~/css/Admin.css" />
|
||||
@section Imports
|
||||
{
|
||||
<style type="text/css">
|
||||
form
|
||||
{
|
||||
max-width: initial;
|
||||
}
|
||||
|
||||
textarea
|
||||
{
|
||||
max-height: 250px;
|
||||
}
|
||||
</style>
|
||||
}
|
||||
@@ -9,26 +9,22 @@
|
||||
</header>
|
||||
|
||||
<article>
|
||||
<form asp-action="Create">
|
||||
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
|
||||
<div>
|
||||
<label asp-for="Id"></label>
|
||||
<input asp-for="Id" type="number"/>
|
||||
<span asp-validation-for="Id" class="text-danger"></span>
|
||||
</div>
|
||||
<form asp-action="Create" onsubmit="ConfigureBadges()">
|
||||
<div asp-validation-summary="All" class="text-danger"></div>
|
||||
<input asp-for="Order" type="number" value="-1" hidden />
|
||||
<div>
|
||||
<label asp-for="EnglishTitle"></label>
|
||||
<input asp-for="EnglishTitle" type="text"/>
|
||||
<input asp-for="EnglishTitle" type="text" required />
|
||||
<span asp-validation-for="EnglishTitle" class="text-danger"></span>
|
||||
</div>
|
||||
<div>
|
||||
<label asp-for="RussianTitle"></label>
|
||||
<input asp-for="RussianTitle" type="text"/>
|
||||
<input asp-for="RussianTitle" type="text" />
|
||||
<span asp-validation-for="RussianTitle" class="text-danger"></span>
|
||||
</div>
|
||||
<div>
|
||||
<label asp-for="EnglishDescription"></label>
|
||||
<textarea asp-for="EnglishDescription"></textarea>
|
||||
<textarea asp-for="EnglishDescription" required></textarea>
|
||||
<span asp-validation-for="EnglishDescription" class="text-danger"></span>
|
||||
</div>
|
||||
<div>
|
||||
@@ -38,27 +34,74 @@
|
||||
</div>
|
||||
<div>
|
||||
<label asp-for="Link"></label>
|
||||
<input asp-for="Link" type="url"/>
|
||||
<input asp-for="Link" type="text" />
|
||||
<span asp-validation-for="Link" class="text-danger"></span>
|
||||
</div>
|
||||
<div>
|
||||
<label asp-for="EnglishLinkCaption"></label>
|
||||
<input asp-for="EnglishLinkCaption" type="text"/>
|
||||
<input asp-for="EnglishLinkCaption" type="text" />
|
||||
<span asp-validation-for="EnglishLinkCaption" class="text-danger"></span>
|
||||
</div>
|
||||
<div>
|
||||
<label asp-for="RussianLinkCaption"></label>
|
||||
<input asp-for="RussianLinkCaption" type="text"/>
|
||||
<input asp-for="RussianLinkCaption" type="text" />
|
||||
<span asp-validation-for="RussianLinkCaption" class="text-danger"></span>
|
||||
</div>
|
||||
<div>
|
||||
<label asp-for="Badges"></label>
|
||||
<input asp-for="Badges" type="text" />
|
||||
<input asp-for="Badges" type="text" id="badges" hidden />
|
||||
<span asp-validation-for="Badges" class="text-danger"></span>
|
||||
<div class="badge-list">
|
||||
@foreach (BadgeModel badge in ViewData["Badges"] as List<BadgeModel>)
|
||||
{
|
||||
<input type="checkbox" id="@badge.Name"/>
|
||||
<div class="badge" style="background-image: url('/images/Badges/@(badge?.Image).png')" title="@(badge?.Description)"></div>
|
||||
<span>@badge.Description</span><br />
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<input type="submit" value="Create" class="btn" />
|
||||
<input type="submit" value="Create" />
|
||||
</form>
|
||||
</article>
|
||||
|
||||
<link type="text/css" rel="stylesheet" href="~/css/Admin.css" />
|
||||
@section Imports
|
||||
{
|
||||
<script type="text/javascript">
|
||||
function ConfigureBadges()
|
||||
{
|
||||
var checkboxes = document.querySelectorAll(".badge-list input");
|
||||
var badges = [];
|
||||
for (var k = 0; k < checkboxes.length; k++)
|
||||
if (checkboxes[k].checked == true)
|
||||
badges[badges.length] = checkboxes[k].id;
|
||||
|
||||
document.querySelector("#badges").value = badges.join(",");
|
||||
}
|
||||
</script>
|
||||
|
||||
<style type="text/css">
|
||||
form
|
||||
{
|
||||
max-width: initial;
|
||||
}
|
||||
|
||||
textarea
|
||||
{
|
||||
max-height: 250px;
|
||||
}
|
||||
|
||||
.badge-list
|
||||
{
|
||||
margin: 10px 0px;
|
||||
}
|
||||
|
||||
.badge-list div
|
||||
{
|
||||
height: 25px;
|
||||
width: 25px;
|
||||
display: inline-block;
|
||||
background-size: contain;
|
||||
}
|
||||
</style>
|
||||
}
|
||||
@@ -4,28 +4,60 @@
|
||||
}
|
||||
|
||||
<header>
|
||||
<p> <a asp-action="Index">Back to the list</a></p>
|
||||
 <a asp-action="Index">Back to the list</a>
|
||||
<h1>Delete project entry</h1>
|
||||
<h3>Are you sure you want to delete this?</h3>
|
||||
</header>
|
||||
|
||||
<article>
|
||||
<p class="form-group">
|
||||
<p>
|
||||
<b>@Html.DisplayNameFor(model => model.Id):</b> @Model.Id<br />
|
||||
</p>
|
||||
<p>
|
||||
<b>@Html.DisplayNameFor(model => model.EnglishTitle):</b> @Model.EnglishTitle<br />
|
||||
<b>@Html.DisplayNameFor(model => model.RussianTitle):</b> @Model.RussianTitle<br />
|
||||
<b>@Html.DisplayNameFor(model => model.EnglishDescription):</b> @Model.EnglishDescription<br />
|
||||
<b>@Html.DisplayNameFor(model => model.RussianDescription):</b> @Model.RussianDescription<br />
|
||||
<b>@Html.DisplayNameFor(model => model.Link):</b> @Model.Link<br />
|
||||
</p>
|
||||
<p>
|
||||
<b>@Html.DisplayNameFor(model => model.EnglishLinkCaption):</b> @Model.EnglishLinkCaption<br />
|
||||
<b>@Html.DisplayNameFor(model => model.RussianLinkCaption):</b> @Model.RussianLinkCaption<br />
|
||||
</p>
|
||||
<p>
|
||||
<b>@Html.DisplayNameFor(model => model.Link):</b> <a target="_blank" href="@Model.Link">@Model.Link</a><br />
|
||||
</p>
|
||||
<p>
|
||||
<b>@Html.DisplayNameFor(model => model.Badges):</b> @Model.Badges<br />
|
||||
<div class="badge-placeholder">
|
||||
@foreach (string b in Model.Badges.Split(','))
|
||||
{
|
||||
BadgeModel badge = (ViewData["Badges"] as List<BadgeModel>).FirstOrDefault(i => i.Name == b);
|
||||
<div style="background-image: url('/images/Badges/@(badge?.Image).png')" title="@(badge?.Description)"></div>
|
||||
}
|
||||
</div>
|
||||
</p>
|
||||
|
||||
<form asp-action="Delete">
|
||||
<input hidden asp-for="Id" />
|
||||
<input type="submit" value="Delete" class="btn-danger" />
|
||||
<input type="submit" value="Delete" required />
|
||||
</form>
|
||||
</article>
|
||||
|
||||
<link type="text/css" rel="stylesheet" href="~/css/Admin.css" />
|
||||
@section Imports
|
||||
{
|
||||
<style type="text/css">
|
||||
.badge-placeholder
|
||||
{
|
||||
display: grid;
|
||||
grid-column-gap: 10px;
|
||||
grid-auto-columns: max-content;
|
||||
grid-auto-flow: column;
|
||||
}
|
||||
|
||||
.badge-placeholder div
|
||||
{
|
||||
height: 25px;
|
||||
width: 25px;
|
||||
display: inline-block;
|
||||
background-size: contain;
|
||||
}
|
||||
</style>
|
||||
}
|
||||
@@ -0,0 +1,111 @@
|
||||
@model MyWebsite.Models.ProjectModel
|
||||
@{
|
||||
ViewData["Title"] = "Edit";
|
||||
}
|
||||
|
||||
<header>
|
||||
 <a asp-action="Index">Back to the list</a>
|
||||
<h1>Edit project</h1>
|
||||
</header>
|
||||
|
||||
<article>
|
||||
<form asp-action="Edit" onsubmit="ConfigureBadges()">
|
||||
<div asp-validation-summary="All" class="text-danger"></div>
|
||||
<input asp-for="Order" type="number" hidden />
|
||||
<div>
|
||||
<label asp-for="Id"></label>
|
||||
<input asp-for="Id" type="text" readonly />
|
||||
</div>
|
||||
<div>
|
||||
<label asp-for="EnglishTitle"></label>
|
||||
<input asp-for="EnglishTitle" type="text" required />
|
||||
<span asp-validation-for="EnglishTitle" class="text-danger"></span>
|
||||
</div>
|
||||
<div>
|
||||
<label asp-for="RussianTitle"></label>
|
||||
<input asp-for="RussianTitle" type="text" />
|
||||
<span asp-validation-for="RussianTitle" class="text-danger"></span>
|
||||
</div>
|
||||
<div>
|
||||
<label asp-for="EnglishDescription"></label>
|
||||
<textarea asp-for="EnglishDescription" required></textarea>
|
||||
<span asp-validation-for="EnglishDescription" class="text-danger"></span>
|
||||
</div>
|
||||
<div>
|
||||
<label asp-for="RussianDescription"></label>
|
||||
<textarea asp-for="RussianDescription"></textarea>
|
||||
<span asp-validation-for="RussianDescription" class="text-danger"></span>
|
||||
</div>
|
||||
<div>
|
||||
<label asp-for="Link"></label>
|
||||
<input asp-for="Link" type="text" />
|
||||
<span asp-validation-for="Link" class="text-danger"></span>
|
||||
</div>
|
||||
<div>
|
||||
<label asp-for="EnglishLinkCaption"></label>
|
||||
<input asp-for="EnglishLinkCaption" type="text" />
|
||||
<span asp-validation-for="EnglishLinkCaption" class="text-danger"></span>
|
||||
</div>
|
||||
<div>
|
||||
<label asp-for="RussianLinkCaption"></label>
|
||||
<input asp-for="RussianLinkCaption" type="text" />
|
||||
<span asp-validation-for="RussianLinkCaption" class="text-danger"></span>
|
||||
</div>
|
||||
<div>
|
||||
<label asp-for="Badges"></label>
|
||||
<input asp-for="Badges" type="text" id="badges" hidden />
|
||||
<span asp-validation-for="Badges" class="text-danger"></span>
|
||||
<div class="badge-list">
|
||||
@foreach (BadgeModel badge in ViewData["Badges"] as List<BadgeModel>)
|
||||
{
|
||||
<input type="checkbox" id="@badge.Name" checked="@(Model.Badges.Split(',').Contains(badge.Name))"/>
|
||||
<div class="badge" style="background-image: url('/images/Badges/@(badge?.Image).png')" title="@(badge?.Description)"></div>
|
||||
<span>@badge.Description</span><br />
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<input type="submit" value="Save" />
|
||||
</form>
|
||||
</article>
|
||||
|
||||
@section Imports
|
||||
{
|
||||
<script type="text/javascript">
|
||||
function ConfigureBadges()
|
||||
{
|
||||
var checkboxes = document.querySelectorAll(".badge-list input");
|
||||
var badges = [];
|
||||
for (var k = 0; k < checkboxes.length; k++)
|
||||
if (checkboxes[k].checked == true)
|
||||
badges[badges.length] = checkboxes[k].id;
|
||||
|
||||
document.querySelector("#badges").value = badges.join(",");
|
||||
}
|
||||
</script>
|
||||
|
||||
<style type="text/css">
|
||||
form
|
||||
{
|
||||
max-width: initial;
|
||||
}
|
||||
|
||||
textarea
|
||||
{
|
||||
max-height: 250px;
|
||||
}
|
||||
|
||||
.badge-list
|
||||
{
|
||||
margin: 10px 0px;
|
||||
}
|
||||
|
||||
.badge-list div
|
||||
{
|
||||
height: 25px;
|
||||
width: 25px;
|
||||
display: inline-block;
|
||||
background-size: contain;
|
||||
}
|
||||
</style>
|
||||
}
|
||||
@@ -4,48 +4,61 @@
|
||||
}
|
||||
|
||||
<header>
|
||||
<p> <a asp-action="Index" asp-controller="Admin" asp-area="">Back to main menu</a></p>
|
||||
 <a asp-action="Index" asp-controller="Admin" asp-area="">Back to main menu</a>
|
||||
<h1>Projects list</h1>
|
||||
<p>
|
||||
<a asp-action="Create" class="comment">// + Add New</a>
|
||||
</p>
|
||||
<a asp-action="Create" class="comment">// + Add new project</a>
|
||||
</header>
|
||||
|
||||
<article>
|
||||
<div asp-validation-summary="All" class="text-danger"></div>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>
|
||||
<th></th>
|
||||
<th class="hide-l1">
|
||||
@Html.DisplayNameFor(model => model.projects.First().Id)
|
||||
</th>
|
||||
<th>
|
||||
@Html.DisplayNameFor(model => model.projects.First().EnglishTitle)
|
||||
@Html.DisplayNameFor(model => model.projects.First().Title)
|
||||
</th>
|
||||
<th>
|
||||
@Html.DisplayNameFor(model => model.projects.First().RussianTitle)
|
||||
<th class="hide-l1">
|
||||
@Html.DisplayNameFor(model => model.projects.First().LinkCaption)
|
||||
</th>
|
||||
<th>
|
||||
<th class="hide-l2">
|
||||
@Html.DisplayNameFor(model => model.projects.First().Link)
|
||||
</th>
|
||||
<th>
|
||||
<th class="hide-l2">
|
||||
@Html.DisplayNameFor(model => model.projects.First().Badges)
|
||||
(<a asp-controller="Badges" asp-action="Index">Edit badges</a>)
|
||||
</th>
|
||||
<th></th>
|
||||
<th>Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach (var item in Model.projects.OrderByDescending(i => i.Id))
|
||||
@foreach (var item in Model.projects.OrderBy(i => i.Order))
|
||||
{
|
||||
<tr>
|
||||
<td>@item.Id</td>
|
||||
<td>@item.EnglishTitle</td>
|
||||
<td>@item.RussianTitle</td>
|
||||
<td>@item.Link</td>
|
||||
<tr id="@item.Id">
|
||||
<td class="reorderingBtns">
|
||||
<a onclick="Up(this)"></a><br />
|
||||
<span></span><br />
|
||||
<a onclick="Down(this)"></a>
|
||||
</td>
|
||||
<td class="hide-l1">@item.Id</td>
|
||||
<td>
|
||||
@item.EnglishTitle (en)<br />
|
||||
@(item.RussianTitle ?? "<not_set>") (ru)
|
||||
</td>
|
||||
<td class="hide-l1">
|
||||
@(item.EnglishLinkCaption ?? "<not_set>") (en)<br />
|
||||
@(item.RussianLinkCaption ?? "<not_set>") (ru)
|
||||
</td>
|
||||
<td class="hide-l2"><a target="_blank" href="@item.Link">@item.Link</a></td>
|
||||
<td class="hide-l2">
|
||||
<div class="badge-placeholder">
|
||||
@foreach (string badge in item.Badges.Split(','))
|
||||
@foreach (string b in item.Badges.Split(','))
|
||||
{
|
||||
<div style="background-image: @("../images/Badges/" + Model.badges.FirstOrDefault(i => i.Name == badge)?.Image + ".png")" title="@(Model.badges.FirstOrDefault(i => i.Name == badge)?.Description)"></div>
|
||||
BadgeModel badge = Model.badges.FirstOrDefault(i => i.Name == b);
|
||||
<div style="background-image: url('../images/Badges/@(badge?.Image).png')" title="@(badge?.Description)"></div>
|
||||
}
|
||||
</div>
|
||||
</td>
|
||||
@@ -57,10 +70,13 @@
|
||||
}
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<button onclick="ApplyReorder()" disabled>Apply reordering</button>
|
||||
</article>
|
||||
|
||||
<link type="text/css" rel="stylesheet" href="~/css/Admin.css" />
|
||||
<style type="text/css">
|
||||
@section Imports
|
||||
{
|
||||
<style type="text/css">
|
||||
.badge-placeholder
|
||||
{
|
||||
display: grid;
|
||||
@@ -76,4 +92,19 @@
|
||||
display: inline-block;
|
||||
background-size: contain;
|
||||
}
|
||||
</style>
|
||||
|
||||
.reorderingBtns
|
||||
{
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.reorderingBtns a:hover
|
||||
{
|
||||
cursor: pointer;
|
||||
color: gray;
|
||||
text-decoration: underline;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script type="text/javascript" src="~/js/ReorderScript.js"></script>
|
||||
}
|
||||
@@ -1,39 +1,48 @@
|
||||
@using System.Globalization
|
||||
@model MyWebsite.Models.ResumeModel
|
||||
@{
|
||||
ViewData["Title"] = "Create resume";
|
||||
ViewData["Title"] = "Create " + (ViewData["Caption"] ?? "resume");
|
||||
}
|
||||
|
||||
<header>
|
||||
<p> <a asp-action="Index">Back to the list</a></p>
|
||||
<h1>Create resume</h1>
|
||||
 <a asp-action="Index">Back to the list</a>
|
||||
<h1>Create @(ViewData["Caption"] ?? "resume")</h1>
|
||||
</header>
|
||||
|
||||
<article>
|
||||
<form asp-action="Create">
|
||||
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
|
||||
<form method="post">
|
||||
<div asp-validation-summary="All" class="text-danger"></div>
|
||||
<div>
|
||||
<label asp-for="Language"></label>
|
||||
<input type="text" asp-for="Language"/>
|
||||
<select asp-for="Language" required>
|
||||
@foreach (var culture in CultureInfo.GetCultures(CultureTypes.NeutralCultures))
|
||||
{
|
||||
<option value="@culture.Name">@culture.EnglishName</option>
|
||||
}
|
||||
</select>
|
||||
<span asp-validation-for="Language" class="text-danger"></span>
|
||||
</div>
|
||||
<div>
|
||||
<label asp-for="Content"></label>
|
||||
<textarea asp-for="Content" spellcheck="false"></textarea>
|
||||
<textarea asp-for="Content" spellcheck="false" required></textarea>
|
||||
<span asp-validation-for="Content" class="text-danger"></span>
|
||||
</div>
|
||||
<br />
|
||||
<input type="submit" value="Save" class="btn"/>
|
||||
<input type="submit" value="Save" />
|
||||
</form>
|
||||
</article>
|
||||
|
||||
<link type="text/css" rel="stylesheet" href="~/css/Admin.css" />
|
||||
<style type="text/css">
|
||||
form {
|
||||
@section Imports
|
||||
{
|
||||
<style type="text/css">
|
||||
form
|
||||
{
|
||||
max-width: initial;
|
||||
}
|
||||
|
||||
textarea {
|
||||
textarea
|
||||
{
|
||||
min-height: 500px;
|
||||
}
|
||||
</style>
|
||||
</style>
|
||||
}
|
||||
@@ -1,24 +1,22 @@
|
||||
@model MyWebsite.Models.ResumeModel
|
||||
@{
|
||||
ViewData["Title"] = "Delete resume";
|
||||
ViewData["Title"] = "Delete " + (ViewData["Caption"] ?? "resume");
|
||||
}
|
||||
|
||||
<header>
|
||||
<p> <a asp-action="Index">Back to the list</a></p>
|
||||
<h1>Delete resume</h1>
|
||||
 <a asp-action="Index">Back to the list</a>
|
||||
<h1>Delete @(ViewData["Caption"] ?? "resume")</h1>
|
||||
<h3>Are you sure you want to delete this?</h3>
|
||||
</header>
|
||||
|
||||
<article>
|
||||
<p class="form-group">
|
||||
<p>
|
||||
<b>@Html.DisplayNameFor(model => model.Language):</b> @(new System.Globalization.CultureInfo(Model.Language).DisplayName)<br />
|
||||
<b>@Html.DisplayNameFor(model => model.LastUpdate):</b> @Model.LastUpdate<br />
|
||||
</p>
|
||||
|
||||
<form asp-action="Delete">
|
||||
<form method="post">
|
||||
<input hidden asp-for="Language" />
|
||||
<input type="submit" value="Delete" class="btn-danger" />
|
||||
<input type="submit" value="Delete" required />
|
||||
</form>
|
||||
</article>
|
||||
|
||||
<link type="text/css" rel="stylesheet" href="~/css/Admin.css" />
|
||||
@@ -1,50 +1,56 @@
|
||||
@model MyWebsite.Models.ResumeModel
|
||||
|
||||
@{
|
||||
ViewData["Title"] = "Edit resume";
|
||||
ViewData["Title"] = "Edit " + (ViewData["Caption"] ?? "resume");
|
||||
}
|
||||
|
||||
<header>
|
||||
<p> <a asp-action="Index">Back to the list</a></p>
|
||||
<h1>Edit resume</h1>
|
||||
<p>
|
||||
 <a asp-action="Index">Back to the list</a>
|
||||
<h1>Edit @(ViewData["Caption"] ?? "resume")</h1>
|
||||
Language: @(new System.Globalization.CultureInfo(Model.Language).DisplayName)<br />
|
||||
Previously updated on @Model.LastUpdate
|
||||
</p>
|
||||
Previously updated on @Model.LastUpdate<br />
|
||||
|
||||
<a class="comment" onclick="CopyToClipboard()">//  Copy to clipboard</a>
|
||||
</header>
|
||||
|
||||
<article>
|
||||
<form asp-action="Edit">
|
||||
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
|
||||
<form method="post">
|
||||
<div asp-validation-summary="All" class="text-danger"></div>
|
||||
<input type="text" asp-for="Language" hidden />
|
||||
<div>
|
||||
<textarea asp-for="Content" spellcheck="false"></textarea>
|
||||
<a class="comment" onclick="CopyToClipboard()" href="#">//  Copy to clipboard</a>
|
||||
<span style="display: none" id="copied"> - Done</span><br />
|
||||
|
||||
<textarea asp-for="Content" spellcheck="false" required></textarea>
|
||||
<span asp-validation-for="Content" class="text-danger"></span>
|
||||
</div>
|
||||
|
||||
<br />
|
||||
<input type="submit" value="Save" class=" btn" />
|
||||
<input type="submit" value="Save" />
|
||||
</form>
|
||||
</article>
|
||||
|
||||
<link type="text/css" rel="stylesheet" href="~/css/Admin.css" />
|
||||
<style type="text/css">
|
||||
form {
|
||||
@section Imports
|
||||
{
|
||||
<style type="text/css">
|
||||
form
|
||||
{
|
||||
max-width: initial;
|
||||
}
|
||||
textarea {
|
||||
|
||||
header .comment
|
||||
{
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
textarea
|
||||
{
|
||||
min-height: 500px;
|
||||
}
|
||||
</style>
|
||||
<script type="text/javascript">
|
||||
async function CopyToClipboard() {
|
||||
text = document.getElementById("Content");
|
||||
text.select();
|
||||
</style>
|
||||
<script type="text/javascript">
|
||||
function CopyToClipboard()
|
||||
{
|
||||
document.querySelector("textarea").select();
|
||||
document.execCommand("copy");
|
||||
window.getSelection().removeAllRanges();
|
||||
document.getElementById("copied").style.display = "initial";
|
||||
await new Promise(res => setTimeout(res, 3000));
|
||||
document.getElementById("copied").style.display = "none";
|
||||
document.getSelection().removeAllRanges();
|
||||
|
||||
alert("CV content copied");
|
||||
}
|
||||
</script>
|
||||
</script>
|
||||
}
|
||||
@@ -1,15 +1,12 @@
|
||||
@model IEnumerable<MyWebsite.Models.ResumeModel>
|
||||
|
||||
@{
|
||||
ViewData["Title"] = "Resumes";
|
||||
}
|
||||
|
||||
<header>
|
||||
<p> <a asp-action="Index" asp-controller="Admin" asp-area="">Back to main menu</a></p>
|
||||
 <a asp-action="Index" asp-controller="Admin" asp-area="">Back to main menu</a>
|
||||
<h1>Resumes list</h1>
|
||||
<p>
|
||||
<a asp-action="Create" class="comment">// + Create New</a>
|
||||
</p>
|
||||
</header>
|
||||
|
||||
<article>
|
||||
@@ -22,7 +19,7 @@
|
||||
<th>
|
||||
@Html.DisplayNameFor(model => model.LastUpdate)
|
||||
</th>
|
||||
<th></th>
|
||||
<th>Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@@ -40,5 +37,3 @@
|
||||
</tbody>
|
||||
</table>
|
||||
</article>
|
||||
|
||||
<link type="text/css" rel="stylesheet" href="~/css/Admin.css" />
|
||||
@@ -1,69 +1,78 @@
|
||||
@model MyWebsite.Areas.Admin.Models.CredentialModel
|
||||
@{
|
||||
@{
|
||||
ViewData["Title"] = "Edit credential";
|
||||
}
|
||||
|
||||
<header>
|
||||
<p> <a asp-action="Index" asp-controller="Admin" asp-area="">Back to main menu</a></p>
|
||||
 <a asp-action="Index" asp-controller="Admin" asp-area="">Back to main menu</a>
|
||||
<h1>Change credential information</h1>
|
||||
</header>
|
||||
|
||||
<article>
|
||||
<form asp-action="Index" onsubmit="return Validate();">
|
||||
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
|
||||
<p>
|
||||
<label asp-for="Updated.Email">New e-mail:</label>
|
||||
<input asp-for="Updated.Email" id="new-email" type="email" />
|
||||
<span asp-validation-for="Updated.Email" class="text-danger" id="email-validation"></span><br />
|
||||
<h2>Change e-mail</h2>
|
||||
<div asp-validation-summary="All" class="text-danger"></div>
|
||||
<form method="post" onsubmit="return ValidateEmail()">
|
||||
<label for="value">New e-mail:</label>
|
||||
<input name="value" id="newEmail" type="email" placeholder="user@example.com" required />
|
||||
|
||||
<label>Confirm e-mail:</label>
|
||||
<input id="confirm-email" type="email" />
|
||||
</p>
|
||||
<p>
|
||||
<label asp-for="Updated.Password">New password:</label>
|
||||
<input asp-for="Updated.Password" id="new-password" type="password" />
|
||||
<span asp-validation-for="Updated.Password" class="text-danger" id="password-validation"></span><br />
|
||||
<input id="confirmEmail" type="email" placeholder="user@example.com" required />
|
||||
|
||||
<span class="text-danger" id="emailValidationError"></span>
|
||||
|
||||
<input name="key" value="email" hidden />
|
||||
<button>Update e-mail</button>
|
||||
</form>
|
||||
|
||||
<h2>Change password</h2>
|
||||
<form method="post" onsubmit="return ValidatePassword()">
|
||||
<label for="value">New password:</label>
|
||||
<input name="value" id="newPassword" type="password" required />
|
||||
|
||||
|
||||
<label>Confirm password:</label>
|
||||
<input id="confirm-password" type="password" />
|
||||
</p>
|
||||
<p>
|
||||
<label asp-for="Current.Email">Current e-mail:</label>
|
||||
<input asp-for="Current.Email" type="email" />
|
||||
<span asp-validation-for="Current.Email" class="text-danger"></span><br />
|
||||
<label asp-for="Current.Password">Current password:</label>
|
||||
<input asp-for="Current.Password" type="password" />
|
||||
<span asp-validation-for="Current.Password" class="text-danger"></span>
|
||||
</p>
|
||||
<input type="submit" value="Update" />
|
||||
<input id="confirmPassword" type="password" required />
|
||||
|
||||
<span class="text-danger" id="passwordValidationError"></span>
|
||||
|
||||
<input name="key" value="password" hidden />
|
||||
<button>Update password</button>
|
||||
</form>
|
||||
</article>
|
||||
|
||||
<link href="~/css/Admin.css" type="text/css" rel="stylesheet" />
|
||||
|
||||
<script type="text/javascript">
|
||||
var newEmail = document.getElementById("new-email");
|
||||
var confirmEmail = document.getElementById("confirm-email");
|
||||
var newPassword = document.getElementById("new-password");
|
||||
var confirmPassword = document.getElementById("confirm-password");
|
||||
var emailValidation = document.getElementById("email-validation");
|
||||
var passwordValidation = document.getElementById("password-validation");
|
||||
|
||||
function Validate()
|
||||
@section Imports
|
||||
{
|
||||
<script type="text/javascript">
|
||||
function ValidateEmail()
|
||||
{
|
||||
var invalid = false;
|
||||
var newEmail = document.querySelector("#newEmail");
|
||||
var confirmEmail = document.querySelector("#confirmEmail");
|
||||
|
||||
var emailValidation = document.querySelector("#emailValidationError");
|
||||
|
||||
emailValidation.innerHTML = "";
|
||||
|
||||
if (newEmail.value == confirmEmail.value)
|
||||
return true;
|
||||
|
||||
emailValidation.innerHTML = "E-mail addresses are invalid or doesn't match";
|
||||
return false;
|
||||
}
|
||||
|
||||
function ValidatePassword()
|
||||
{
|
||||
var newPassword = document.querySelector("#newPassword");
|
||||
var confirmPassword = document.querySelector("#confirmPassword");
|
||||
|
||||
var passwordValidation = document.querySelector("#passwordValidationError");
|
||||
|
||||
passwordValidation.innerHTML = "";
|
||||
|
||||
if (newEmail.value != "" && newEmail.value != confirmEmail.value)
|
||||
{
|
||||
emailValidation.innerHTML = "Addresses don't match";
|
||||
invalid = true;
|
||||
}
|
||||
if (newPassword.value != "" && newPassword.value != confirmPassword.value)
|
||||
{
|
||||
passwordValidation.innerHTML = "Passwords don't match";
|
||||
invalid = true;
|
||||
}
|
||||
if (newPassword.value == confirmPassword.value)
|
||||
return true;
|
||||
|
||||
return !invalid;
|
||||
passwordValidation.innerHTML = "Passwords doesn't match";
|
||||
return false;
|
||||
}
|
||||
</script>
|
||||
</script>
|
||||
}
|
||||
@@ -1,22 +1,49 @@
|
||||
@model CustomData
|
||||
@{
|
||||
ViewData["Title"] = "GUTSchedule";
|
||||
IEnumerable<ResumeModel> policies = ViewData["Policies"] as IEnumerable<ResumeModel>;
|
||||
}
|
||||
|
||||
<header>
|
||||
<p> <a asp-action="Index" asp-controller="Admin" asp-area="">Back to main menu</a></p>
|
||||
 <a asp-action="Index" asp-controller="Admin" asp-area="">Back to main menu</a>
|
||||
<h1>GUTSchedule</h1>
|
||||
</header>
|
||||
|
||||
<article>
|
||||
<div asp-validation-summary="All" class="text-danger"></div>
|
||||
|
||||
<h2>Offset dates</h2>
|
||||
<form asp-action="Index">
|
||||
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
|
||||
<input asp-for="Key" hidden />
|
||||
<label asp-for="Value">First work day in the semester: (Current: @Model.Value)</label>
|
||||
<input asp-for="Key" value="offset" hidden />
|
||||
<label asp-for="Value">First work day in the semester: (Current: @Model?.Value)</label>
|
||||
<input type="number" asp-for="Value" />
|
||||
<span asp-validation-for="Value" class="text-danger"></span>
|
||||
<input type="submit" value="Update" class="btn"/>
|
||||
<input type="submit" value="Update" />
|
||||
</form>
|
||||
</article>
|
||||
|
||||
<link href="~/css/Admin.css" type="text/css" rel="stylesheet" />
|
||||
<h2>Privacy policies</h2>
|
||||
<a class="comment" asp-action="PrivacyPolicy" target="_blank">// View privacy policy page</a><br />
|
||||
<a class="comment" asp-action="CreatePolicy">// + Add new privacy policy</a>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Langauge</th>
|
||||
<th>Last update</th>
|
||||
<th>Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach (ResumeModel item in policies)
|
||||
{
|
||||
<tr>
|
||||
<td>@item.Language</td>
|
||||
<td>@item.LastUpdate</td>
|
||||
<td>
|
||||
<a asp-action="EditPolicy" asp-route-id="@item.Language">Edit</a> |
|
||||
<a asp-action="DeletePolicy" asp-route-id="@item.Language">Delete</a>
|
||||
</td>
|
||||
</tr>
|
||||
}
|
||||
</tbody>
|
||||
</table>
|
||||
</article>
|
||||
@@ -0,0 +1,74 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>@ViewData["Title"] - Admin pangel - XFox111.NET</title>
|
||||
<link rel="shortcut icon" href="~/favicon.ico" type="image/x-icon" />
|
||||
|
||||
<link rel="stylesheet" type="text/css" href="~/css/Style.css" />
|
||||
<link rel="stylesheet" type="text/css" href="~/css/Fonts.css" />
|
||||
<link rel="stylesheet" href="https://s3.amazonaws.com/icomoon.io/114779/Socicon/style.css?u8vidh" />
|
||||
<link href="~/css/Admin.css" type="text/css" rel="stylesheet" />
|
||||
|
||||
<script type="text/javascript">
|
||||
function ToggleMenu()
|
||||
{
|
||||
var menu = document.getElementById("main-menu");
|
||||
|
||||
if (menu.style.display == "none")
|
||||
menu.style.display = "initial";
|
||||
else
|
||||
menu.style.display = "none";
|
||||
}
|
||||
</script>
|
||||
|
||||
@RenderSection("Imports", false)
|
||||
|
||||
@{
|
||||
if (IsSectionDefined("OpenGraph"))
|
||||
RenderSection("OpenGraph");
|
||||
else
|
||||
{
|
||||
<meta name="author" content="Michael 'XFox' Gordeev" />
|
||||
<meta name="description" content="Hi, my name is Michael. I'm C# Developer and this is my personal website. Here you can find info about me, my projects and more. Check it out!" />
|
||||
|
||||
<meta property="og:type" content="website" />
|
||||
<meta property="og:site_name" content="XFox111.NET" />
|
||||
<meta property="og:url" content="//XFox111.NET/" />
|
||||
<meta property="og:locale" content="en_US" />
|
||||
<meta property="og:image" content="/images/me.png" />
|
||||
<meta property="og:description" content="Hi, my name is Michael. I'm C# Developer and this is my personal website. Here you can find info about me, my projects and more. Check it out!" />
|
||||
<meta property="og:title" content="Michael 'XFox' Gordeev - Personal website" />
|
||||
}
|
||||
}
|
||||
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
</head>
|
||||
<body>
|
||||
<nav>
|
||||
<a asp-controller="Home" asp-action="Index" asp-area="">XFox111.NET</a>
|
||||
|
||||
<menu type="toolbar" id="main-menu" style="display:none">
|
||||
<li><a asp-area="" asp-controller="Home" asp-action="Index">AboutMe();</a></li>
|
||||
<li><a href="//xfox111.blogspot.com/" target="_blank">MyBlog();</a></li>
|
||||
<li><a asp-area="" asp-controller="Resume" asp-action="Index">Resume();</a></li>
|
||||
<li><a asp-area="" asp-controller="Projects" asp-action="Index">Projects();</a></li>
|
||||
<li><a asp-area="" asp-controller="Gallery" asp-action="Index">Arts();</a></li>
|
||||
<li><a asp-area="" asp-controller="Contacts" asp-action="Index">Contacts();</a></li>
|
||||
</menu>
|
||||
|
||||
<div>
|
||||
<a asp-controller="Home" asp-action="SwitchLanguage" lang="ru">РУС </a>
|
||||
<a id="menu-toggle" onclick="ToggleMenu();"></a>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<main onclick="document.querySelector('#main-menu').style.display = 'none'">
|
||||
@RenderBody()
|
||||
</main>
|
||||
|
||||
<footer>
|
||||
<span class="comment">// Copyright ©@(DateTime.Today.Year) Michael "XFox" Gordeev</span>
|
||||
</footer>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,5 +1,4 @@
|
||||
@using MyWebsite
|
||||
@using MyWebsite.Models
|
||||
@using MyWebsite.ViewModels
|
||||
@using MyWebsite.Areas.Admin.Models
|
||||
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
|
||||
|
||||
@@ -13,13 +13,13 @@ namespace MyWebsite.Areas.Projects.Controllers
|
||||
[Area("Projects")]
|
||||
public class FoxTubeController : ExtendedController
|
||||
{
|
||||
readonly DatabaseContext db;
|
||||
readonly List<string> paths = new List<string>();
|
||||
readonly List<string> files;
|
||||
public FoxTubeController(DatabaseContext context) : base(context)
|
||||
{
|
||||
db = context;
|
||||
private FoxTubeDatabaseContext FoxTubeDatabaseContext { get; set; }
|
||||
|
||||
public FoxTubeController(DatabaseContext context, FoxTubeDatabaseContext foxTubeDatabase) : base(context)
|
||||
{
|
||||
FoxTubeDatabaseContext = foxTubeDatabase;
|
||||
Scan(Directory.GetCurrentDirectory() + "\\wwwroot\\assets\\FoxTube\\Screenshots\\" + CultureInfo.CurrentUICulture.ThreeLetterISOLanguageName, paths);
|
||||
|
||||
for (int i = 0; i < paths.Count; i++)
|
||||
@@ -29,14 +29,14 @@ namespace MyWebsite.Areas.Projects.Controllers
|
||||
}
|
||||
|
||||
public IActionResult Index() =>
|
||||
View(new ScreenshotViewModel(db)
|
||||
View(new ScreenshotViewModel(Database)
|
||||
{
|
||||
Paths = paths,
|
||||
Names = files
|
||||
});
|
||||
|
||||
public IActionResult Screenshot(string id) =>
|
||||
View(new ScreenshotViewModel(db)
|
||||
View(new ScreenshotViewModel(Database)
|
||||
{
|
||||
Paths = paths,
|
||||
Names = files,
|
||||
@@ -44,7 +44,7 @@ namespace MyWebsite.Areas.Projects.Controllers
|
||||
});
|
||||
|
||||
public IActionResult Privacy() =>
|
||||
View(new ResumeViewModel(db, CultureInfo.CurrentCulture));
|
||||
View(new ResumeViewModel(FoxTubeDatabaseContext.PrivacyPolicies.Find(CultureInfo.CurrentCulture.TwoLetterISOLanguageName) ?? FoxTubeDatabaseContext.PrivacyPolicies.Find("en"), Database));
|
||||
|
||||
void Scan(string path, List<string> files)
|
||||
{
|
||||
|
||||
@@ -22,9 +22,7 @@
|
||||
</ul>
|
||||
|
||||
<h1>Trailer</h1>
|
||||
<div>
|
||||
<iframe width="560" height="315" src="https://www.youtube.com/embed/Mio9FbxmbhM" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
|
||||
</div>
|
||||
<iframe class="video" src="https://www.youtube.com/embed/Mio9FbxmbhM" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
|
||||
|
||||
<h1>Description</h1>
|
||||
<p>
|
||||
|
||||
@@ -5,9 +5,9 @@
|
||||
}
|
||||
|
||||
<header>
|
||||
<p> <a asp-action="Index">Back to description</a></p>
|
||||
 <a asp-action="Index">Back to description</a>
|
||||
<h1>FoxTube privacy policy</h1>
|
||||
<p>Last update: @Model?.Resume.LastUpdate</p>
|
||||
Last update: @Model?.Resume.LastUpdate
|
||||
</header>
|
||||
|
||||
<article>
|
||||
@@ -16,15 +16,34 @@
|
||||
|
||||
@section Imports {
|
||||
<style type="text/css">
|
||||
header, article {
|
||||
article
|
||||
{
|
||||
margin: 0px 50px;
|
||||
}
|
||||
header a {
|
||||
|
||||
header
|
||||
{
|
||||
margin: 16px 50px;
|
||||
}
|
||||
|
||||
header a
|
||||
{
|
||||
color: black;
|
||||
text-decoration: none;
|
||||
}
|
||||
header a:hover {
|
||||
|
||||
header a:hover
|
||||
{
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
@@media only screen and (max-width: 500px)
|
||||
{
|
||||
header, article
|
||||
{
|
||||
margin-right: 20px;
|
||||
margin-left: 20px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
}
|
||||
@@ -1,12 +1,10 @@
|
||||
@using System.IO
|
||||
@using System.Globalization
|
||||
@model ScreenshotViewModel
|
||||
@model ScreenshotViewModel
|
||||
@{
|
||||
ViewData["Title"] = "Screenshot";
|
||||
Layout = "_Layout.cshtml";
|
||||
}
|
||||
|
||||
<article class="image-overview-block">
|
||||
<header>
|
||||
<p class="controls">
|
||||
 <a asp-action="Index" class="back">Back to description</a>
|
||||
@if (Model.Previous != null)
|
||||
@@ -20,25 +18,28 @@
|
||||
<a asp-action="Screenshot" asp-route-id="@Model.Next" class="back">Next</a>
|
||||
}
|
||||
</p>
|
||||
|
||||
<p class="title">
|
||||
<p>
|
||||
<b>@Model.Current</b>
|
||||
</p>
|
||||
</header>
|
||||
|
||||
<img src="@Model.Paths[Model.Position]" id="image" onclick="ToggleImageSize();"/>
|
||||
<article class="image-overview-block">
|
||||
<img src="@Model.Paths[Model.Position]" id="image" onclick="ToggleImageSize();" />
|
||||
</article>
|
||||
|
||||
@section Imports {
|
||||
<link rel="stylesheet" type="text/css" href="~/css/Gallery.css" />
|
||||
<style type="text/css">
|
||||
#image {
|
||||
max-height: initial;
|
||||
#image
|
||||
{
|
||||
max-height: 75vh;
|
||||
}
|
||||
.controls {
|
||||
display: inline-block;
|
||||
}
|
||||
.title {
|
||||
float: right;
|
||||
|
||||
header
|
||||
{
|
||||
display: grid;
|
||||
grid-template-columns: 1fr auto;
|
||||
margin: 0px 20px;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -51,8 +52,8 @@
|
||||
image.style = "";
|
||||
else
|
||||
{
|
||||
image.style.maxHeight = "none";
|
||||
image.style.maxWidth = "none";
|
||||
image.style.maxHeight = "initial";
|
||||
image.style.maxWidth = "initial";
|
||||
image.style.cursor = "zoom-out";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,13 +6,14 @@
|
||||
<base href="~/assets/FoxTube/" />
|
||||
<link rel="shortcut icon" href="favicon.ico" type="image/x-icon" />
|
||||
|
||||
<link rel="stylesheet" type="text/css" href="~/css/Socicon.css" />
|
||||
<link rel="stylesheet" href="https://s3.amazonaws.com/icomoon.io/114779/Socicon/style.css?u8vidh" />
|
||||
<link rel="stylesheet" type="text/css" href="~/css/Fonts.css" />
|
||||
<link rel="stylesheet" type="text/css" href="FoxTube.css" />
|
||||
|
||||
<script type="text/javascript">
|
||||
function ToggleMenu()
|
||||
{
|
||||
var menu = document.getElementById("main-menu");
|
||||
var menu = document.querySelector("menu");
|
||||
|
||||
if (menu.style.display == "none")
|
||||
menu.style.display = "initial";
|
||||
@@ -30,7 +31,8 @@
|
||||
<meta name="author" content="Michael 'XFox' Gordeev">
|
||||
<meta name="description" content="YouTube client for Windows 10 family devices. It's fast and convenient. It also supports live streams and 8K videos!">
|
||||
|
||||
<meta property="og:image" content="FoxTubeLogo.png">
|
||||
<meta property="og:image" content="/assets/FoxTube/Logo.svg">
|
||||
<meta property="og:site_name" content="FoxTube - New YouTube client for Windows 10" />
|
||||
<meta property="og:video" content="//www.youtube.com/embed/Mio9FbxmbhM">
|
||||
<meta property="og:video" content="https://www.youtube.com/embed/Mio9FbxmbhM">
|
||||
<meta property="og:video" content="https://www.youtube.com/v/Mio9FbxmbhM">
|
||||
@@ -49,15 +51,11 @@
|
||||
<img class="logo" src="Logo.svg" />
|
||||
<a asp-action="Index">
|
||||
<b>FoxTube</b><br />
|
||||
YouTube client for Windows 10
|
||||
<span>YouTube client for Windows 10</span>
|
||||
</a>
|
||||
|
||||
<menu type="toolbar" id="main-menu" style="display:none">
|
||||
<li><a asp-area="" asp-controller="Home" asp-action="Index">Home();</a></li>
|
||||
<li><a asp-area="" asp-controller="Resume" asp-action="Index">MyResume();</a></li>
|
||||
<li><a asp-area="" asp-controller="Projects" asp-action="Index">Projects();</a></li>
|
||||
<li><a asp-area="" asp-controller="Gallery" asp-action="Index">Arts();</a></li>
|
||||
<li><a asp-area="" asp-controller="Contacts" asp-action="Index">Contacts();</a></li>
|
||||
<menu type="toolbar" style="display:none">
|
||||
<partial name="~/Views/Shared/TopBarMenu.cshtml" />
|
||||
</menu>
|
||||
|
||||
<p>
|
||||
@@ -67,7 +65,7 @@
|
||||
</p>
|
||||
</nav>
|
||||
|
||||
<main>
|
||||
<main onclick="document.querySelector('menu').style.display = 'none'">
|
||||
@RenderBody()
|
||||
</main>
|
||||
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
@model ResumeViewModel
|
||||
@{
|
||||
Layout = "/Views/Shared/_Layout.cshtml";
|
||||
ViewData["Title"] = "GUT.Schedule privacy policy";
|
||||
}
|
||||
|
||||
<header>
|
||||
<h1>GUT.Schedule privacy policy</h1>
|
||||
<p>Last update: @Model?.Resume?.LastUpdate</p>
|
||||
</header>
|
||||
|
||||
<article>
|
||||
@Html.Raw(Model?.Resume?.Content)
|
||||
</article>
|
||||
@@ -39,11 +39,15 @@ namespace MyWebsite.Controllers
|
||||
CredentialModel user = Database.Users.FirstOrDefault(i => i.Email == model.Credential.Email);
|
||||
if (user == null || !Encryptor.VerifyHash(model?.Credential.Password, user.Password))
|
||||
{
|
||||
if (!Database.Users.Any())
|
||||
goto Authorize;
|
||||
|
||||
ModelState.AddModelError("Authorization error", "Invaild e-mail or password");
|
||||
return View(new CredentialViewModel(Database, model));
|
||||
}
|
||||
|
||||
Claim claim = new Claim(ClaimsIdentity.DefaultNameClaimType, user.Email);
|
||||
Authorize:
|
||||
Claim claim = new Claim(ClaimsIdentity.DefaultNameClaimType, user?.Email ?? "root");
|
||||
|
||||
ClaimsIdentity id = new ClaimsIdentity(new Claim[] { claim }, "ApplicationCookie", ClaimsIdentity.DefaultNameClaimType, ClaimsIdentity.DefaultRoleClaimType);
|
||||
await HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, new ClaimsPrincipal(id)).ConfigureAwait(false);
|
||||
@@ -56,16 +60,5 @@ namespace MyWebsite.Controllers
|
||||
await HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme).ConfigureAwait(false);
|
||||
return RedirectToAction("Login", "Admin");
|
||||
}
|
||||
|
||||
[AllowAnonymous]
|
||||
public bool ResetPassword(string id)
|
||||
{
|
||||
CredentialModel user = Database.Users.Find("michael.xfox@outlook.com");
|
||||
user.Password = Encryptor.ComputeHash(id);
|
||||
Database.Users.Update(user);
|
||||
Database.SaveChanges();
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -9,6 +9,8 @@ namespace MyWebsite.Models.Databases
|
||||
public DbSet<Message> Messages { get; set; }
|
||||
public DbSet<Changelog> Changelogs { get; set; }
|
||||
|
||||
public DbSet<ResumeModel> PrivacyPolicies { get; set; }
|
||||
|
||||
public FoxTubeDatabaseContext(DbContextOptions<FoxTubeDatabaseContext> options) : base(options) =>
|
||||
Database.EnsureCreated();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace MyWebsite.Models.Databases
|
||||
{
|
||||
public class GUTScheduleDatabaseContext : DbContext
|
||||
{
|
||||
public DbSet<ResumeModel> PrivacyPolicies { get; set; }
|
||||
public DbSet<CustomData> OffsetDates { get; set; }
|
||||
|
||||
public GUTScheduleDatabaseContext(DbContextOptions<GUTScheduleDatabaseContext> options) : base(options) =>
|
||||
Database.EnsureCreated();
|
||||
}
|
||||
}
|
||||
@@ -9,7 +9,7 @@ namespace MyWebsite.Models
|
||||
public class ImageModel
|
||||
{
|
||||
[Key]
|
||||
[Column(TypeName = "varchar(20)")]
|
||||
[Column(TypeName = "varchar(255)")]
|
||||
[DisplayName("File name")]
|
||||
public string FileName { get; set; }
|
||||
|
||||
@@ -27,7 +27,6 @@ namespace MyWebsite.Models
|
||||
[DisplayName("Description")]
|
||||
public string Description => CultureInfo.CurrentUICulture.TwoLetterISOLanguageName == "ru" && !string.IsNullOrWhiteSpace(RussianDescription) ? RussianDescription : EnglishDescription;
|
||||
|
||||
[Required]
|
||||
[Column(TypeName = "text")]
|
||||
[DisplayName("Description (en)")]
|
||||
public string EnglishDescription { get; set; }
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System.ComponentModel;
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
using System.Globalization;
|
||||
@@ -10,8 +11,14 @@ namespace MyWebsite.Models
|
||||
{
|
||||
[Key]
|
||||
[Required]
|
||||
[DisplayName("ID (Order)")]
|
||||
public decimal Id { get; set; }
|
||||
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
|
||||
[DisplayName("ID")]
|
||||
public Guid Id { get; set; }
|
||||
|
||||
[Required]
|
||||
[Column(TypeName = "int")]
|
||||
[DisplayName("Order")]
|
||||
public int Order { get; set; }
|
||||
|
||||
[DisplayName("Title")]
|
||||
public string Title => CultureInfo.CurrentUICulture.TwoLetterISOLanguageName == "ru" && !string.IsNullOrWhiteSpace(RussianTitle) ? RussianTitle : EnglishTitle;
|
||||
@@ -42,7 +49,6 @@ namespace MyWebsite.Models
|
||||
[DisplayName("Link text caption")]
|
||||
public string LinkCaption => CultureInfo.CurrentUICulture.TwoLetterISOLanguageName == "ru" && !string.IsNullOrWhiteSpace(RussianTitle) ? RussianLinkCaption : EnglishLinkCaption;
|
||||
|
||||
[Required]
|
||||
[Column(TypeName = "varchar(50)")]
|
||||
[DisplayName("Link text caption (en)")]
|
||||
public string EnglishLinkCaption { get; set; }
|
||||
|
||||
@@ -1,36 +1,26 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||
<AspNetCoreHostingModel>InProcess</AspNetCoreHostingModel>
|
||||
<AssemblyName>XFox111dotNET</AssemblyName>
|
||||
<Authors>Michael "XFox" Gordeev</Authors>
|
||||
<Company>FoxDev Studio</Company>
|
||||
<Product>XFox111.NET</Product>
|
||||
<Description>This is my personal website written in ASP.NET MVC</Description>
|
||||
<Copyright>©2020 Michael "XFox" Gordeev</Copyright>
|
||||
<PackageProjectUrl>https://xfox111.net/</PackageProjectUrl>
|
||||
<RepositoryUrl>https://github.com/xfox111/cvwebsite</RepositoryUrl>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Remove="wwwroot\projects-assets\**" />
|
||||
<Content Remove="wwwroot\projects-assets\**" />
|
||||
<EmbeddedResource Remove="wwwroot\projects-assets\**" />
|
||||
<None Remove="wwwroot\projects-assets\**" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Remove="Areas\Admin\NewFile.txt" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.CodeAnalysis.FxCopAnalyzers" Version="2.9.8">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="3.1.0" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="3.1.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="3.1.0" />
|
||||
<PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="3.1.0" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="3.1.2" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="3.1.2" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="3.1.2" />
|
||||
<PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="3.1.1" />
|
||||
<PackageReference Include="Select.HtmlToPdf.NetCore" Version="19.2.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Folder Include="wwwroot\assets\FoxTube\Screenshots\" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
|
||||
</Project>
|
||||
@@ -1,13 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<Controller_SelectedScaffolderID>MvcControllerEmptyScaffolder</Controller_SelectedScaffolderID>
|
||||
<Controller_SelectedScaffolderCategoryPath>root/Controller</Controller_SelectedScaffolderCategoryPath>
|
||||
<WebStackScaffolding_ControllerDialogWidth>600</WebStackScaffolding_ControllerDialogWidth>
|
||||
<WebStackScaffolding_IsLayoutPageSelected>False</WebStackScaffolding_IsLayoutPageSelected>
|
||||
<WebStackScaffolding_IsPartialViewSelected>False</WebStackScaffolding_IsPartialViewSelected>
|
||||
<WebStackScaffolding_IsReferencingScriptLibrariesSelected>False</WebStackScaffolding_IsReferencingScriptLibrariesSelected>
|
||||
<WebStackScaffolding_IsAsyncSelected>False</WebStackScaffolding_IsAsyncSelected>
|
||||
<WebStackScaffolding_ViewDialogWidth>600</WebStackScaffolding_ViewDialogWidth>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
@@ -10,13 +10,10 @@ using MyWebsite.Models.Databases;
|
||||
|
||||
namespace MyWebsite
|
||||
{
|
||||
// TODO: Add reordering for contact links
|
||||
// TODO: Complete project admin page
|
||||
// TODO: Complete artworks admin page
|
||||
// TODO: FoxTube API admin page
|
||||
// TODO: Complete homepage
|
||||
// TODO: Complete FoxTube page
|
||||
// TODO: Add localization system
|
||||
// TODO: Add blog
|
||||
// TODO: Rid of JavaScript (use Blazor)
|
||||
public class Startup
|
||||
{
|
||||
@@ -36,6 +33,9 @@ namespace MyWebsite
|
||||
services.AddDbContext<FoxTubeDatabaseContext>(options =>
|
||||
options.UseSqlServer(Configuration.GetConnectionString("FoxTubeDB")));
|
||||
|
||||
services.AddDbContext<GUTScheduleDatabaseContext>(options =>
|
||||
options.UseSqlServer(Configuration.GetConnectionString("GUTScheduleDB")));
|
||||
|
||||
services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme).AddCookie(options =>
|
||||
options.LoginPath = new PathString("/Admin/Login"));
|
||||
|
||||
|
||||
@@ -8,6 +8,9 @@ namespace MyWebsite.ViewModels
|
||||
{
|
||||
public ResumeModel Resume { get; }
|
||||
public ResumeViewModel(DatabaseContext context, CultureInfo language) : base(context) =>
|
||||
Resume = context.Resume.Find(language?.Name) ?? context.Resume.Find("en-US");
|
||||
Resume = context.Resume.Find(language?.TwoLetterISOLanguageName) ?? context.Resume.Find("en");
|
||||
|
||||
public ResumeViewModel(ResumeModel model, DatabaseContext context) : base(context) =>
|
||||
Resume = model;
|
||||
}
|
||||
}
|
||||
@@ -10,6 +10,6 @@ namespace MyWebsite.ViewModels
|
||||
public IEnumerable<LinkModel> Links { get; }
|
||||
|
||||
public ViewModelBase(DatabaseContext context) =>
|
||||
Links = context?.Links.ToList();
|
||||
Links = context?.Links.OrderBy(i => i.Order);
|
||||
}
|
||||
}
|
||||
@@ -6,23 +6,23 @@
|
||||
<h1>Administration</h1>
|
||||
</header>
|
||||
|
||||
<article>
|
||||
<p class="admin-menu">
|
||||
<article class="admin-menu">
|
||||
<p>
|
||||
<a asp-action="Gallery" class="comment">// Artworks</a><br />
|
||||
<a asp-action="Projects" class="comment">// Projects</a><br />
|
||||
<a asp-action="Badges" class="comment">// Badges</a><br />
|
||||
<a asp-action="Resume" class="comment">// Resume</a><br />
|
||||
<a asp-action="Contacts" class="comment">// Contact links</a>
|
||||
</p>
|
||||
<p class="admin-menu">
|
||||
<p>
|
||||
<a asp-action="FoxTube" class="comment">// FoxTube API</a><br />
|
||||
<a asp-action="GUTSchedule" class="comment">// GUT.Schedule API</a>
|
||||
</p>
|
||||
<p>
|
||||
<a asp-action="Credential" class="logout">// Change credential information</a>
|
||||
<a asp-action="Credential" class="comment logout">// Change credential information</a>
|
||||
</p>
|
||||
<p>
|
||||
<a asp-action="Logout" class="logout"> Logout</a>
|
||||
<a asp-action="Logout" class="comment logout"> Logout</a>
|
||||
</p>
|
||||
</article>
|
||||
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
}
|
||||
|
||||
<header>
|
||||
<p>
|
||||
@if (Model.Previous != null)
|
||||
{
|
||||
@:
|
||||
@@ -17,11 +16,10 @@
|
||||
@:| 
|
||||
<a asp-action="Details" asp-route-id="@Model.Next">Next</a>
|
||||
}
|
||||
</p>
|
||||
</header>
|
||||
|
||||
<article class="image-overview-block">
|
||||
<img src="~/images/Gallery/@Model.Current?.FileName" onclick="ToggleImageSize();" id="image" />
|
||||
<img src="~/images/Gallery/@Model.Current?.FileName" onclick="ToggleImageSize();" />
|
||||
|
||||
<div>
|
||||
<h1>@Model.Current?.Title</h1>
|
||||
@@ -32,13 +30,14 @@
|
||||
</div>
|
||||
</article>
|
||||
|
||||
@section Imports {
|
||||
@section Imports
|
||||
{
|
||||
<link rel="stylesheet" type="text/css" href="~/css/Gallery.css" />
|
||||
|
||||
<script type="text/javascript">
|
||||
function ToggleImageSize()
|
||||
{
|
||||
var image = document.getElementById("image");
|
||||
var image = document.querySelector("img");
|
||||
|
||||
if (image.style.cursor == "zoom-out")
|
||||
image.style = "";
|
||||
|
||||
@@ -5,14 +5,14 @@
|
||||
|
||||
<header>
|
||||
<h1>My resume</h1>
|
||||
<p>Last update: @Model?.Resume.LastUpdate</p>
|
||||
<p>Last update: @Model?.Resume?.LastUpdate</p>
|
||||
|
||||
<a class="comment" asp-action="Download">// Download CV (.pdf) </a><br />
|
||||
<a class="comment" asp-action="Print">// Print CV </a>
|
||||
</header>
|
||||
|
||||
<article>
|
||||
@Html.Raw(Model?.Resume.Content)
|
||||
@Html.Raw(Model?.Resume?.Content)
|
||||
</article>
|
||||
|
||||
@section Footer
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
<base href="~/assets/Construction/" />
|
||||
|
||||
<link rel="stylesheet" type="text/css" href="Construction.css">
|
||||
<link rel="stylesheet" type="text/css" href="~/css/Fonts.css">
|
||||
<script type="text/javascript" src="Construction.js"></script>
|
||||
|
||||
<meta name="author" content="Michael 'XFox' Gordeev">
|
||||
@@ -89,7 +90,7 @@
|
||||
|
||||
@foreach (LinkModel item in Model.Links.Where(i => i.Name.Belongs("outlook", "linkedin", "vkontakte", "twitter", "github")))
|
||||
{
|
||||
<p>@item.Title: <a href="@item.Url">@((item.Url.ToString().StartsWith("mailto:") ? "" : "https:") + item.Url)</a></p>
|
||||
<p>@item.Title: <a href="@item.Url" target="_blank">@((item.Url.ToString().StartsWith("mailto:") ? "" : "https:") + item.Url)</a></p>
|
||||
}
|
||||
<br />
|
||||
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
|
||||
<!-- TODO: Make Error page-->
|
||||
<header>
|
||||
<h1 class="text-danger">Error.</h1>
|
||||
<h2 class="text-danger">An error occurred while processing your request.</h2>
|
||||
<h1>Error</h1>
|
||||
<h2>An error occurred while processing your request.</h2>
|
||||
</header>
|
||||
|
||||
<article>
|
||||
|
||||
@@ -8,6 +8,23 @@
|
||||
|
||||
<article>
|
||||
<p>
|
||||
Homepage
|
||||
Hi guys! This is my website. And this is its home page. Usually, homepages should look as much glorious and cool as they can. But for some inspirational reasons I've done everything except homepage.
|
||||
</p>
|
||||
<p>
|
||||
Well, maybe not everything... But the most of it. If I could I would leave it offline for a few more <s>years</s> <s>month</s> time. But I need it online now, so here we go. <br />
|
||||
Lets consider it as 0.1.2020.03.08.666 prerelease beta technical preview demo pre-RTM version.
|
||||
</p>
|
||||
<p>
|
||||
So you can lurk around and check other pages. I'm pretty sure they should be fine.
|
||||
</p>
|
||||
<dl>
|
||||
<dt>Cheers,</dt>
|
||||
<dd>Michael "XFox" Gordeev</dd>
|
||||
</dl>
|
||||
<p hidden>
|
||||
But anyway I should tell some more about it, shouldn't I?
|
||||
</p>
|
||||
<p hidden>
|
||||
My name is Michael, I'm C# Developer and CS student in Saint Petersburg (the russian one:)
|
||||
</p>
|
||||
</article>
|
||||
@@ -14,7 +14,7 @@
|
||||
<article>
|
||||
@if (Model.Projects.Count() > 0)
|
||||
{
|
||||
@foreach (ProjectModel project in Model.Projects)
|
||||
@foreach (ProjectModel project in Model.Projects.OrderBy(i => i.Order))
|
||||
{
|
||||
<div class="project-item">
|
||||
<div>
|
||||
@@ -40,6 +40,7 @@
|
||||
}
|
||||
</article>
|
||||
|
||||
@section Imports {
|
||||
@section Imports
|
||||
{
|
||||
<link rel="stylesheet" type="text/css" href="~/css/Projects.css" />
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
<li><a asp-area="" asp-controller="Home" asp-action="Index">AboutMe();</a></li>
|
||||
<li hidden><a href="//xfox111.blogspot.com/" target="_blank">MyBlog();</a></li>
|
||||
<li><a asp-area="" asp-controller="Resume" asp-action="Index">MyResume();</a></li>
|
||||
<li><a asp-area="" asp-controller="Projects" asp-action="Index">Projects();</a></li>
|
||||
<li><a asp-area="" asp-controller="Gallery" asp-action="Index">Arts();</a></li>
|
||||
<li><a asp-area="" asp-controller="Contacts" asp-action="Index">Contacts();</a></li>
|
||||
@@ -6,12 +6,13 @@
|
||||
<link rel="shortcut icon" href="~/favicon.ico" type="image/x-icon" />
|
||||
|
||||
<link rel="stylesheet" type="text/css" href="~/css/Style.css" />
|
||||
<link rel="stylesheet" type="text/css" href="~/css/Socicon.css" />
|
||||
<link rel="stylesheet" type="text/css" href="~/css/Fonts.css" />
|
||||
<link rel="stylesheet" href="https://s3.amazonaws.com/icomoon.io/114779/Socicon/style.css?u8vidh" />
|
||||
|
||||
<script type="text/javascript">
|
||||
function ToggleMenu()
|
||||
{
|
||||
var menu = document.getElementById("main-menu");
|
||||
var menu = document.querySelector("nav menu");
|
||||
|
||||
if (menu.style.display == "none")
|
||||
menu.style.display = "initial";
|
||||
@@ -47,12 +48,8 @@
|
||||
<nav>
|
||||
<a asp-controller="Home" asp-action="Index" asp-area="">XFox111.NET</a>
|
||||
|
||||
<menu type="toolbar" id="main-menu" style="display:none">
|
||||
<li><a asp-area="" asp-controller="Home" asp-action="Index">AboutMe();</a></li>
|
||||
<li><a asp-area="" asp-controller="Resume" asp-action="Index">Resume();</a></li>
|
||||
<li><a asp-area="" asp-controller="Projects" asp-action="Index">Projects();</a></li>
|
||||
<li><a asp-area="" asp-controller="Gallery" asp-action="Index">Arts();</a></li>
|
||||
<li><a asp-area="" asp-controller="Contacts" asp-action="Index">Contacts();</a></li>
|
||||
<menu type="toolbar" style="display:none">
|
||||
<partial name="~/Views/Shared/TopBarMenu.cshtml" />
|
||||
</menu>
|
||||
|
||||
<div>
|
||||
@@ -61,7 +58,7 @@
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<main>
|
||||
<main onclick="document.querySelector('nav menu').style.display = 'none'">
|
||||
@RenderBody()
|
||||
</main>
|
||||
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
{
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Information",
|
||||
"Microsoft": "Warning",
|
||||
"Microsoft.Hosting.Lifetime": "Information"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -9,6 +9,7 @@
|
||||
"AllowedHosts": "*",
|
||||
"ConnectionStrings": {
|
||||
"MainDB": "Server=(localdb)\\mssqllocaldb;Database=xfox111;Trusted_Connection=True;",
|
||||
"FoxTubeDB": "Server=(localdb)\\mssqllocaldb;Database=foxtube;Trusted_Connection=True;"
|
||||
"FoxTubeDB": "Server=(localdb)\\mssqllocaldb;Database=foxtube;Trusted_Connection=True;",
|
||||
"GUTScheduleDB": "Server=(localdb)\\mssqllocaldb;Database=gutSchedule;Trusted_Connection=True;"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration>
|
||||
<!--Redirects-->
|
||||
<system.webServer>
|
||||
<rewrite>
|
||||
<rules>
|
||||
<!--Legacy redirects-->
|
||||
<rule name="GutSchedule API redirect" stopProcessing="true">
|
||||
<match url="schedule_offset.txt" />
|
||||
<action type="Redirect" url="https://xfox111.net/API/GUTSchedule/SemesterOffsetDay" redirectType="Permanent" appendQueryString="false" />
|
||||
</rule>
|
||||
<rule name="GUT.Schedule Privacy policy" stopProcessing="true">
|
||||
<match url="Projects/GUTSchedule/PrivacyPolicy.txt" />
|
||||
<action type="Redirect" url="https://xfox111.net/Projects/GUTSchedule/PrivacyPolicy" redirectType="Permanent" appendQueryString="false" />
|
||||
</rule>
|
||||
<rule name="FoxTubr Privacy policy" stopProcessing="true">
|
||||
<match url="Projects/FoxTube/PrivacyPolicy.txt" />
|
||||
<action type="Redirect" url="https://xfox111.net/Projects/FoxTube/PrivacyPolicy" redirectType="Permanent" appendQueryString="false" />
|
||||
</rule>
|
||||
<!--/Legacy redirects-->
|
||||
<!--Website maintainence redirect-->
|
||||
<rule name="Construction redirect" stopProcessing="true" enabled="false">
|
||||
<match url="^(?!Admin|API|Construction|css|assets|fonts|images)" />
|
||||
<action type="Redirect" url="https://xfox111.net/Construction" redirectType="Temporary" appendQueryString="false" />
|
||||
</rule>
|
||||
<!--\Website maintainence redirect-->
|
||||
</rules>
|
||||
</rewrite>
|
||||
</system.webServer>
|
||||
<!--/Redirects-->
|
||||
<location path="." inheritInChildApplications="false" allowOverride="false">
|
||||
<system.webServer>
|
||||
<handlers>
|
||||
<add name="aspNetCore" path="*" verb="*" modules="AspNetCoreModule" resourceType="Unspecified" />
|
||||
</handlers>
|
||||
<aspNetCore processPath=".\XFox111dotNET.exe" stdoutLogEnabled="true" stdoutLogFile=".\logs\stdout" hostingModel="inprocess" />
|
||||
</system.webServer>
|
||||
<system.web>
|
||||
<trust level="Full" />
|
||||
</system.web>
|
||||
</location>
|
||||
<system.web>
|
||||
<compilation defaultLanguage="c#" />
|
||||
<globalization fileEncoding="utf-8" />
|
||||
</system.web>
|
||||
</configuration>
|
||||
<!--ProjectGuid: 9fb2b925-dc18-4081-ac91-96f2c49415f9-->
|
||||
@@ -1,19 +1,4 @@
|
||||
/* Declaring fonts */
|
||||
@font-face
|
||||
{
|
||||
font-family: 'Consolas';
|
||||
src: url("/fonts/Consolas/consolas.eot");
|
||||
src: url("/fonts/Consolas/consolas.eot?#iefix") format("embedded-opentype"), url("/fonts/Consolas/consolas.otf") format("opentype"), url("/fonts/Consolas/consolas.svg") format("svg"), url("/fonts/Consolas/consolas.ttf") format("truetype"), url("/fonts/Consolas/consolas.woff") format("woff"), url("/fonts/Consolas/consolas.woff2") format("woff2");
|
||||
}
|
||||
|
||||
@font-face
|
||||
{
|
||||
font-family: 'Segoe MDL2 Assets';
|
||||
src: url("/fonts/Segoe MDL2 Assets/segoeMLD2assets.eot");
|
||||
src: url("/fonts/Segoe MDL2 Assets/segoeMLD2assets.eot?#iefix") format("embedded-opentype"), url("/fonts/Segoe MDL2 Assets/segoeMLD2assets.otf") format("opentype"), url("/fonts/Segoe MDL2 Assets/segoeMLD2assets.svg") format("svg"), url("/fonts/Segoe MDL2 Assets/segoeMLD2assets.ttf") format("truetype"), url("/fonts/Segoe MDL2 Assets/segoeMLD2assets.woff") format("woff"), url("/fonts/Segoe MDL2 Assets/segoeMLD2assets.woff2") format("woff2");
|
||||
}
|
||||
|
||||
/* Header */
|
||||
/* Header */
|
||||
nav
|
||||
{
|
||||
user-select: none;
|
||||
@@ -68,6 +53,7 @@ nav
|
||||
line-height: 26px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
nav > div:last-child select
|
||||
{
|
||||
background-color: #333337;
|
||||
@@ -78,9 +64,10 @@ nav
|
||||
height: 21px;
|
||||
margin: 2px 0px;
|
||||
}
|
||||
|
||||
nav > div:last-child img
|
||||
{
|
||||
height: 100%;
|
||||
height: 26px;
|
||||
}
|
||||
|
||||
/* Body */
|
||||
@@ -95,7 +82,7 @@ body
|
||||
color: white;
|
||||
font-size: 9pt;
|
||||
margin: 0px;
|
||||
font-family: 'Segoe UI Symbol';
|
||||
font-family: 'SegoeUISymbol';
|
||||
overflow: auto;
|
||||
display: grid;
|
||||
height: 100vh;
|
||||
@@ -103,7 +90,7 @@ body
|
||||
|
||||
main
|
||||
{
|
||||
font-family: Consolas;
|
||||
font-family: 'Consolas';
|
||||
margin: 50px 0px 50px 12px;
|
||||
}
|
||||
|
||||
@@ -111,6 +98,7 @@ main
|
||||
{
|
||||
margin: 0px;
|
||||
display: none;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
a
|
||||
@@ -223,3 +211,38 @@ footer
|
||||
{
|
||||
content: '\1F7A8';
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 560px)
|
||||
{
|
||||
nav > div:last-child
|
||||
{
|
||||
height: initial;
|
||||
grid-template-columns: initial;
|
||||
}
|
||||
|
||||
nav > div:last-child select
|
||||
{
|
||||
width: initial;
|
||||
margin: 0px 5px;
|
||||
}
|
||||
|
||||
nav > div > span
|
||||
{
|
||||
text-align: start !important;
|
||||
}
|
||||
|
||||
main
|
||||
{
|
||||
margin-top: 110px;
|
||||
}
|
||||
|
||||
.git-btn
|
||||
{
|
||||
min-width: 17px;
|
||||
}
|
||||
|
||||
.git-btn > span
|
||||
{
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,19 +1,4 @@
|
||||
/* Declaring fonts */
|
||||
@font-face
|
||||
{
|
||||
font-family: 'Consolas';
|
||||
src: url("/fonts/Consolas/consolas.eot");
|
||||
src: url("/fonts/Consolas/consolas.eot?#iefix") format("embedded-opentype"), url("/fonts/Consolas/consolas.otf") format("opentype"), url("/fonts/Consolas/consolas.svg") format("svg"), url("/fonts/Consolas/consolas.ttf") format("truetype"), url("/fonts/Consolas/consolas.woff") format("woff"), url("/fonts/Consolas/consolas.woff2") format("woff2");
|
||||
}
|
||||
|
||||
@font-face
|
||||
{
|
||||
font-family: 'Segoe MDL2 Assets';
|
||||
src: url("/fonts/Segoe MDL2 Assets/segoeMLD2assets.eot");
|
||||
src: url("/fonts/Segoe MDL2 Assets/segoeMLD2assets.eot?#iefix") format("embedded-opentype"), url("/fonts/Segoe MDL2 Assets/segoeMLD2assets.otf") format("opentype"), url("/fonts/Segoe MDL2 Assets/segoeMLD2assets.svg") format("svg"), url("/fonts/Segoe MDL2 Assets/segoeMLD2assets.ttf") format("truetype"), url("/fonts/Segoe MDL2 Assets/segoeMLD2assets.woff") format("woff"), url("/fonts/Segoe MDL2 Assets/segoeMLD2assets.woff2") format("woff2");
|
||||
}
|
||||
|
||||
/* Header styles */
|
||||
/* Header styles */
|
||||
nav
|
||||
{
|
||||
display: grid;
|
||||
@@ -70,40 +55,6 @@ menu
|
||||
display: block;
|
||||
}
|
||||
|
||||
/* Adaptive code */
|
||||
@media only screen and (min-width: 1150px)
|
||||
{
|
||||
menu
|
||||
{
|
||||
display: initial !important;
|
||||
grid-row: 1;
|
||||
grid-column: 3;
|
||||
margin: 0px;
|
||||
align-self: end;
|
||||
margin-bottom: 3px;
|
||||
}
|
||||
|
||||
menu li
|
||||
{
|
||||
display: inline-block;
|
||||
margin-right: 10px;
|
||||
margin-top: 0px;
|
||||
}
|
||||
|
||||
#menu-toggle
|
||||
{
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 700px) {
|
||||
body
|
||||
{
|
||||
margin-top: 112px !important;
|
||||
height: calc(100vh - 112px) !important;
|
||||
}
|
||||
}
|
||||
|
||||
/* Body styles */
|
||||
html
|
||||
{
|
||||
@@ -112,7 +63,7 @@ html
|
||||
|
||||
body
|
||||
{
|
||||
font-family: 'Consolas', 'Segoe MDL2 Assets';
|
||||
font-family: 'Consolas', 'SegoeMDL2Assets';
|
||||
overflow: auto;
|
||||
margin: 0px;
|
||||
margin-top: 84px;
|
||||
@@ -123,7 +74,7 @@ body
|
||||
|
||||
main
|
||||
{
|
||||
font-family: 'Calibri', 'Segoe MDL2 Assets';
|
||||
font-family: 'Calibri', 'SegoeMDL2Assets';
|
||||
}
|
||||
|
||||
.back
|
||||
@@ -152,6 +103,18 @@ article
|
||||
color: #57a64a !important;
|
||||
}
|
||||
|
||||
.video
|
||||
{
|
||||
max-width: 560px;
|
||||
height: 315px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
*[hidden]
|
||||
{
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* Footer styles */
|
||||
footer
|
||||
{
|
||||
@@ -172,3 +135,56 @@ footer
|
||||
{
|
||||
color: orangered;
|
||||
}
|
||||
|
||||
/* Adaptive code */
|
||||
@media only screen and (min-width: 1150px)
|
||||
{
|
||||
menu
|
||||
{
|
||||
display: initial !important;
|
||||
grid-row: 1;
|
||||
grid-column: 3;
|
||||
margin: 0px;
|
||||
align-self: end;
|
||||
margin-bottom: 3px;
|
||||
}
|
||||
|
||||
menu li
|
||||
{
|
||||
display: inline-block;
|
||||
margin-right: 10px;
|
||||
margin-top: 0px;
|
||||
}
|
||||
|
||||
#menu-toggle
|
||||
{
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 700px) and (min-width: 480px)
|
||||
{
|
||||
body
|
||||
{
|
||||
margin-top: 112px !important;
|
||||
height: calc(100vh - 112px) !important;
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 480px)
|
||||
{
|
||||
nav > a > span
|
||||
{
|
||||
display: none;
|
||||
}
|
||||
|
||||
.video
|
||||
{
|
||||
height: 240px !important;
|
||||
}
|
||||
}
|
||||
|
||||
nav > p > a:nth-last-child(2)
|
||||
{
|
||||
visibility: hidden;
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
input
|
||||
input:not([type="checkbox"])
|
||||
{
|
||||
padding: 10px;
|
||||
border-radius: 10px;
|
||||
border-radius: 5px;
|
||||
border: 1px solid black;
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
@@ -12,32 +12,84 @@ select
|
||||
{
|
||||
padding: 10px;
|
||||
border: 1px solid black;
|
||||
border-radius: 10px;
|
||||
border-radius: 5px;
|
||||
width: 100%;
|
||||
-moz-appearance: none; /* Firefox */
|
||||
-webkit-appearance: none; /* Safari and Chrome */
|
||||
}
|
||||
|
||||
input:invalid
|
||||
{
|
||||
border: 3px solid red;
|
||||
}
|
||||
|
||||
input[type="submit"],
|
||||
input[type="button"],
|
||||
button
|
||||
{
|
||||
margin: 10px;
|
||||
border-radius: 10px;
|
||||
border-radius: 5px;
|
||||
border: 0px;
|
||||
padding: 10px 20px;
|
||||
background-color: #343434;
|
||||
color: white;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
input[type="submit"]:disabled,
|
||||
input[type="button"]:disabled,
|
||||
button:disabled
|
||||
{
|
||||
background-color: gray;
|
||||
cursor: initial;
|
||||
}
|
||||
|
||||
input[type="submit"]:hover:not(:disabled),
|
||||
input[type="button"]:hover:not(:disabled),
|
||||
button:hover:not(:disabled)
|
||||
{
|
||||
background-color: #505050;
|
||||
}
|
||||
|
||||
input[type="submit"]:active,
|
||||
input[type="button"]:active,
|
||||
button:active
|
||||
{
|
||||
background-color: black;
|
||||
}
|
||||
|
||||
input[type="submit"][required],
|
||||
input[type="button"][required]
|
||||
{
|
||||
background-color: red;
|
||||
}
|
||||
|
||||
input[type="submit"][required]:hover,
|
||||
input[type="button"][required]:hover
|
||||
{
|
||||
background-color: rgb(200, 0, 0);
|
||||
}
|
||||
|
||||
input[type="submit"][required]:active,
|
||||
input[type="button"][required]:active
|
||||
{
|
||||
background-color: darkred;
|
||||
}
|
||||
|
||||
input[readonly]
|
||||
{
|
||||
background-color: lightgray;
|
||||
}
|
||||
|
||||
textarea
|
||||
{
|
||||
resize: none;
|
||||
width: 100%;
|
||||
border-radius: 10px;
|
||||
border-radius: 5px;
|
||||
border: 1px solid black;
|
||||
padding: 10px;
|
||||
box-sizing: border-box;
|
||||
height: 200px;
|
||||
font-family: Consolas;
|
||||
height: 68vh;
|
||||
font-family: 'Consolas';
|
||||
}
|
||||
|
||||
.select-container::after
|
||||
@@ -60,17 +112,17 @@ textarea
|
||||
|
||||
form
|
||||
{
|
||||
max-width: 50%;
|
||||
max-width: 500px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.admin-menu a
|
||||
.admin-menu > p a
|
||||
{
|
||||
font-size: 16pt;
|
||||
}
|
||||
|
||||
.logout, .logout:link, .logout:link:visited
|
||||
.comment.logout
|
||||
{
|
||||
font-size: 16pt;
|
||||
color: red !important;
|
||||
}
|
||||
|
||||
@@ -94,48 +146,34 @@ table
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.form-group input
|
||||
{
|
||||
width: auto;
|
||||
}
|
||||
|
||||
.text-danger
|
||||
{
|
||||
text-decoration: solid;
|
||||
color: red;
|
||||
}
|
||||
|
||||
.btn
|
||||
{
|
||||
background-color: #343434;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.btn-danger
|
||||
{
|
||||
background-color: red;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.checkbox
|
||||
{
|
||||
width: auto;
|
||||
}
|
||||
|
||||
.readonly
|
||||
{
|
||||
background-color: lightgray;
|
||||
}
|
||||
|
||||
.reorder-arrow:link
|
||||
{
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 700px)
|
||||
@media only screen and (max-width: 1080px)
|
||||
{
|
||||
form
|
||||
.hide-l1
|
||||
{
|
||||
max-width: initial;
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 850px)
|
||||
{
|
||||
.hide-l2
|
||||
{
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
@@ -51,3 +51,11 @@
|
||||
{
|
||||
color: #d69d85;
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 500px)
|
||||
{
|
||||
footer
|
||||
{
|
||||
padding: 20px;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
@font-face
|
||||
{
|
||||
font-family: 'Consolas';
|
||||
src: local("Consolas"), url("/fonts/Consolas/consolas.eot"), url("/fonts/Consolas/consolas.eot?#iefix") format("embedded-opentype"), url("/fonts/Consolas/consolas.otf") format("opentype"), url("/fonts/Consolas/consolas.svg") format("svg"), url("/fonts/Consolas/consolas.ttf") format("truetype"), url("/fonts/Consolas/consolas.woff") format("woff"), url("/fonts/Consolas/consolas.woff2") format("woff2");
|
||||
}
|
||||
|
||||
@font-face
|
||||
{
|
||||
font-family: 'SegoeMDL2Assets';
|
||||
src: local("Segoe MDL2 Assets"), url("/fonts/Segoe MDL2 Assets/segoeMLD2assets.eot"), url("/fonts/Segoe MDL2 Assets/segoeMLD2assets.eot?#iefix") format("embedded-opentype"), url("/fonts/Segoe MDL2 Assets/segoeMLD2assets.otf") format("opentype"), url("/fonts/Segoe MDL2 Assets/segoeMLD2assets.svg") format("svg"), url("/fonts/Segoe MDL2 Assets/segoeMLD2assets.ttf") format("truetype"), url("/fonts/Segoe MDL2 Assets/segoeMLD2assets.woff") format("woff"), url("/fonts/Segoe MDL2 Assets/segoeMLD2assets.woff2") format("woff2");
|
||||
}
|
||||
|
||||
@font-face
|
||||
{
|
||||
font-family: 'Calibri';
|
||||
src: local("Calibri"), url("/fonts/Calibri/calibri.eot"), url("/fonts/Calibri/calibri.eot?#iefix") format("embedded-opentype"), url("/fonts/Calibri/calibri.otf") format("opentype"), url("/fonts/Calibri/calibri.svg") format("svg"), url("/fonts/Calibri/calibri.ttf") format("truetype"), url("/fonts/Calibri/calibri.woff") format("woff"), url("/fonts/Calibri/calibri.woff2") format("woff2");
|
||||
}
|
||||
|
||||
@font-face
|
||||
{
|
||||
font-family: 'SegoeUISymbol';
|
||||
src: local("Segoe UI Symbol"), url("/fonts/Segoe UI Symbol/segoeUISymbol.eot"), url("/fonts/Segoe UI Symbol/segoeUISymbol.eot?#iefix") format("embedded-opentype"), url("/fonts/Segoe UI Symbol/segoeUISymbol.otf") format("opentype"), url("/fonts/Segoe UI Symbol/segoeUISymbol.svg") format("svg"), url("/fonts/Segoe UI Symbol/segoeUISymbol.ttf") format("truetype"), url("/fonts/Segoe UI Symbol/segoeUISymbol.woff") format("woff"), url("/fonts/Segoe UI Symbol/segoeUISymbol.woff2") format("woff2");
|
||||
}
|
||||
@@ -14,6 +14,27 @@
|
||||
transform: scale(1.1);
|
||||
}
|
||||
|
||||
/* Image details page styles */
|
||||
.image-overview-block img
|
||||
{
|
||||
max-height: 50vh;
|
||||
max-width: 100%;
|
||||
float: left;
|
||||
cursor: zoom-in;
|
||||
}
|
||||
|
||||
.image-overview-block > div,
|
||||
.image-overview-block > form
|
||||
{
|
||||
display: inline-block;
|
||||
margin-left: 20px;
|
||||
}
|
||||
|
||||
.image-overview-block h1
|
||||
{
|
||||
margin-bottom: 0px;
|
||||
}
|
||||
|
||||
/* Adaptive code */
|
||||
@media only screen and (max-width: 700px)
|
||||
{
|
||||
@@ -28,22 +49,10 @@
|
||||
}
|
||||
}
|
||||
|
||||
/* Image details page styles */
|
||||
.image-overview-block img
|
||||
@media only screen and (max-width: 500px)
|
||||
{
|
||||
max-height: 50vh;
|
||||
max-width: 100%;
|
||||
float: left;
|
||||
cursor: zoom-in;
|
||||
}
|
||||
|
||||
.image-overview-block div
|
||||
{
|
||||
display: inline-block;
|
||||
margin-left: 20px;
|
||||
}
|
||||
|
||||
.image-overview-block h1
|
||||
{
|
||||
margin-bottom: 0px;
|
||||
.image-overview-block img
|
||||
{
|
||||
max-height: unset;
|
||||
}
|
||||
}
|
||||
@@ -4,7 +4,8 @@ header
|
||||
display: grid;
|
||||
grid-template-columns: 1fr auto;
|
||||
grid-column-gap: 20px;
|
||||
margin: 20px 50px;
|
||||
margin-top: 20px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
h1
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -2,21 +2,6 @@
|
||||
This file contains main layout styles which applies to every View. In some views this rules are overrided in separate CSS files
|
||||
*/
|
||||
|
||||
/* Declaring fonts */
|
||||
@font-face
|
||||
{
|
||||
font-family: 'Consolas';
|
||||
src: url("/fonts/Consolas/consolas.eot");
|
||||
src: url("/fonts/Consolas/consolas.eot?#iefix") format("embedded-opentype"), url("/fonts/Consolas/consolas.otf") format("opentype"), url("/fonts/Consolas/consolas.svg") format("svg"), url("/fonts/Consolas/consolas.ttf") format("truetype"), url("/fonts/Consolas/consolas.woff") format("woff"), url("/fonts/Consolas/consolas.woff2") format("woff2");
|
||||
}
|
||||
|
||||
@font-face
|
||||
{
|
||||
font-family: 'Segoe MDL2 Assets';
|
||||
src: url("/fonts/Segoe MDL2 Assets/segoeMLD2assets.eot");
|
||||
src: url("/fonts/Segoe MDL2 Assets/segoeMLD2assets.eot?#iefix") format("embedded-opentype"), url("/fonts/Segoe MDL2 Assets/segoeMLD2assets.otf") format("opentype"), url("/fonts/Segoe MDL2 Assets/segoeMLD2assets.svg") format("svg"), url("/fonts/Segoe MDL2 Assets/segoeMLD2assets.ttf") format("truetype"), url("/fonts/Segoe MDL2 Assets/segoeMLD2assets.woff") format("woff"), url("/fonts/Segoe MDL2 Assets/segoeMLD2assets.woff2") format("woff2");
|
||||
}
|
||||
|
||||
/* Header styles */
|
||||
nav
|
||||
{
|
||||
@@ -33,6 +18,7 @@ nav
|
||||
padding: 10px;
|
||||
min-height: 33px;
|
||||
font-size: 26px;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
nav a
|
||||
@@ -66,30 +52,6 @@ menu
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
/* Adaptive code */
|
||||
@media only screen and (min-width: 1000px)
|
||||
{
|
||||
menu
|
||||
{
|
||||
display: initial !important;
|
||||
grid-row: 1;
|
||||
grid-column: 2;
|
||||
margin: 0px;
|
||||
}
|
||||
|
||||
menu li
|
||||
{
|
||||
display: inline-block;
|
||||
margin-right: 10px;
|
||||
margin-top: 0px;
|
||||
}
|
||||
|
||||
#menu-toggle
|
||||
{
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
/* Footer styles */
|
||||
footer
|
||||
{
|
||||
@@ -123,7 +85,7 @@ body
|
||||
overflow: auto;
|
||||
margin: 0px;
|
||||
margin-top: 53px;
|
||||
font-family: 'Consolas', 'Segoe MDL2 Assets';
|
||||
font-family: 'Consolas', 'SegoeMDL2Assets';
|
||||
/* This stuff is necessary for sticky footer */
|
||||
display: grid;
|
||||
grid-template-rows: 1fr auto;
|
||||
@@ -136,12 +98,12 @@ header a
|
||||
color: black;
|
||||
}
|
||||
|
||||
header a:hover
|
||||
{
|
||||
a:link:hover
|
||||
{
|
||||
text-decoration: underline;
|
||||
}
|
||||
}
|
||||
|
||||
article, header
|
||||
article
|
||||
{
|
||||
margin: 0px 50px;
|
||||
}
|
||||
@@ -151,7 +113,60 @@ article, header
|
||||
color: blue;
|
||||
}
|
||||
|
||||
header
|
||||
{
|
||||
margin: 16px 50px;
|
||||
}
|
||||
|
||||
.comment, .comment:visited
|
||||
{
|
||||
color: #57a64a !important;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
*[hidden]
|
||||
{
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* Adaptive code */
|
||||
@media only screen and (min-width: 980px)
|
||||
{
|
||||
menu
|
||||
{
|
||||
display: initial !important;
|
||||
grid-row: 1;
|
||||
grid-column: 2;
|
||||
margin: 0px;
|
||||
}
|
||||
|
||||
menu li
|
||||
{
|
||||
display: inline-block;
|
||||
margin-right: 10px;
|
||||
margin-top: 0px;
|
||||
}
|
||||
|
||||
#menu-toggle
|
||||
{
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 500px)
|
||||
{
|
||||
article
|
||||
{
|
||||
margin: 0px 20px;
|
||||
}
|
||||
|
||||
header
|
||||
{
|
||||
margin: 16px 20px;
|
||||
}
|
||||
}
|
||||
|
||||
nav > div > a:nth-last-child(2)
|
||||
{
|
||||
visibility: hidden;
|
||||
}
|
||||
Binary file not shown.
Binary file not shown.
File diff suppressed because it is too large
Load Diff
|
After Width: | Height: | Size: 5.8 MiB |
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
File diff suppressed because it is too large
Load Diff
|
After Width: | Height: | Size: 6.0 MiB |
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
File diff suppressed because one or more lines are too long
|
Before Width: | Height: | Size: 315 KiB |
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,41 @@
|
||||
function Up(btn)
|
||||
{
|
||||
var item = btn.parentNode.parentNode;
|
||||
var table = document.querySelector("tbody");
|
||||
|
||||
table.insertBefore(item, item.previousElementSibling);
|
||||
|
||||
document.querySelector("button").disabled = false;
|
||||
}
|
||||
|
||||
function Down(btn)
|
||||
{
|
||||
var item = btn.parentNode.parentNode;
|
||||
var table = document.querySelector("tbody");
|
||||
|
||||
table.insertBefore(item, item.nextElementSibling.nextElementSibling);
|
||||
|
||||
document.querySelector("button").disabled = false;
|
||||
}
|
||||
|
||||
function ApplyReorder()
|
||||
{
|
||||
var table = document.querySelector("tbody");
|
||||
|
||||
var form = document.createElement("form");
|
||||
form.method = "post";
|
||||
form.hidden = true;
|
||||
|
||||
document.body.appendChild(form);
|
||||
|
||||
for (var k = 0; k < table.children.length; k++)
|
||||
{
|
||||
var item = document.createElement("input");
|
||||
item.type = "text";
|
||||
item.name = "reorderList";
|
||||
item.value = table.children[k].id;
|
||||
form.appendChild(item);
|
||||
}
|
||||
|
||||
form.submit();
|
||||
}
|
||||
Reference in New Issue
Block a user