Remove deprecated MVC routes, views, and models
This commit is contained in:
parent
4efbbe8a4e
commit
1158886c52
41 changed files with 0 additions and 3477 deletions
|
@ -1,51 +0,0 @@
|
|||
using LANCommander.Models;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace LANCommander.Controllers.Api
|
||||
{
|
||||
[Route("api/[controller]")]
|
||||
[ApiController]
|
||||
public class UploadController : ControllerBase
|
||||
{
|
||||
private const string UploadDirectory = "Upload";
|
||||
|
||||
[HttpPost("Init")]
|
||||
public string Init()
|
||||
{
|
||||
var key = Guid.NewGuid().ToString();
|
||||
|
||||
if (!Directory.Exists(UploadDirectory))
|
||||
Directory.CreateDirectory(UploadDirectory);
|
||||
|
||||
if (!System.IO.File.Exists(Path.Combine(UploadDirectory, key)))
|
||||
System.IO.File.Create(Path.Combine(UploadDirectory, key)).Close();
|
||||
|
||||
return key;
|
||||
}
|
||||
|
||||
[HttpPost("Chunk")]
|
||||
public async Task Chunk([FromForm] ChunkUpload chunk)
|
||||
{
|
||||
var filePath = Path.Combine(UploadDirectory, chunk.Key.ToString());
|
||||
|
||||
if (!System.IO.File.Exists(filePath))
|
||||
throw new Exception("Destination file not initialized.");
|
||||
|
||||
Request.EnableBuffering();
|
||||
|
||||
using (var ms = new MemoryStream())
|
||||
{
|
||||
await chunk.File.CopyToAsync(ms);
|
||||
|
||||
var data = ms.ToArray();
|
||||
|
||||
using (var fs = new FileStream(filePath, FileMode.Append, FileAccess.Write, FileShare.None))
|
||||
{
|
||||
fs.Position = chunk.Start;
|
||||
fs.Write(data, 0, data.Length);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,140 +0,0 @@
|
|||
using LANCommander.Data;
|
||||
using LANCommander.Data.Models;
|
||||
using LANCommander.Extensions;
|
||||
using LANCommander.Models;
|
||||
using LANCommander.SDK;
|
||||
using LANCommander.Services;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using System.IO.Compression;
|
||||
using YamlDotNet.Serialization;
|
||||
using YamlDotNet.Serialization.NamingConventions;
|
||||
|
||||
namespace LANCommander.Controllers
|
||||
{
|
||||
[Authorize(Roles = "Administrator")]
|
||||
public class ArchivesController : Controller
|
||||
{
|
||||
private readonly GameService GameService;
|
||||
private readonly ArchiveService ArchiveService;
|
||||
|
||||
public ArchivesController(GameService gameService, ArchiveService archiveService)
|
||||
{
|
||||
GameService = gameService;
|
||||
ArchiveService = archiveService;
|
||||
}
|
||||
|
||||
public async Task<IActionResult> Add(Guid? id)
|
||||
{
|
||||
if (id == null)
|
||||
return NotFound();
|
||||
|
||||
var game = await GameService.Get(id.GetValueOrDefault());
|
||||
|
||||
if (game == null)
|
||||
return NotFound();
|
||||
|
||||
Archive lastVersion = null;
|
||||
|
||||
if (game.Archives != null && game.Archives.Count > 0)
|
||||
lastVersion = game.Archives.OrderByDescending(a => a.CreatedOn).First();
|
||||
|
||||
return View(new Archive()
|
||||
{
|
||||
Game = game,
|
||||
GameId = game.Id,
|
||||
LastVersion = lastVersion,
|
||||
});
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
public async Task<IActionResult> Add(Guid? id, Archive archive)
|
||||
{
|
||||
archive.Id = Guid.Empty;
|
||||
|
||||
var game = await GameService.Get(id.GetValueOrDefault());
|
||||
|
||||
if (game == null)
|
||||
return NotFound();
|
||||
|
||||
archive.Game = game;
|
||||
archive.GameId = game.Id;
|
||||
|
||||
if (game.Archives != null && game.Archives.Any(a => a.Version == archive.Version))
|
||||
ModelState.AddModelError("Version", "An archive for this game is already using that version.");
|
||||
|
||||
if (ModelState.IsValid)
|
||||
{
|
||||
await ArchiveService.Update(archive);
|
||||
|
||||
return RedirectToAction("Edit", "Games", new { id = id });
|
||||
}
|
||||
|
||||
return View(archive);
|
||||
}
|
||||
|
||||
public async Task<IActionResult> Download(Guid id)
|
||||
{
|
||||
var archive = await ArchiveService.Get(id);
|
||||
|
||||
var content = new FileStream($"Upload/{archive.ObjectKey}".ToPath(), FileMode.Open, FileAccess.Read, FileShare.Read);
|
||||
|
||||
return File(content, "application/octet-stream", $"{archive.Game.Title.SanitizeFilename()}.zip");
|
||||
}
|
||||
|
||||
public async Task<IActionResult> Delete(Guid? id)
|
||||
{
|
||||
var archive = await ArchiveService.Get(id.GetValueOrDefault());
|
||||
var gameId = archive.Game.Id;
|
||||
|
||||
await ArchiveService.Delete(archive);
|
||||
|
||||
return RedirectToAction("Edit", "Games", new { id = gameId });
|
||||
}
|
||||
|
||||
public async Task<IActionResult> Browse(Guid id)
|
||||
{
|
||||
var archive = await ArchiveService.Get(id);
|
||||
|
||||
return View(archive);
|
||||
}
|
||||
|
||||
public async Task<IActionResult> Validate(Guid id, Archive archive)
|
||||
{
|
||||
var path = $"Upload/{id}".ToPath();
|
||||
|
||||
string manifestContents = String.Empty;
|
||||
long compressedSize = 0;
|
||||
long uncompressedSize = 0;
|
||||
|
||||
if (!System.IO.File.Exists(path))
|
||||
return BadRequest("Specified object does not exist");
|
||||
|
||||
var game = await GameService.Get(archive.GameId);
|
||||
|
||||
if (game == null)
|
||||
return BadRequest("The related game is missing or corrupt.");
|
||||
|
||||
archive.GameId = game.Id;
|
||||
archive.Id = Guid.Empty;
|
||||
archive.CompressedSize = compressedSize;
|
||||
archive.UncompressedSize = uncompressedSize;
|
||||
archive.ObjectKey = id.ToString();
|
||||
|
||||
try
|
||||
{
|
||||
archive = await ArchiveService.Add(archive);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
return Json(new
|
||||
{
|
||||
Id = archive.Id,
|
||||
ObjectKey = archive.ObjectKey,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,166 +0,0 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc.Rendering;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using LANCommander.Data;
|
||||
using LANCommander.Data.Models;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
|
||||
namespace LANCommander.Controllers
|
||||
{
|
||||
[Authorize(Roles = "Administrator")]
|
||||
public class CompaniesController : Controller
|
||||
{
|
||||
private readonly DatabaseContext _context;
|
||||
|
||||
public CompaniesController(DatabaseContext context)
|
||||
{
|
||||
_context = context;
|
||||
}
|
||||
|
||||
// GET: Companies
|
||||
public async Task<IActionResult> Index()
|
||||
{
|
||||
return _context.Companies != null ?
|
||||
View(await _context.Companies.ToListAsync()) :
|
||||
Problem("Entity set 'DatabaseContext.Companies' is null.");
|
||||
}
|
||||
|
||||
// GET: Companies/Details/5
|
||||
public async Task<IActionResult> Details(Guid? id)
|
||||
{
|
||||
if (id == null || _context.Companies == null)
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
|
||||
var company = await _context.Companies
|
||||
.FirstOrDefaultAsync(m => m.Id == id);
|
||||
if (company == null)
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
|
||||
return View(company);
|
||||
}
|
||||
|
||||
// GET: Companies/Create
|
||||
public IActionResult Create()
|
||||
{
|
||||
return View();
|
||||
}
|
||||
|
||||
// POST: Companies/Create
|
||||
// To protect from overposting attacks, enable the specific properties you want to bind to.
|
||||
// For more details, see http://go.microsoft.com/fwlink/?LinkId=317598.
|
||||
[HttpPost]
|
||||
[ValidateAntiForgeryToken]
|
||||
public async Task<IActionResult> Create([Bind("Name,Id,CreatedOn,CreatedById,UpdatedOn,UpdatedById")] Company company)
|
||||
{
|
||||
if (ModelState.IsValid)
|
||||
{
|
||||
company.Id = Guid.NewGuid();
|
||||
_context.Add(company);
|
||||
await _context.SaveChangesAsync();
|
||||
return RedirectToAction(nameof(Index));
|
||||
}
|
||||
return View(company);
|
||||
}
|
||||
|
||||
// GET: Companies/Edit/5
|
||||
public async Task<IActionResult> Edit(Guid? id)
|
||||
{
|
||||
if (id == null || _context.Companies == null)
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
|
||||
var company = await _context.Companies.FindAsync(id);
|
||||
if (company == null)
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
return View(company);
|
||||
}
|
||||
|
||||
// POST: Companies/Edit/5
|
||||
// To protect from overposting attacks, enable the specific properties you want to bind to.
|
||||
// For more details, see http://go.microsoft.com/fwlink/?LinkId=317598.
|
||||
[HttpPost]
|
||||
[ValidateAntiForgeryToken]
|
||||
public async Task<IActionResult> Edit(Guid id, [Bind("Name,Id,CreatedOn,CreatedById,UpdatedOn,UpdatedById")] Company company)
|
||||
{
|
||||
if (id != company.Id)
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
|
||||
if (ModelState.IsValid)
|
||||
{
|
||||
try
|
||||
{
|
||||
_context.Update(company);
|
||||
await _context.SaveChangesAsync();
|
||||
}
|
||||
catch (DbUpdateConcurrencyException)
|
||||
{
|
||||
if (!CompanyExists(company.Id))
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
else
|
||||
{
|
||||
throw;
|
||||
}
|
||||
}
|
||||
return RedirectToAction(nameof(Index));
|
||||
}
|
||||
return View(company);
|
||||
}
|
||||
|
||||
// GET: Companies/Delete/5
|
||||
public async Task<IActionResult> Delete(Guid? id)
|
||||
{
|
||||
if (id == null || _context.Companies == null)
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
|
||||
var company = await _context.Companies
|
||||
.FirstOrDefaultAsync(m => m.Id == id);
|
||||
if (company == null)
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
|
||||
return View(company);
|
||||
}
|
||||
|
||||
// POST: Companies/Delete/5
|
||||
[HttpPost, ActionName("Delete")]
|
||||
[ValidateAntiForgeryToken]
|
||||
public async Task<IActionResult> DeleteConfirmed(Guid id)
|
||||
{
|
||||
if (_context.Companies == null)
|
||||
{
|
||||
return Problem("Entity set 'DatabaseContext.Companies' is null.");
|
||||
}
|
||||
var company = await _context.Companies.FindAsync(id);
|
||||
if (company != null)
|
||||
{
|
||||
_context.Companies.Remove(company);
|
||||
}
|
||||
|
||||
await _context.SaveChangesAsync();
|
||||
return RedirectToAction(nameof(Index));
|
||||
}
|
||||
|
||||
private bool CompanyExists(Guid id)
|
||||
{
|
||||
return (_context.Companies?.Any(e => e.Id == id)).GetValueOrDefault();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,577 +0,0 @@
|
|||
using System;
|
||||
using System.IO;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc.Rendering;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using LANCommander.Data;
|
||||
using LANCommander.Data.Models;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using LANCommander.Services;
|
||||
using System.Drawing;
|
||||
using LANCommander.Models;
|
||||
using LANCommander.Data.Enums;
|
||||
using LANCommander.PCGamingWiki;
|
||||
|
||||
namespace LANCommander.Controllers
|
||||
{
|
||||
[Authorize(Roles = "Administrator")]
|
||||
public class GamesController : Controller
|
||||
{
|
||||
private readonly GameService GameService;
|
||||
private readonly ArchiveService ArchiveService;
|
||||
private readonly CategoryService CategoryService;
|
||||
private readonly TagService TagService;
|
||||
private readonly GenreService GenreService;
|
||||
private readonly CompanyService CompanyService;
|
||||
private readonly IGDBService IGDBService;
|
||||
private readonly PCGamingWikiClient PCGamingWikiClient;
|
||||
|
||||
public GamesController(GameService gameService, ArchiveService archiveService, CategoryService categoryService, TagService tagService, GenreService genreService, CompanyService companyService, IGDBService igdbService)
|
||||
{
|
||||
GameService = gameService;
|
||||
ArchiveService = archiveService;
|
||||
CategoryService = categoryService;
|
||||
TagService = tagService;
|
||||
GenreService = genreService;
|
||||
CompanyService = companyService;
|
||||
IGDBService = igdbService;
|
||||
PCGamingWikiClient = new PCGamingWikiClient();
|
||||
}
|
||||
|
||||
// GET: Games
|
||||
public async Task<IActionResult> Index()
|
||||
{
|
||||
return View(GameService.Get());
|
||||
}
|
||||
|
||||
public async Task<IActionResult> Add(long? igdbid)
|
||||
{
|
||||
var viewModel = new GameViewModel()
|
||||
{
|
||||
Game = new Game(),
|
||||
Developers = new List<SelectListItem>(),
|
||||
Publishers = new List<SelectListItem>(),
|
||||
Genres = new List<SelectListItem>(),
|
||||
Tags = new List<SelectListItem>(),
|
||||
};
|
||||
|
||||
if (igdbid == null)
|
||||
{
|
||||
viewModel.Game = new Game()
|
||||
{
|
||||
Actions = new List<Data.Models.Action>(),
|
||||
MultiplayerModes = new List<Data.Models.MultiplayerMode>()
|
||||
};
|
||||
|
||||
viewModel.Developers = CompanyService.Get().OrderBy(c => c.Name).Select(c => new SelectListItem() { Text = c.Name, Value = c.Name }).ToList();
|
||||
viewModel.Publishers = CompanyService.Get().OrderBy(c => c.Name).Select(c => new SelectListItem() { Text = c.Name, Value = c.Name }).ToList();
|
||||
viewModel.Genres = GenreService.Get().OrderBy(g => g.Name).Select(g => new SelectListItem() { Text = g.Name, Value = g.Name }).ToList();
|
||||
viewModel.Tags = TagService.Get().OrderBy(t => t.Name).Select(t => new SelectListItem() { Text = t.Name, Value = t.Name }).ToList();
|
||||
|
||||
return View(viewModel);
|
||||
}
|
||||
|
||||
var result = await IGDBService.Get(igdbid.Value, "genres.*", "game_modes.*", "multiplayer_modes.*", "release_dates.*", "platforms.*", "keywords.*", "involved_companies.*", "involved_companies.company.*", "cover.*");
|
||||
|
||||
viewModel.Game = new Game()
|
||||
{
|
||||
IGDBId = result.Id.GetValueOrDefault(),
|
||||
Title = result.Name,
|
||||
Description = result.Summary,
|
||||
ReleasedOn = result.FirstReleaseDate.GetValueOrDefault().UtcDateTime,
|
||||
Actions = new List<Data.Models.Action>(),
|
||||
MultiplayerModes = new List<MultiplayerMode>()
|
||||
};
|
||||
|
||||
|
||||
var playerCounts = await PCGamingWikiClient.GetMultiplayerPlayerCounts(result.Name);
|
||||
|
||||
if (playerCounts != null)
|
||||
{
|
||||
foreach (var playerCount in playerCounts)
|
||||
{
|
||||
MultiplayerType type;
|
||||
|
||||
switch (playerCount.Key)
|
||||
{
|
||||
case "Local Play":
|
||||
type = MultiplayerType.Local;
|
||||
break;
|
||||
|
||||
case "LAN Play":
|
||||
type = MultiplayerType.Lan;
|
||||
break;
|
||||
|
||||
case "Online Play":
|
||||
type = MultiplayerType.Online;
|
||||
break;
|
||||
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
|
||||
viewModel.Game.MultiplayerModes.Add(new MultiplayerMode()
|
||||
{
|
||||
Type = type,
|
||||
MaxPlayers = playerCount.Value,
|
||||
MinPlayers = 2
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (result.GameModes != null && result.GameModes.Values != null)
|
||||
viewModel.Game.Singleplayer = result.GameModes.Values.Any(gm => gm.Name == "Singleplayer");
|
||||
|
||||
#region Multiplayer Modes
|
||||
if (result.MultiplayerModes != null && result.MultiplayerModes.Values != null)
|
||||
{
|
||||
var lan = result.MultiplayerModes.Values.Where(mm => mm.LanCoop.GetValueOrDefault()).OrderByDescending(mm => mm.OnlineMax).FirstOrDefault();
|
||||
var online = result.MultiplayerModes.Values.Where(mm => mm.OnlineCoop.GetValueOrDefault()).OrderByDescending(mm => mm.OnlineMax).FirstOrDefault();
|
||||
var offline = result.MultiplayerModes.Values.Where(mm => mm.OfflineCoop.GetValueOrDefault()).OrderByDescending(mm => mm.OnlineMax).FirstOrDefault();
|
||||
|
||||
if (lan != null)
|
||||
{
|
||||
viewModel.Game.MultiplayerModes.Add(new MultiplayerMode()
|
||||
{
|
||||
Type = MultiplayerType.Lan,
|
||||
MaxPlayers = lan.OnlineMax.GetValueOrDefault(),
|
||||
});
|
||||
}
|
||||
|
||||
if (online != null)
|
||||
{
|
||||
viewModel.Game.MultiplayerModes.Add(new MultiplayerMode()
|
||||
{
|
||||
Type = MultiplayerType.Online,
|
||||
MaxPlayers = online.OnlineMax.GetValueOrDefault(),
|
||||
});
|
||||
}
|
||||
|
||||
if (offline != null)
|
||||
{
|
||||
viewModel.Game.MultiplayerModes.Add(new MultiplayerMode()
|
||||
{
|
||||
Type = MultiplayerType.Local,
|
||||
MaxPlayers = offline.OfflineMax.GetValueOrDefault(),
|
||||
});
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Publishers & Developers
|
||||
var companies = CompanyService.Get();
|
||||
|
||||
if (result.InvolvedCompanies != null && result.InvolvedCompanies.Values != null)
|
||||
{
|
||||
// Make sure companie
|
||||
var developerNames = result.InvolvedCompanies.Values.Where(c => c.Developer.GetValueOrDefault()).Select(c => c.Company.Value.Name);
|
||||
var publisherNames = result.InvolvedCompanies.Values.Where(c => c.Publisher.GetValueOrDefault()).Select(c => c.Company.Value.Name);
|
||||
|
||||
viewModel.Developers.AddRange(companies.Select(c => new SelectListItem()
|
||||
{
|
||||
Text = c.Name,
|
||||
Value = c.Name,
|
||||
Selected = developerNames.Contains(c.Name),
|
||||
}));
|
||||
|
||||
viewModel.Publishers.AddRange(companies.Select(c => new SelectListItem()
|
||||
{
|
||||
Text = c.Name,
|
||||
Value = c.Name,
|
||||
Selected = publisherNames.Contains(c.Name),
|
||||
}));
|
||||
|
||||
foreach (var developer in developerNames)
|
||||
{
|
||||
if (!viewModel.Developers.Any(d => d.Value == developer))
|
||||
{
|
||||
viewModel.Developers.Add(new SelectListItem()
|
||||
{
|
||||
Text = developer,
|
||||
Value = developer,
|
||||
Selected = true
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var publisher in publisherNames)
|
||||
{
|
||||
if (!viewModel.Publishers.Any(d => d.Value == publisher))
|
||||
{
|
||||
viewModel.Publishers.Add(new SelectListItem()
|
||||
{
|
||||
Text = publisher,
|
||||
Value = publisher,
|
||||
Selected = true
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
viewModel.Developers = viewModel.Developers.OrderBy(d => d.Value).ToList();
|
||||
viewModel.Publishers = viewModel.Publishers.OrderBy(d => d.Value).ToList();
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Genres
|
||||
var genres = GenreService.Get();
|
||||
|
||||
if (result.Genres != null && result.Genres.Values != null)
|
||||
{
|
||||
var genreNames = result.Genres.Values.Select(g => g.Name);
|
||||
|
||||
viewModel.Genres.AddRange(genres.Select(g => new SelectListItem()
|
||||
{
|
||||
Text = g.Name,
|
||||
Value = g.Name,
|
||||
Selected = genreNames.Contains(g.Name),
|
||||
}));
|
||||
|
||||
foreach (var genre in genreNames)
|
||||
{
|
||||
if (!viewModel.Genres.Any(g => g.Value == genre))
|
||||
{
|
||||
viewModel.Genres.Add(new SelectListItem()
|
||||
{
|
||||
Text = genre,
|
||||
Value = genre,
|
||||
Selected = true
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
viewModel.Genres = viewModel.Genres.OrderBy(g => g.Value).ToList();
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Tags
|
||||
var tags = TagService.Get();
|
||||
|
||||
if (result.Keywords != null && result.Keywords.Values != null)
|
||||
{
|
||||
var tagNames = result.Keywords.Values.Select(t => t.Name).Take(20);
|
||||
|
||||
viewModel.Tags.AddRange(genres.Select(t => new SelectListItem()
|
||||
{
|
||||
Text = t.Name,
|
||||
Value = t.Name,
|
||||
Selected = tagNames.Contains(t.Name),
|
||||
}));
|
||||
|
||||
foreach (var tag in tagNames)
|
||||
{
|
||||
if (!viewModel.Tags.Any(t => t.Value == tag))
|
||||
{
|
||||
viewModel.Tags.Add(new SelectListItem()
|
||||
{
|
||||
Text = tag,
|
||||
Value = tag,
|
||||
Selected = true
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
return View(viewModel);
|
||||
}
|
||||
|
||||
// POST: Games/Create
|
||||
// To protect from overposting attacks, enable the specific properties you want to bind to.
|
||||
// For more details, see http://go.microsoft.com/fwlink/?LinkId=317598.
|
||||
[HttpPost]
|
||||
[ValidateAntiForgeryToken]
|
||||
public async Task<IActionResult> Add(GameViewModel viewModel)
|
||||
{
|
||||
if (ModelState.IsValid)
|
||||
{
|
||||
var game = await GameService.Add(viewModel.Game);
|
||||
|
||||
if (viewModel.SelectedDevelopers != null && viewModel.SelectedDevelopers.Length > 0)
|
||||
game.Developers = viewModel.SelectedDevelopers.Select(async d => await CompanyService.AddMissing(x => x.Name == d, new Company() { Name = d })).Select(t => t.Result).ToList();
|
||||
|
||||
if (viewModel.SelectedPublishers != null && viewModel.SelectedPublishers.Length > 0)
|
||||
game.Publishers = viewModel.SelectedPublishers.Select(async p => await CompanyService.AddMissing(x => x.Name == p, new Company() { Name = p })).Select(t => t.Result).ToList();
|
||||
|
||||
if (viewModel.SelectedGenres != null && viewModel.SelectedGenres.Length > 0)
|
||||
game.Genres = viewModel.SelectedGenres.Select(async g => await GenreService.AddMissing(x => x.Name == g, new Genre() { Name = g })).Select(t => t.Result).ToList();
|
||||
|
||||
if (viewModel.SelectedTags != null && viewModel.SelectedTags.Length > 0)
|
||||
game.Tags = viewModel.SelectedTags.Select(async t => await TagService.AddMissing(x => x.Name == t, new Tag() { Name = t })).Select(t => t.Result).ToList();
|
||||
|
||||
await GameService.Update(game);
|
||||
|
||||
return RedirectToAction(nameof(Edit), new { id = game.Id });
|
||||
}
|
||||
|
||||
return View(viewModel.Game);
|
||||
}
|
||||
|
||||
// GET: Games/Edit/5
|
||||
public async Task<IActionResult> Edit(Guid? id)
|
||||
{
|
||||
var viewModel = new GameViewModel();
|
||||
|
||||
viewModel.Game = await GameService.Get(id.GetValueOrDefault());
|
||||
|
||||
if (viewModel.Game == null)
|
||||
return NotFound();
|
||||
|
||||
viewModel.Developers = CompanyService.Get()
|
||||
.OrderBy(c => c.Name)
|
||||
.Select(c => new SelectListItem() { Text = c.Name, Value = c.Name, Selected = viewModel.Game.Developers.Any(d => d.Id == c.Id) })
|
||||
.ToList();
|
||||
|
||||
viewModel.Publishers = CompanyService.Get()
|
||||
.OrderBy(c => c.Name)
|
||||
.Select(c => new SelectListItem() { Text = c.Name, Value = c.Name, Selected = viewModel.Game.Publishers.Any(d => d.Id == c.Id) })
|
||||
.ToList();
|
||||
|
||||
viewModel.Genres = GenreService.Get()
|
||||
.OrderBy(g => g.Name)
|
||||
.Select(g => new SelectListItem() { Text = g.Name, Value = g.Name, Selected = viewModel.Game.Genres.Any(x => x.Id == g.Id) })
|
||||
.ToList();
|
||||
|
||||
viewModel.Tags = TagService.Get()
|
||||
.OrderBy(t => t.Name)
|
||||
.Select(t => new SelectListItem() { Text = t.Name, Value = t.Name, Selected = viewModel.Game.Tags.Any(x => x.Id == t.Id) })
|
||||
.ToList();
|
||||
|
||||
return View(viewModel);
|
||||
}
|
||||
|
||||
// POST: Games/Edit/5
|
||||
// To protect from overposting attacks, enable the specific properties you want to bind to.
|
||||
// For more details, see http://go.microsoft.com/fwlink/?LinkId=317598.
|
||||
[HttpPost]
|
||||
[ValidateAntiForgeryToken]
|
||||
public async Task<IActionResult> Edit(Guid id, GameViewModel viewModel)
|
||||
{
|
||||
if (id != viewModel.Game.Id)
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
|
||||
if (ModelState.IsValid)
|
||||
{
|
||||
var game = GameService.Get(g => g.Id == viewModel.Game.Id).FirstOrDefault();
|
||||
|
||||
game.Title = viewModel.Game.Title;
|
||||
game.SortTitle = viewModel.Game.SortTitle;
|
||||
game.DirectoryName = viewModel.Game.DirectoryName;
|
||||
game.Icon = viewModel.Game.Icon;
|
||||
game.Description = viewModel.Game.Description;
|
||||
game.ReleasedOn = viewModel.Game.ReleasedOn;
|
||||
game.Singleplayer = viewModel.Game.Singleplayer;
|
||||
|
||||
#region Update Developers
|
||||
if (viewModel.SelectedDevelopers == null)
|
||||
viewModel.SelectedDevelopers = new string[0];
|
||||
|
||||
foreach (var developer in game.Developers)
|
||||
{
|
||||
if (!viewModel.SelectedDevelopers.Any(d => d == developer.Name))
|
||||
game.Developers.Remove(developer);
|
||||
}
|
||||
|
||||
foreach (var newDeveloper in viewModel.SelectedDevelopers.Where(sd => !game.Developers.Any(d => d.Name == sd)))
|
||||
{
|
||||
game.Developers.Add(new Company()
|
||||
{
|
||||
Name = newDeveloper
|
||||
});
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Update Publishers
|
||||
if (viewModel.SelectedPublishers == null)
|
||||
viewModel.SelectedPublishers = new string[0];
|
||||
|
||||
foreach (var publisher in game.Publishers)
|
||||
{
|
||||
if (!viewModel.SelectedPublishers.Any(p => p == publisher.Name))
|
||||
game.Publishers.Remove(publisher);
|
||||
}
|
||||
|
||||
foreach (var newPublisher in viewModel.SelectedPublishers.Where(sp => !game.Publishers.Any(p => p.Name == sp)))
|
||||
{
|
||||
game.Publishers.Add(new Company()
|
||||
{
|
||||
Name = newPublisher
|
||||
});
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Update Genres
|
||||
if (viewModel.SelectedGenres == null)
|
||||
viewModel.SelectedGenres = new string[0];
|
||||
|
||||
foreach (var genre in game.Genres)
|
||||
{
|
||||
if (!viewModel.SelectedGenres.Any(g => g == genre.Name))
|
||||
game.Genres.Remove(genre);
|
||||
}
|
||||
|
||||
foreach (var newGenre in viewModel.SelectedGenres.Where(sg => !game.Genres.Any(g => g.Name == sg)))
|
||||
{
|
||||
game.Genres.Add(new Genre()
|
||||
{
|
||||
Name = newGenre
|
||||
});
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Update Tags
|
||||
if (viewModel.SelectedTags == null)
|
||||
viewModel.SelectedTags = new string[0];
|
||||
|
||||
foreach (var tag in game.Tags)
|
||||
{
|
||||
if (!viewModel.SelectedTags.Any(t => t == tag.Name))
|
||||
game.Tags.Remove(tag);
|
||||
}
|
||||
|
||||
foreach (var newTag in viewModel.SelectedTags.Where(st => !game.Tags.Any(t => t.Name == st)))
|
||||
{
|
||||
game.Tags.Add(new Tag()
|
||||
{
|
||||
Name = newTag
|
||||
});
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Update Actions
|
||||
if (game.Actions != null)
|
||||
{
|
||||
game.Actions.Clear();
|
||||
|
||||
if (viewModel.Game.Actions != null)
|
||||
{
|
||||
foreach (var action in viewModel.Game.Actions)
|
||||
{
|
||||
game.Actions.Add(action);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Update MultiplayerModes
|
||||
if (game.MultiplayerModes != null)
|
||||
{
|
||||
game.MultiplayerModes.Clear();
|
||||
|
||||
if (viewModel.Game.MultiplayerModes != null)
|
||||
{
|
||||
foreach (var multiplayerMode in viewModel.Game.MultiplayerModes)
|
||||
{
|
||||
game.MultiplayerModes.Add(multiplayerMode);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
await GameService.Update(game);
|
||||
|
||||
return RedirectToAction(nameof(Edit), new { id = id });
|
||||
}
|
||||
|
||||
return View(viewModel);
|
||||
}
|
||||
|
||||
// GET: Games/Delete/5
|
||||
public async Task<IActionResult> Delete(Guid? id)
|
||||
{
|
||||
var game = await GameService.Get(id.GetValueOrDefault());
|
||||
|
||||
if (game == null)
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
|
||||
return View(game);
|
||||
}
|
||||
|
||||
// POST: Games/Delete/5
|
||||
[HttpPost, ActionName("Delete")]
|
||||
[ValidateAntiForgeryToken]
|
||||
public async Task<IActionResult> DeleteConfirmed(Guid id)
|
||||
{
|
||||
var game = await GameService.Get(id);
|
||||
|
||||
if (game == null)
|
||||
return NotFound();
|
||||
|
||||
await GameService.Delete(game);
|
||||
|
||||
return RedirectToAction(nameof(Index));
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
public async Task<IActionResult> Lookup(Game game)
|
||||
{
|
||||
var viewModel = new GameLookupResultsViewModel()
|
||||
{
|
||||
Search = game.Title
|
||||
};
|
||||
|
||||
var results = await IGDBService.Search(game.Title, "involved_companies.*", "involved_companies.company.*");
|
||||
|
||||
if (results == null)
|
||||
return View(new List<Game>());
|
||||
|
||||
viewModel.Results = results.Select(r =>
|
||||
{
|
||||
var result = new Game()
|
||||
{
|
||||
IGDBId = r.Id.GetValueOrDefault(),
|
||||
Title = r.Name,
|
||||
ReleasedOn = r.FirstReleaseDate.GetValueOrDefault().UtcDateTime,
|
||||
Developers = new List<Company>()
|
||||
};
|
||||
|
||||
if (r.InvolvedCompanies != null && r.InvolvedCompanies.Values != null)
|
||||
{
|
||||
result.Developers = r.InvolvedCompanies.Values.Where(c => c.Developer.HasValue && c.Developer.GetValueOrDefault() && c.Company != null && c.Company.Value != null).Select(c => new Company()
|
||||
{
|
||||
Name = c.Company.Value.Name
|
||||
}).ToList();
|
||||
}
|
||||
|
||||
return result;
|
||||
});
|
||||
|
||||
return View(viewModel);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Provides a list of possible games based on the given name
|
||||
/// </summary>
|
||||
/// <param name="name">Name of the game to lookup against IGDB</param>
|
||||
/// <returns></returns>
|
||||
public async Task<IActionResult> SearchMetadata(string name)
|
||||
{
|
||||
var metadata = await IGDBService.Search(name, "genres.*", "multiplayer_modes.*", "release_dates.*", "platforms.*", "keywords.*", "involved_companies.*", "involved_companies.company.*", "cover.*");
|
||||
|
||||
if (metadata == null)
|
||||
return NotFound();
|
||||
|
||||
return Json(metadata);
|
||||
}
|
||||
|
||||
public async Task<IActionResult> GetIcon(Guid id)
|
||||
{
|
||||
try
|
||||
{
|
||||
var game = await GameService.Get(id);
|
||||
|
||||
return File(GameService.GetIcon(game), "image/png");
|
||||
}
|
||||
catch (FileNotFoundException ex)
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,110 +0,0 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc.Rendering;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using LANCommander.Data;
|
||||
using LANCommander.Data.Models;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using LANCommander.Models;
|
||||
using LANCommander.Services;
|
||||
|
||||
namespace LANCommander.Controllers
|
||||
{
|
||||
[Authorize(Roles = "Administrator")]
|
||||
public class KeysController : Controller
|
||||
{
|
||||
private readonly DatabaseContext Context;
|
||||
private readonly KeyService KeyService;
|
||||
|
||||
public KeysController(DatabaseContext context, KeyService keyService)
|
||||
{
|
||||
Context = context;
|
||||
KeyService = keyService;
|
||||
}
|
||||
|
||||
public async Task<IActionResult> Details(Guid? id)
|
||||
{
|
||||
using (var repo = new Repository<Game>(Context, HttpContext))
|
||||
{
|
||||
var game = await repo.Find(id.GetValueOrDefault());
|
||||
|
||||
if (game == null)
|
||||
return NotFound();
|
||||
|
||||
return View(game);
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<IActionResult> Edit(Guid? id)
|
||||
{
|
||||
using (var repo = new Repository<Game>(Context, HttpContext))
|
||||
{
|
||||
var game = await repo.Find(id.GetValueOrDefault());
|
||||
|
||||
if (game == null)
|
||||
return NotFound();
|
||||
|
||||
var viewModel = new EditKeysViewModel()
|
||||
{
|
||||
Game = game,
|
||||
Keys = String.Join("\n", game.Keys.OrderByDescending(k => k.ClaimedOn).Select(k => k.Value))
|
||||
};
|
||||
|
||||
return View(viewModel);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
[HttpPost]
|
||||
[ValidateAntiForgeryToken]
|
||||
public async Task<IActionResult> Edit(Guid id, EditKeysViewModel viewModel)
|
||||
{
|
||||
var keys = viewModel.Keys.Split("\n").Select(k => k.Trim()).Where(k => !String.IsNullOrWhiteSpace(k));
|
||||
|
||||
using (var gameRepo = new Repository<Game>(Context, HttpContext))
|
||||
{
|
||||
var game = await gameRepo.Find(id);
|
||||
|
||||
if (game == null)
|
||||
return NotFound();
|
||||
|
||||
using (var keyRepo = new Repository<Key>(Context, HttpContext))
|
||||
{
|
||||
var existingKeys = keyRepo.Get(k => k.Game.Id == id).ToList();
|
||||
|
||||
var keysDeleted = existingKeys.Where(k => !keys.Contains(k.Value));
|
||||
var keysAdded = keys.Where(k => !existingKeys.Any(e => e.Value == k));
|
||||
|
||||
foreach (var key in keysDeleted)
|
||||
keyRepo.Delete(key);
|
||||
|
||||
foreach (var key in keysAdded)
|
||||
await keyRepo.Add(new Key()
|
||||
{
|
||||
Game = game,
|
||||
Value = key,
|
||||
});
|
||||
|
||||
await keyRepo.SaveChanges();
|
||||
}
|
||||
}
|
||||
|
||||
return RedirectToAction("Edit", "Games", new { id = id });
|
||||
}
|
||||
|
||||
public async Task<IActionResult> Release(Guid id)
|
||||
{
|
||||
var existing = await KeyService.Get(id);
|
||||
|
||||
if (existing == null)
|
||||
return NotFound();
|
||||
|
||||
await KeyService.Release(id);
|
||||
|
||||
return RedirectToAction("Details", "Keys", new { id = existing.Game.Id });
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,102 +0,0 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc.Rendering;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using LANCommander.Data;
|
||||
using LANCommander.Data.Models;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using LANCommander.Models;
|
||||
using LANCommander.Services;
|
||||
|
||||
namespace LANCommander.Controllers
|
||||
{
|
||||
[Authorize(Roles = "Administrator")]
|
||||
public class ScriptsController : BaseController
|
||||
{
|
||||
private readonly GameService GameService;
|
||||
private readonly ScriptService ScriptService;
|
||||
|
||||
public ScriptsController(GameService gameService, ScriptService scriptService)
|
||||
{
|
||||
GameService = gameService;
|
||||
ScriptService = scriptService;
|
||||
}
|
||||
|
||||
public async Task<IActionResult> Add(Guid? id)
|
||||
{
|
||||
var game = await GameService.Get(id.GetValueOrDefault());
|
||||
|
||||
if (game == null)
|
||||
return NotFound();
|
||||
|
||||
var script = new Script()
|
||||
{
|
||||
GameId = game.Id,
|
||||
Game = game
|
||||
};
|
||||
|
||||
return View(script);
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
public async Task<IActionResult> Add(Script script)
|
||||
{
|
||||
script.Id = Guid.Empty;
|
||||
|
||||
if (ModelState.IsValid)
|
||||
{
|
||||
script = await ScriptService.Add(script);
|
||||
|
||||
return RedirectToAction("Edit", "Games", new { id = script.GameId });
|
||||
}
|
||||
|
||||
return View(script);
|
||||
}
|
||||
|
||||
public async Task<IActionResult> Edit(Guid? id)
|
||||
{
|
||||
var script = await ScriptService.Get(id.GetValueOrDefault());
|
||||
|
||||
if (script == null)
|
||||
return NotFound();
|
||||
|
||||
return View(script);
|
||||
}
|
||||
|
||||
|
||||
[HttpPost]
|
||||
[ValidateAntiForgeryToken]
|
||||
public async Task<IActionResult> Edit(Guid id, Script script)
|
||||
{
|
||||
if (ModelState.IsValid)
|
||||
{
|
||||
await ScriptService.Update(script);
|
||||
|
||||
Alert("The script has been saved!", "success");
|
||||
|
||||
return RedirectToAction("Edit", "Games", new { id = script.GameId });
|
||||
}
|
||||
|
||||
script.Game = await GameService.Get(script.GameId.GetValueOrDefault());
|
||||
|
||||
return View(script);
|
||||
}
|
||||
|
||||
public async Task<IActionResult> Delete(Guid? id)
|
||||
{
|
||||
var script = await ScriptService.Get(id.GetValueOrDefault());
|
||||
|
||||
if (script == null)
|
||||
return NotFound();
|
||||
|
||||
var gameId = script.GameId;
|
||||
|
||||
await ScriptService.Delete(script);
|
||||
|
||||
return RedirectToAction("Edit", "Games", new { id = gameId });
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,166 +0,0 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc.Rendering;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using LANCommander.Data;
|
||||
using LANCommander.Data.Models;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
|
||||
namespace LANCommander.Controllers
|
||||
{
|
||||
[Authorize(Roles = "Administrator")]
|
||||
public class TagsController : Controller
|
||||
{
|
||||
private readonly DatabaseContext _context;
|
||||
|
||||
public TagsController(DatabaseContext context)
|
||||
{
|
||||
_context = context;
|
||||
}
|
||||
|
||||
// GET: Tags
|
||||
public async Task<IActionResult> Index()
|
||||
{
|
||||
return _context.Tags != null ?
|
||||
View(await _context.Tags.ToListAsync()) :
|
||||
Problem("Entity set 'DatabaseContext.Tags' is null.");
|
||||
}
|
||||
|
||||
// GET: Tags/Details/5
|
||||
public async Task<IActionResult> Details(Guid? id)
|
||||
{
|
||||
if (id == null || _context.Tags == null)
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
|
||||
var tag = await _context.Tags
|
||||
.FirstOrDefaultAsync(m => m.Id == id);
|
||||
if (tag == null)
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
|
||||
return View(tag);
|
||||
}
|
||||
|
||||
// GET: Tags/Create
|
||||
public IActionResult Create()
|
||||
{
|
||||
return View();
|
||||
}
|
||||
|
||||
// POST: Tags/Create
|
||||
// To protect from overposting attacks, enable the specific properties you want to bind to.
|
||||
// For more details, see http://go.microsoft.com/fwlink/?LinkId=317598.
|
||||
[HttpPost]
|
||||
[ValidateAntiForgeryToken]
|
||||
public async Task<IActionResult> Create([Bind("Name,Id,CreatedOn,CreatedById,UpdatedOn,UpdatedById")] Tag tag)
|
||||
{
|
||||
if (ModelState.IsValid)
|
||||
{
|
||||
tag.Id = Guid.NewGuid();
|
||||
_context.Add(tag);
|
||||
await _context.SaveChangesAsync();
|
||||
return RedirectToAction(nameof(Index));
|
||||
}
|
||||
return View(tag);
|
||||
}
|
||||
|
||||
// GET: Tags/Edit/5
|
||||
public async Task<IActionResult> Edit(Guid? id)
|
||||
{
|
||||
if (id == null || _context.Tags == null)
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
|
||||
var tag = await _context.Tags.FindAsync(id);
|
||||
if (tag == null)
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
return View(tag);
|
||||
}
|
||||
|
||||
// POST: Tags/Edit/5
|
||||
// To protect from overposting attacks, enable the specific properties you want to bind to.
|
||||
// For more details, see http://go.microsoft.com/fwlink/?LinkId=317598.
|
||||
[HttpPost]
|
||||
[ValidateAntiForgeryToken]
|
||||
public async Task<IActionResult> Edit(Guid id, [Bind("Name,Id,CreatedOn,CreatedById,UpdatedOn,UpdatedById")] Tag tag)
|
||||
{
|
||||
if (id != tag.Id)
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
|
||||
if (ModelState.IsValid)
|
||||
{
|
||||
try
|
||||
{
|
||||
_context.Update(tag);
|
||||
await _context.SaveChangesAsync();
|
||||
}
|
||||
catch (DbUpdateConcurrencyException)
|
||||
{
|
||||
if (!TagExists(tag.Id))
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
else
|
||||
{
|
||||
throw;
|
||||
}
|
||||
}
|
||||
return RedirectToAction(nameof(Index));
|
||||
}
|
||||
return View(tag);
|
||||
}
|
||||
|
||||
// GET: Tags/Delete/5
|
||||
public async Task<IActionResult> Delete(Guid? id)
|
||||
{
|
||||
if (id == null || _context.Tags == null)
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
|
||||
var tag = await _context.Tags
|
||||
.FirstOrDefaultAsync(m => m.Id == id);
|
||||
if (tag == null)
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
|
||||
return View(tag);
|
||||
}
|
||||
|
||||
// POST: Tags/Delete/5
|
||||
[HttpPost, ActionName("Delete")]
|
||||
[ValidateAntiForgeryToken]
|
||||
public async Task<IActionResult> DeleteConfirmed(Guid id)
|
||||
{
|
||||
if (_context.Tags == null)
|
||||
{
|
||||
return Problem("Entity set 'DatabaseContext.Tags' is null.");
|
||||
}
|
||||
var tag = await _context.Tags.FindAsync(id);
|
||||
if (tag != null)
|
||||
{
|
||||
_context.Tags.Remove(tag);
|
||||
}
|
||||
|
||||
await _context.SaveChangesAsync();
|
||||
return RedirectToAction(nameof(Index));
|
||||
}
|
||||
|
||||
private bool TagExists(Guid id)
|
||||
{
|
||||
return (_context.Tags?.Any(e => e.Id == id)).GetValueOrDefault();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,56 +0,0 @@
|
|||
using LANCommander.Models;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace LANCommander.Controllers
|
||||
{
|
||||
[Authorize(Roles = "Administrator")]
|
||||
public class UploadController : Controller
|
||||
{
|
||||
private const string UploadDirectory = "Upload";
|
||||
|
||||
public JsonResult Init()
|
||||
{
|
||||
var key = Guid.NewGuid().ToString();
|
||||
|
||||
if (!Directory.Exists(UploadDirectory))
|
||||
Directory.CreateDirectory(UploadDirectory);
|
||||
|
||||
if (!System.IO.File.Exists(Path.Combine(UploadDirectory, key)))
|
||||
System.IO.File.Create(Path.Combine(UploadDirectory, key)).Close();
|
||||
|
||||
return Json(new
|
||||
{
|
||||
Key = key
|
||||
});
|
||||
}
|
||||
|
||||
public async Task<IActionResult> Chunk([FromForm] ChunkUpload chunk)
|
||||
{
|
||||
var filePath = Path.Combine(UploadDirectory, chunk.Key.ToString());
|
||||
|
||||
if (!System.IO.File.Exists(filePath))
|
||||
return BadRequest("Destination file not initialized.");
|
||||
|
||||
Request.EnableBuffering();
|
||||
|
||||
using (var ms = new MemoryStream())
|
||||
{
|
||||
await chunk.File.CopyToAsync(ms);
|
||||
|
||||
var data = ms.ToArray();
|
||||
|
||||
using (var fs = new FileStream(filePath, FileMode.Append, FileAccess.Write, FileShare.None))
|
||||
{
|
||||
fs.Position = chunk.Start;
|
||||
fs.Write(data, 0, data.Length);
|
||||
}
|
||||
}
|
||||
|
||||
Thread.Sleep(100);
|
||||
|
||||
return Json("Done!");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -59,12 +59,6 @@
|
|||
<ProjectReference Include="..\LANCommander.SDK\LANCommander.SDK.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<TypeScriptCompile Update="wwwroot\js\Upload.ts">
|
||||
<CopyToOutputDirectory>Never</CopyToOutputDirectory>
|
||||
</TypeScriptCompile>
|
||||
</ItemGroup>
|
||||
|
||||
<ProjectExtensions><VisualStudio><UserProperties /></VisualStudio></ProjectExtensions>
|
||||
|
||||
</Project>
|
||||
|
|
|
@ -1,11 +0,0 @@
|
|||
namespace LANCommander.Models
|
||||
{
|
||||
public class ChunkUpload
|
||||
{
|
||||
public long Start { get; set; }
|
||||
public long End { get; set; }
|
||||
public long Total { get; set; }
|
||||
public Guid Key { get; set; }
|
||||
public IFormFile File { get; set; }
|
||||
}
|
||||
}
|
|
@ -1,10 +0,0 @@
|
|||
using LANCommander.Data.Models;
|
||||
|
||||
namespace LANCommander.Models
|
||||
{
|
||||
public class EditKeysViewModel
|
||||
{
|
||||
public Game Game { get; set; }
|
||||
public string Keys { get; set; }
|
||||
}
|
||||
}
|
|
@ -1,10 +0,0 @@
|
|||
using LANCommander.Data.Models;
|
||||
|
||||
namespace LANCommander.Models
|
||||
{
|
||||
public class GameLookupResultsViewModel
|
||||
{
|
||||
public string Search { get; set; }
|
||||
public IEnumerable<Game> Results { get; set; }
|
||||
}
|
||||
}
|
|
@ -1,21 +0,0 @@
|
|||
using LANCommander.Data.Models;
|
||||
using Microsoft.AspNetCore.Mvc.Rendering;
|
||||
|
||||
namespace LANCommander.Models
|
||||
{
|
||||
public class GameViewModel
|
||||
{
|
||||
public long? IgdbId { get; set; }
|
||||
public Game Game { get; set; }
|
||||
public List<SelectListItem>? Genres { get; set; }
|
||||
public List<SelectListItem>? Tags { get; set; }
|
||||
public List<SelectListItem>? Categories { get; set; }
|
||||
public List<SelectListItem>? Developers { get; set; }
|
||||
public List<SelectListItem>? Publishers { get; set; }
|
||||
public string[]? SelectedGenres { get; set; }
|
||||
public string[]? SelectedTags { get; set; }
|
||||
public string[]? SelectedCategories { get; set; }
|
||||
public string[]? SelectedDevelopers { get; set; }
|
||||
public string[]? SelectedPublishers { get; set; }
|
||||
}
|
||||
}
|
|
@ -1,23 +0,0 @@
|
|||
@page "/Games/{id:guid}/Browse"
|
||||
@inject GameService GameService
|
||||
|
||||
<Card Title="Archive Browser" SubTitle="@Game.Title">
|
||||
<Table>
|
||||
<ArchiveBrowser ArchiveId="@Archive.Id" />
|
||||
</Table>
|
||||
</Card>
|
||||
|
||||
@code {
|
||||
[Parameter] public Guid Id { get; set; }
|
||||
|
||||
private Game Game { get; set; }
|
||||
private Archive Archive { get; set; }
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
Game = await GameService.Get(Id);
|
||||
|
||||
if (Game.Archives != null && Game.Archives.Count > 0)
|
||||
Archive = Game.Archives.OrderByDescending(a => a.CreatedOn).First();
|
||||
}
|
||||
}
|
|
@ -1,127 +0,0 @@
|
|||
@model LANCommander.Data.Models.Archive
|
||||
|
||||
@{
|
||||
ViewData["Title"] = "Add Archive";
|
||||
}
|
||||
|
||||
<div class="container-xl">
|
||||
<!-- Page title -->
|
||||
<div class="page-header d-print-none">
|
||||
<div class="row align-items-center">
|
||||
<div class="col">
|
||||
<div class="page-pretitle">@Model.Game.Title</div>
|
||||
<h2 class="page-title">
|
||||
Add Archive
|
||||
</h2>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="page-body">
|
||||
<div class="container-xl">
|
||||
<div class="row row-cards">
|
||||
<div class="col-12">
|
||||
<form asp-action="Add" enctype="multipart/form-data" class="card">
|
||||
<fieldset>
|
||||
<div class="card-body">
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label asp-for="Version" class="control-label"></label>
|
||||
<input asp-for="Version" class="form-control" />
|
||||
<span asp-validation-for="Version" class="text-danger"></span>
|
||||
@if (Model.LastVersion != null && !String.IsNullOrWhiteSpace(Model.LastVersion.Version))
|
||||
{
|
||||
<small class="form-hint">Last version: @Model.LastVersion.Version</small>
|
||||
}
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label asp-for="Changelog" class="control-label"></label>
|
||||
<textarea asp-for="Changelog" class="form-control"></textarea>
|
||||
<span asp-validation-for="Changelog" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="File" class="control-label">File</label>
|
||||
<input type="file" id="File" class="form-control" />
|
||||
</div>
|
||||
<div>
|
||||
<div class="progress h-4">
|
||||
<div class="progress-bar" role="progressbar" style="width: 0%"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<input type="hidden" asp-for="GameId" />
|
||||
<input type="hidden" asp-for="LastVersion.Id" />
|
||||
<input type="hidden" asp-for="ObjectKey" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card-footer">
|
||||
<div class="d-flex">
|
||||
<a asp-action="Edit" asp-controller="Games" asp-route-id="@Model.Game.Id" class="btn btn-ghost-primary">Cancel</a>
|
||||
<button class="btn btn-primary ms-auto" id="UploadButton">Upload</button>
|
||||
</div>
|
||||
</div>
|
||||
</fieldset>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@section Scripts {
|
||||
@{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
|
||||
|
||||
<script src="~/js/Upload.js"></script>
|
||||
<script>
|
||||
var uploader = new Uploader();
|
||||
|
||||
uploader.Init('File', 'UploadButton');
|
||||
|
||||
uploader.OnStart = () => {
|
||||
$('fieldset').prop('disabled', true);
|
||||
$('.progress-bar')
|
||||
.css('width', '0%')
|
||||
.removeClass('bg-success')
|
||||
.removeClass('bg-danger')
|
||||
.addClass('progress-bar-striped')
|
||||
.addClass('progress-bar-animated')
|
||||
.text('0%');
|
||||
};
|
||||
|
||||
uploader.OnComplete = (id, key) => {
|
||||
$('#Id').val(id);
|
||||
$('#ObjectKey').val(key);
|
||||
$('.progress-bar')
|
||||
.css('width', '100%')
|
||||
.removeClass('progress-bar-striped')
|
||||
.removeClass('progress-bar-animated')
|
||||
.addClass('bg-success')
|
||||
.text('Upload Complete!');
|
||||
|
||||
setTimeout(() => {
|
||||
window.location.href = '@Url.Action("Edit", "Games", new { id = Model.Game.Id })';
|
||||
}, 2000);
|
||||
};
|
||||
|
||||
uploader.OnProgress = (percent) => {
|
||||
$('.progress-bar')
|
||||
.css('width', `${percent * 100}%`)
|
||||
.text(`${Math.round(percent * 100)}%`);
|
||||
};
|
||||
|
||||
uploader.OnError = () => {
|
||||
$('fieldset').prop('disabled', false);
|
||||
$('.progress-bar')
|
||||
.css('width', '100%')
|
||||
.removeClass('progress-bar-striped')
|
||||
.removeClass('progress-bar-animated')
|
||||
.addClass('bg-danger')
|
||||
.text('Upload Error!');
|
||||
};
|
||||
</script>
|
||||
}
|
|
@ -1,32 +0,0 @@
|
|||
@using LANCommander.Components;
|
||||
@model LANCommander.Data.Models.Archive
|
||||
|
||||
@{
|
||||
ViewData["Title"] = "Browse Archive";
|
||||
}
|
||||
|
||||
<div class="container-xl">
|
||||
<!-- Page title -->
|
||||
<div class="page-header d-print-none">
|
||||
<div class="row align-items-center">
|
||||
<div class="col">
|
||||
<div class="page-pretitle">@Model.Game.Title</div>
|
||||
<h2 class="page-title">
|
||||
Browse Archive
|
||||
</h2>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="page-body">
|
||||
<div class="container-xl">
|
||||
<div class="row row-cards">
|
||||
<div class="col-12">
|
||||
<div class="card">
|
||||
<component type="typeof(ArchiveBrowser)" render-mode="Server" param-ArchiveId="Model.Id" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
|
@ -1,43 +0,0 @@
|
|||
@model LANCommander.Data.Models.Company
|
||||
|
||||
@{
|
||||
ViewData["Title"] = "Create";
|
||||
}
|
||||
|
||||
<h1>Create</h1>
|
||||
|
||||
<h4>Company</h4>
|
||||
<hr />
|
||||
<div class="row">
|
||||
<div class="col-md-4">
|
||||
<form asp-action="Create">
|
||||
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
|
||||
<div class="form-group">
|
||||
<label asp-for="Name" class="control-label"></label>
|
||||
<input asp-for="Name" class="form-control" />
|
||||
<span asp-validation-for="Name" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label asp-for="CreatedOn" class="control-label"></label>
|
||||
<input asp-for="CreatedOn" class="form-control" />
|
||||
<span asp-validation-for="CreatedOn" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label asp-for="UpdatedOn" class="control-label"></label>
|
||||
<input asp-for="UpdatedOn" class="form-control" />
|
||||
<span asp-validation-for="UpdatedOn" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<input type="submit" value="Create" class="btn btn-primary" />
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<a asp-action="Index">Back to List</a>
|
||||
</div>
|
||||
|
||||
@section Scripts {
|
||||
@{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
|
||||
}
|
|
@ -1,39 +0,0 @@
|
|||
@model LANCommander.Data.Models.Company
|
||||
|
||||
@{
|
||||
ViewData["Title"] = "Delete";
|
||||
}
|
||||
|
||||
<h1>Delete</h1>
|
||||
|
||||
<h3>Are you sure you want to delete this?</h3>
|
||||
<div>
|
||||
<h4>Company</h4>
|
||||
<hr />
|
||||
<dl class="row">
|
||||
<dt class = "col-sm-2">
|
||||
@Html.DisplayNameFor(model => model.Name)
|
||||
</dt>
|
||||
<dd class = "col-sm-10">
|
||||
@Html.DisplayFor(model => model.Name)
|
||||
</dd>
|
||||
<dt class = "col-sm-2">
|
||||
@Html.DisplayNameFor(model => model.CreatedOn)
|
||||
</dt>
|
||||
<dd class = "col-sm-10">
|
||||
@Html.DisplayFor(model => model.CreatedOn)
|
||||
</dd>
|
||||
<dt class = "col-sm-2">
|
||||
@Html.DisplayNameFor(model => model.UpdatedOn)
|
||||
</dt>
|
||||
<dd class = "col-sm-10">
|
||||
@Html.DisplayFor(model => model.UpdatedOn)
|
||||
</dd>
|
||||
</dl>
|
||||
|
||||
<form asp-action="Delete">
|
||||
<input type="hidden" asp-for="Id" />
|
||||
<input type="submit" value="Delete" class="btn btn-danger" /> |
|
||||
<a asp-action="Index">Back to List</a>
|
||||
</form>
|
||||
</div>
|
|
@ -1,36 +0,0 @@
|
|||
@model LANCommander.Data.Models.Company
|
||||
|
||||
@{
|
||||
ViewData["Title"] = "Details";
|
||||
}
|
||||
|
||||
<h1>Details</h1>
|
||||
|
||||
<div>
|
||||
<h4>Company</h4>
|
||||
<hr />
|
||||
<dl class="row">
|
||||
<dt class = "col-sm-2">
|
||||
@Html.DisplayNameFor(model => model.Name)
|
||||
</dt>
|
||||
<dd class = "col-sm-10">
|
||||
@Html.DisplayFor(model => model.Name)
|
||||
</dd>
|
||||
<dt class = "col-sm-2">
|
||||
@Html.DisplayNameFor(model => model.CreatedOn)
|
||||
</dt>
|
||||
<dd class = "col-sm-10">
|
||||
@Html.DisplayFor(model => model.CreatedOn)
|
||||
</dd>
|
||||
<dt class = "col-sm-2">
|
||||
@Html.DisplayNameFor(model => model.UpdatedOn)
|
||||
</dt>
|
||||
<dd class = "col-sm-10">
|
||||
@Html.DisplayFor(model => model.UpdatedOn)
|
||||
</dd>
|
||||
</dl>
|
||||
</div>
|
||||
<div>
|
||||
<a asp-action="Edit" asp-route-id="@Model?.Id">Edit</a> |
|
||||
<a asp-action="Index">Back to List</a>
|
||||
</div>
|
|
@ -1,44 +0,0 @@
|
|||
@model LANCommander.Data.Models.Company
|
||||
|
||||
@{
|
||||
ViewData["Title"] = "Edit";
|
||||
}
|
||||
|
||||
<h1>Edit</h1>
|
||||
|
||||
<h4>Company</h4>
|
||||
<hr />
|
||||
<div class="row">
|
||||
<div class="col-md-4">
|
||||
<form asp-action="Edit">
|
||||
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
|
||||
<div class="form-group">
|
||||
<label asp-for="Name" class="control-label"></label>
|
||||
<input asp-for="Name" class="form-control" />
|
||||
<span asp-validation-for="Name" class="text-danger"></span>
|
||||
</div>
|
||||
<input type="hidden" asp-for="Id" />
|
||||
<div class="form-group">
|
||||
<label asp-for="CreatedOn" class="control-label"></label>
|
||||
<input asp-for="CreatedOn" class="form-control" />
|
||||
<span asp-validation-for="CreatedOn" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label asp-for="UpdatedOn" class="control-label"></label>
|
||||
<input asp-for="UpdatedOn" class="form-control" />
|
||||
<span asp-validation-for="UpdatedOn" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<input type="submit" value="Save" class="btn btn-primary" />
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<a asp-action="Index">Back to List</a>
|
||||
</div>
|
||||
|
||||
@section Scripts {
|
||||
@{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
|
||||
}
|
|
@ -1,47 +0,0 @@
|
|||
@model IEnumerable<LANCommander.Data.Models.Company>
|
||||
|
||||
@{
|
||||
ViewData["Title"] = "Index";
|
||||
}
|
||||
|
||||
<h1>Index</h1>
|
||||
|
||||
<p>
|
||||
<a asp-action="Create">Create New</a>
|
||||
</p>
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>
|
||||
@Html.DisplayNameFor(model => model.Name)
|
||||
</th>
|
||||
<th>
|
||||
@Html.DisplayNameFor(model => model.CreatedOn)
|
||||
</th>
|
||||
<th>
|
||||
@Html.DisplayNameFor(model => model.UpdatedOn)
|
||||
</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach (var item in Model) {
|
||||
<tr>
|
||||
<td>
|
||||
@Html.DisplayFor(modelItem => item.Name)
|
||||
</td>
|
||||
<td>
|
||||
@Html.DisplayFor(modelItem => item.CreatedOn)
|
||||
</td>
|
||||
<td>
|
||||
@Html.DisplayFor(modelItem => item.UpdatedOn)
|
||||
</td>
|
||||
<td>
|
||||
<a asp-action="Edit" asp-route-id="@item.Id">Edit</a> |
|
||||
<a asp-action="Details" asp-route-id="@item.Id">Details</a> |
|
||||
<a asp-action="Delete" asp-route-id="@item.Id">Delete</a>
|
||||
</td>
|
||||
</tr>
|
||||
}
|
||||
</tbody>
|
||||
</table>
|
|
@ -1,125 +0,0 @@
|
|||
@using LANCommander.Components
|
||||
@model LANCommander.Models.GameViewModel
|
||||
|
||||
@{
|
||||
ViewData["Title"] = "Add Game";
|
||||
}
|
||||
|
||||
<div class="container-xl">
|
||||
<!-- Page title -->
|
||||
<div class="page-header d-print-none">
|
||||
<div class="row align-items-center">
|
||||
<div class="col">
|
||||
<h2 class="page-title">
|
||||
Add Game
|
||||
</h2>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="page-body">
|
||||
<div class="container-xl">
|
||||
<div class="row row-cards">
|
||||
<div class="col-12">
|
||||
<form asp-action="Add" class="card">
|
||||
<div class="card-body">
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label asp-for="Game.Title" class="control-label"></label>
|
||||
<div class="input-group">
|
||||
<input asp-for="Game.Title" class="form-control" />
|
||||
<button class="btn" type="submit" asp-action="Lookup">Lookup</button>
|
||||
</div>
|
||||
<span asp-validation-for="Game.Title" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label asp-for="Game.SortTitle" class="control-label"></label>
|
||||
<input asp-for="Game.SortTitle" class="form-control" />
|
||||
<span asp-validation-for="Game.SortTitle" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label asp-for="Game.Icon" class="control-label"></label>
|
||||
<input asp-for="Game.Icon" class="form-control" />
|
||||
<span asp-validation-for="Game.Icon" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label asp-for="Game.Description" class="control-label"></label>
|
||||
<textarea asp-for="Game.Description" class="form-control" data-bs-toggle="autosize"></textarea>
|
||||
<span asp-validation-for="Game.Description" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label asp-for="Game.ReleasedOn" class="control-label"></label>
|
||||
<input asp-for="Game.ReleasedOn" class="form-control" />
|
||||
<span asp-validation-for="Game.ReleasedOn" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label class="form-check">
|
||||
<input asp-for="Game.Singleplayer" type="checkbox" class="form-check-input" />
|
||||
<span class="form-check-label">Singleplayer</span>
|
||||
<span class="form-check-description">Game has a singleplayer mode</span>
|
||||
</label>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label asp-for="Developers" class="control-label"></label>
|
||||
<input type="text" class="developer-select" />
|
||||
<select asp-for="SelectedDevelopers" class="d-none"></select>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label asp-for="Publishers" class="control-label"></label>
|
||||
<input type="text" class="publisher-select" />
|
||||
<select asp-for="SelectedPublishers" class="d-none"></select>
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label asp-for="Genres" class="control-label"></label>
|
||||
<input type="text" class="genre-select" />
|
||||
<select asp-for="SelectedGenres" class="d-none"></select>
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label asp-for="Tags" class="control-label"></label>
|
||||
<input type="text" class="tag-select" />
|
||||
<select asp-for="SelectedTags" class="d-none"></select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card-header">
|
||||
<h3 class="card-title">Actions</h3>
|
||||
</div>
|
||||
|
||||
<component type="typeof(ActionEditor)" render-mode="Server" param-Actions="Model.Game.Actions.ToList()" param-GameId="Model.Game.Id" />
|
||||
|
||||
<div class="card-header">
|
||||
<h3 class="card-title">Multiplayer Modes</h3>
|
||||
</div>
|
||||
|
||||
<component type="typeof(MultiplayerModeEditor)" render-mode="Server" param-MultiplayerModes="Model.Game.MultiplayerModes" param-GameId="Model.Game.Id" />
|
||||
|
||||
<div class="card-footer">
|
||||
<div class="d-flex">
|
||||
<a asp-action="Index" class="btn btn-ghost-primary">Cancel</a>
|
||||
<button type="submit" class="btn btn-primary ms-auto">Save</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@section Scripts {
|
||||
@{ await Html.RenderPartialAsync("_ValidationScriptsPartial"); }
|
||||
|
||||
<script>
|
||||
new Select('.developer-select', @Html.Raw(Json.Serialize(Model.Developers)));
|
||||
new Select('.publisher-select', @Html.Raw(Json.Serialize(Model.Publishers)));
|
||||
new Select('.genre-select', @Html.Raw(Json.Serialize(Model.Genres)));
|
||||
new Select('.tag-select', @Html.Raw(Json.Serialize(Model.Tags)));
|
||||
</script>
|
||||
}
|
|
@ -1,65 +0,0 @@
|
|||
@model LANCommander.Data.Models.Game
|
||||
|
||||
@{
|
||||
ViewData["Title"] = "Delete";
|
||||
}
|
||||
|
||||
<div class="container container-tight py-4">
|
||||
<div class="page-header">
|
||||
<div class="row align-items-center">
|
||||
<div class="col">
|
||||
<h2 class="page-title">Delete @Model.Title?</h2>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
<p class="text-muted">Are you sure you want to delete this game?
|
||||
@if (Model.Archives != null && Model.Archives.Count > 0)
|
||||
{
|
||||
<span>It will also delete the following archives:</span>
|
||||
}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
@if (Model.Archives != null && Model.Archives.Count > 0)
|
||||
{
|
||||
<div class="table-responsive">
|
||||
<table class="table table-vcenter table-mobile-md card-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Version</th>
|
||||
<th>Uploaded By</th>
|
||||
<th>Uploaded On</th>
|
||||
<th>Size</th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
<tbody>
|
||||
@foreach (var archive in Model.Archives.OrderByDescending(a => a.CreatedOn))
|
||||
{
|
||||
<tr>
|
||||
<td>@Html.DisplayFor(m => archive.Version)</td>
|
||||
<td>@Html.DisplayFor(m => archive.CreatedBy.UserName)</td>
|
||||
<td>@Html.DisplayFor(m => archive.CreatedOn)</td>
|
||||
<td>@ByteSizeLib.ByteSize.FromBytes(archive.CompressedSize)</td>
|
||||
</tr>
|
||||
}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
}
|
||||
|
||||
<div class="card-footer">
|
||||
<div class="d-flex justify-content-between">
|
||||
<a asp-action="Index" class="btn btn-ghost-primary">Cancel</a>
|
||||
|
||||
<form asp-action="Delete">
|
||||
<input type="hidden" asp-for="Id" />
|
||||
<button type="submit" class="btn btn-danger ms-auto">Delete</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
|
@ -1,303 +0,0 @@
|
|||
@using LANCommander.Components
|
||||
@using LANCommander.Data.Models
|
||||
@model LANCommander.Models.GameViewModel
|
||||
|
||||
@{
|
||||
ViewData["Title"] = "Edit";
|
||||
}
|
||||
|
||||
<div class="container-xl">
|
||||
<!-- Page title -->
|
||||
<div class="page-header d-print-none">
|
||||
<div class="row align-items-center">
|
||||
<div class="col">
|
||||
<h2 class="page-title">
|
||||
Edit Game
|
||||
</h2>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="page-body">
|
||||
<div class="container-xl">
|
||||
<div class="row row-cards">
|
||||
<div class="col-12">
|
||||
<form asp-action="Edit" class="card">
|
||||
<div class="card-body">
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label asp-for="Game.Title" class="control-label"></label>
|
||||
<div class="input-group">
|
||||
<input asp-for="Game.Title" class="form-control" />
|
||||
<button class="btn" type="submit" asp-action="Lookup">Lookup</button>
|
||||
</div>
|
||||
<span asp-validation-for="Game.Title" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label asp-for="Game.SortTitle" class="control-label"></label>
|
||||
<input asp-for="Game.SortTitle" class="form-control" />
|
||||
<span asp-validation-for="Game.SortTitle" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label asp-for="Game.Icon" class="control-label"></label>
|
||||
<input asp-for="Game.Icon" class="form-control" />
|
||||
<span asp-validation-for="Game.Icon" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label asp-for="Game.Description" class="control-label"></label>
|
||||
<textarea asp-for="Game.Description" class="form-control" data-bs-toggle="autosize"></textarea>
|
||||
<span asp-validation-for="Game.Description" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label asp-for="Game.ReleasedOn" class="control-label"></label>
|
||||
<input asp-for="Game.ReleasedOn" class="form-control" />
|
||||
<span asp-validation-for="Game.ReleasedOn" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label class="form-check">
|
||||
<input asp-for="Game.Singleplayer" type="checkbox" class="form-check-input" />
|
||||
<span class="form-check-label">Singleplayer</span>
|
||||
<span class="form-check-description">Game has a singleplayer mode</span>
|
||||
</label>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label asp-for="Developers" class="control-label"></label>
|
||||
<input type="text" class="developer-select" />
|
||||
<select asp-for="SelectedDevelopers" class="d-none"></select>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label asp-for="Publishers" class="control-label"></label>
|
||||
<input type="text" class="publisher-select" />
|
||||
<select asp-for="SelectedPublishers" class="d-none"></select>
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label asp-for="Genres" class="control-label"></label>
|
||||
<input type="text" class="genre-select" />
|
||||
<select asp-for="SelectedGenres" class="d-none"></select>
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label asp-for="Tags" class="control-label"></label>
|
||||
<input type="text" class="tag-select" />
|
||||
<select asp-for="SelectedTags" class="d-none"></select>
|
||||
</div>
|
||||
|
||||
<input type="hidden" asp-for="Game.Id" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card-header">
|
||||
<h3 class="card-title">Actions</h3>
|
||||
</div>
|
||||
|
||||
<component type="typeof(ActionEditor)" render-mode="Server" param-Actions="Model.Game.Actions.ToList()" param-GameId="Model.Game.Id" />
|
||||
|
||||
<div class="card-header">
|
||||
<h3 class="card-title">Multiplayer Modes</h3>
|
||||
</div>
|
||||
|
||||
<component type="typeof(MultiplayerModeEditor)" render-mode="Server" param-MultiplayerModes="Model.Game.MultiplayerModes" param-GameId="Model.Game.Id" />
|
||||
|
||||
<div class="card-footer">
|
||||
<div class="d-flex">
|
||||
<a asp-action="Index" class="btn btn-ghost-primary">Cancel</a>
|
||||
<button type="submit" class="btn btn-primary ms-auto">Save</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div class="col-12">
|
||||
<div class="card">
|
||||
@if (Model.Game.Keys != null && Model.Game.Keys.Count > 0)
|
||||
{
|
||||
<div class="card-header">
|
||||
<h3 class="card-title">Keys</h3>
|
||||
<div class="card-actions">
|
||||
<a asp-action="Details" asp-controller="Keys" asp-route-id="@Model.Game.Id" class="btn btn-ghost-primary">
|
||||
Details
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
var keysAvailable = Model.Game.Keys.Count(k =>
|
||||
{
|
||||
return (k.AllocationMethod == KeyAllocationMethod.MacAddress && String.IsNullOrWhiteSpace(k.ClaimedByMacAddress)) ||
|
||||
(k.AllocationMethod == KeyAllocationMethod.UserAccount && k.ClaimedByUser == null);
|
||||
});
|
||||
|
||||
<div class="card-body">
|
||||
<div class="datagrid text-center">
|
||||
<div class="datagrid-item">
|
||||
<div class="datagrid-title">Available</div>
|
||||
<div class="datagrid-content">
|
||||
@keysAvailable
|
||||
</div>
|
||||
</div>
|
||||
<div class="datagrid-item">
|
||||
<div class="datagrid-title">Claimed</div>
|
||||
<div class="datagrid-content">
|
||||
@(Model.Game.Keys.Count - keysAvailable)
|
||||
</div>
|
||||
</div>
|
||||
<div class="datagrid-item">
|
||||
<div class="datagrid-title">Total</div>
|
||||
<div class="datagrid-content">
|
||||
@Model.Game.Keys.Count
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
else
|
||||
{
|
||||
<div class="empty">
|
||||
<p class="empty-title">No Keys</p>
|
||||
<p class="empty-subtitle text-muted">There have been no keys added for this game.</p>
|
||||
<div class="empty-action">
|
||||
<a asp-action="Edit" asp-controller="Keys" asp-route-id="@Model.Game.Id" class="btn btn-primary">Edit Keys</a>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-12">
|
||||
<div class="card">
|
||||
@if (Model.Game.Archives != null && Model.Game.Archives.Count > 0)
|
||||
{
|
||||
<div class="card-header">
|
||||
<h3 class="card-title">Archives</h3>
|
||||
<div class="card-actions">
|
||||
<a asp-action="Add" asp-controller="Archives" asp-route-id="@Model.Game.Id" class="btn btn-primary">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="icon" width="24" height="24" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z" fill="none"></path><line x1="12" y1="5" x2="12" y2="19"></line><line x1="5" y1="12" x2="19" y2="12"></line></svg>
|
||||
Add
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="table-responsive">
|
||||
<table class="table table-vcenter table-mobile-md card-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Version</th>
|
||||
<th>Uploaded By</th>
|
||||
<th>Uploaded On</th>
|
||||
<th>Size</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
<tbody>
|
||||
@foreach (var archive in Model.Game.Archives.OrderByDescending(a => a.CreatedOn))
|
||||
{
|
||||
<tr>
|
||||
<td>@Html.DisplayFor(m => archive.Version)</td>
|
||||
<td>@Html.DisplayFor(m => archive.CreatedBy.UserName)</td>
|
||||
<td>@Html.DisplayFor(m => archive.CreatedOn)</td>
|
||||
<td>@ByteSizeLib.ByteSize.FromBytes(new FileInfo(System.IO.Path.Combine("Upload", archive.ObjectKey)).Length)</td>
|
||||
<td>
|
||||
<div class="btn-list flex-nowrap justify-content-end">
|
||||
<a asp-action="Download" asp-controller="Archives" asp-route-id="@archive.Id" class="btn">Download</a>
|
||||
<a asp-action="Browse" asp-controller="Archives" asp-route-id="@archive.Id" class="btn">Browse</a>
|
||||
<a asp-action="Delete" asp-controller="Archives" asp-route-id="@archive.Id" class="btn btn-danger">Delete</a>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
}
|
||||
else
|
||||
{
|
||||
<div class="empty">
|
||||
<p class="empty-title">No Archives</p>
|
||||
<p class="empty-subtitle text-muted">There have been no archives uploaded for this game.</p>
|
||||
<div class="empty-action">
|
||||
<a asp-action="Add" asp-controller="Archives" asp-route-id="@Model.Game.Id" class="btn btn-primary">Upload Archive</a>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-12">
|
||||
<div class="card">
|
||||
@if (Model.Game.Scripts != null && Model.Game.Scripts.Count > 0)
|
||||
{
|
||||
<div class="card-header">
|
||||
<h3 class="card-title">Scripts</h3>
|
||||
<div class="card-actions">
|
||||
<a asp-action="Add" asp-controller="Scripts" asp-route-id="@Model.Game.Id" class="btn btn-primary">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="icon" width="24" height="24" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z" fill="none"></path><line x1="12" y1="5" x2="12" y2="19"></line><line x1="5" y1="12" x2="19" y2="12"></line></svg>
|
||||
Add
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="table-responsive">
|
||||
<table class="table table-vcenter table-mobile-md card-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Type</th>
|
||||
<th>Name</th>
|
||||
<th>Created On</th>
|
||||
<th>Created By</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
<tbody>
|
||||
@foreach (var script in Model.Game.Scripts.OrderBy(s => s.Type).ThenByDescending(s => s.CreatedOn))
|
||||
{
|
||||
<tr>
|
||||
<td>@Html.DisplayFor(m => script.Type)</td>
|
||||
<td>@Html.DisplayFor(m => script.Name)</td>
|
||||
<td>@Html.DisplayFor(m => script.CreatedOn)</td>
|
||||
<td>@Html.DisplayFor(m => script.CreatedBy.UserName)</td>
|
||||
<td>
|
||||
<div class="btn-list flex-nowrap justify-content-end">
|
||||
<a asp-action="Edit" asp-controller="Scripts" asp-route-id="@script.Id" class="btn">Edit</a>
|
||||
<a asp-action="Delete" asp-controller="Scripts" asp-route-id="@script.Id" class="btn btn-danger">Delete</a>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
}
|
||||
else
|
||||
{
|
||||
<div class="empty">
|
||||
<p class="empty-title">No Scripts</p>
|
||||
<p class="empty-subtitle text-muted">There have been no scripts added for this game.</p>
|
||||
<div class="empty-action">
|
||||
<a asp-action="Add" asp-controller="Scripts" asp-route-id="@Model.Game.Id" class="btn btn-primary">Add Script</a>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@section Scripts {
|
||||
@{ await Html.RenderPartialAsync("_ValidationScriptsPartial"); }
|
||||
|
||||
<script>
|
||||
new Select('.developer-select', @Html.Raw(Json.Serialize(Model.Developers)));
|
||||
new Select('.publisher-select', @Html.Raw(Json.Serialize(Model.Publishers)));
|
||||
new Select('.genre-select', @Html.Raw(Json.Serialize(Model.Genres)));
|
||||
new Select('.tag-select', @Html.Raw(Json.Serialize(Model.Tags)));
|
||||
</script>
|
||||
}
|
|
@ -1,110 +0,0 @@
|
|||
@model IEnumerable<LANCommander.Data.Models.Game>
|
||||
|
||||
@{
|
||||
ViewData["Title"] = "Games";
|
||||
}
|
||||
<div class="container-xl">
|
||||
<div class="page-header d-print-none">
|
||||
<div class="row align-items-center">
|
||||
<div class="col">
|
||||
<h2 class="page-title">
|
||||
Games
|
||||
</h2>
|
||||
</div>
|
||||
|
||||
<div class="col-auto ms-auto">
|
||||
<div class="btn-list">
|
||||
<a asp-action="Add" class="btn btn-primary d-none d-sm-inline-block">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="icon" width="24" height="24" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z" fill="none"></path><line x1="12" y1="5" x2="12" y2="19"></line><line x1="5" y1="12" x2="19" y2="12"></line></svg>
|
||||
Add
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="page-body">
|
||||
<div class="container-xl">
|
||||
<div class="row row-cards">
|
||||
<div class="col-12">
|
||||
<div class="card">
|
||||
<div class="table-responsive">
|
||||
<table class="table table-vcenter table-mobile-md card-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th></th>
|
||||
<th>
|
||||
@Html.DisplayNameFor(model => model.Title)
|
||||
</th>
|
||||
<th>
|
||||
@Html.DisplayNameFor(model => model.SortTitle)
|
||||
</th>
|
||||
<th>
|
||||
@Html.DisplayNameFor(model => model.ReleasedOn)
|
||||
</th>
|
||||
<th>
|
||||
@Html.DisplayNameFor(model => model.CreatedOn)
|
||||
</th>
|
||||
<th>
|
||||
@Html.DisplayNameFor(model => model.CreatedBy)
|
||||
</th>
|
||||
<th>
|
||||
@Html.DisplayNameFor(model => model.UpdatedOn)
|
||||
</th>
|
||||
<th>
|
||||
@Html.DisplayNameFor(model => model.UpdatedBy)
|
||||
</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
<tbody>
|
||||
@foreach (var item in Model.OrderBy(g => !String.IsNullOrWhiteSpace(g.SortTitle) ? g.SortTitle : g.Title))
|
||||
{
|
||||
<tr>
|
||||
<td>
|
||||
@if (!String.IsNullOrWhiteSpace(item.Icon)) {
|
||||
<img src="@Url.Action("GetIcon", "Games", new { id = item.Id })" />
|
||||
}
|
||||
</td>
|
||||
<td>
|
||||
@Html.DisplayFor(modelItem => item.Title)
|
||||
</td>
|
||||
<td>
|
||||
@Html.DisplayFor(modelItem => item.SortTitle)
|
||||
</td>
|
||||
<td>
|
||||
@if (item.ReleasedOn.HasValue)
|
||||
{
|
||||
@item.ReleasedOn.Value.ToString("MM/dd/yyyy")
|
||||
}
|
||||
</td>
|
||||
<td>
|
||||
@Html.DisplayFor(modelItem => item.CreatedOn)
|
||||
</td>
|
||||
<td>
|
||||
@Html.DisplayFor(modelItem => item.CreatedBy.UserName)
|
||||
</td>
|
||||
<td>
|
||||
@Html.DisplayFor(modelItem => item.UpdatedOn)
|
||||
</td>
|
||||
<td>
|
||||
@Html.DisplayFor(modelItem => item.UpdatedBy.UserName)
|
||||
</td>
|
||||
<td>
|
||||
<div class="btn-list flex-nowrap justify-content-end">
|
||||
<a asp-action="Edit" asp-route-id="@item.Id" class="btn">Edit</a>
|
||||
<a asp-action="Delete" asp-route-id="@item.Id" class="btn btn-danger">Delete</a>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
|
@ -1,99 +0,0 @@
|
|||
@model LANCommander.Models.GameLookupResultsViewModel
|
||||
|
||||
@{
|
||||
ViewData["Title"] = "Games";
|
||||
}
|
||||
<div class="container-xl">
|
||||
<div class="page-header d-print-none">
|
||||
<div class="row align-items-center">
|
||||
<div class="col">
|
||||
<div class="page-pretitle">@Model.Search</div>
|
||||
<h2 class="page-title">
|
||||
Game Lookup
|
||||
</h2>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="page-body">
|
||||
<div class="container-xl">
|
||||
<div class="row row-cards">
|
||||
<div class="col-12">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title">Results</h3>
|
||||
</div>
|
||||
@if (Model.Results.Count() == 0)
|
||||
{
|
||||
<div class="card-body">
|
||||
<p>No games could be found with the search "@Model.Search".</p>
|
||||
</div>
|
||||
}
|
||||
else
|
||||
{
|
||||
<div class="card-body">
|
||||
@if (Model.Results.Count() > 1)
|
||||
{
|
||||
<p>There was a total of @Model.Results.Count() games that matched the search "@Model.Search" in IGDB's database.</p>
|
||||
}
|
||||
else
|
||||
{
|
||||
<p>Only one game matched the search "@Model.Search" in IGDB's database.</p>
|
||||
}
|
||||
</div>
|
||||
<form>
|
||||
<div class="table-responsive">
|
||||
<table class="table table-vcenter table-mobile-md card-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>
|
||||
Title
|
||||
</th>
|
||||
<th>
|
||||
Release Date
|
||||
</th>
|
||||
<th>
|
||||
Developers
|
||||
</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
<tbody>
|
||||
@foreach (var item in Model.Results)
|
||||
{
|
||||
<tr>
|
||||
<td>
|
||||
@Html.DisplayFor(modelItem => item.Title)
|
||||
</td>
|
||||
<td>
|
||||
@Html.DisplayFor(modelItem => item.ReleasedOn)
|
||||
</td>
|
||||
<td>
|
||||
@String.Join(", ", item.Developers.Select(d => d.Name))
|
||||
</td>
|
||||
<td>
|
||||
<div class="btn-list flex-nowrap justify-content-end">
|
||||
<a asp-action="Add" asp-route-igdbid="@item.IGDBId" class="btn btn-ghost-primary">Select</a>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
}
|
||||
|
||||
<div class="card-footer">
|
||||
<div class="d-flex">
|
||||
<a class="btn btn-ghost-primary" asp-action="Add" asp-controller="Games">Go Back</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
|
@ -1,106 +0,0 @@
|
|||
@using LANCommander.Data.Models
|
||||
@model LANCommander.Data.Models.Game
|
||||
|
||||
@{
|
||||
ViewData["Title"] = "Keys | " + Model.Title;
|
||||
}
|
||||
|
||||
<div class="container-xl">
|
||||
<!-- Page title -->
|
||||
<div class="page-header d-print-none">
|
||||
<div class="row align-items-center">
|
||||
<div class="col">
|
||||
<div class="page-pretitle">@Model.Title</div>
|
||||
<h2 class="page-title">
|
||||
Keys
|
||||
</h2>
|
||||
</div>
|
||||
|
||||
<div class="col-auto ms-auto">
|
||||
<div class="btn-list">
|
||||
<a asp-action="Edit" asp-controller="Games" asp-route-id="@Model.Id" class="btn btn-ghost-primary">Back</a>
|
||||
<a asp-action="Edit" asp-route-id="@Model.Id" class="btn btn-primary d-none d-sm-inline-block">Edit</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="page-body">
|
||||
<div class="container-xl">
|
||||
<div class="row row-cards">
|
||||
<div class="col-12">
|
||||
<form asp-action="Edit" class="card">
|
||||
@if (Model.Keys != null && Model.Keys.Count > 0)
|
||||
{
|
||||
<div class="table-responsive">
|
||||
<table class="table table-vcenter table-mobile-md card-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Key</th>
|
||||
<th>Allocation Method</th>
|
||||
<th>Claimed By</th>
|
||||
<th>Claimed On</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
<tbody>
|
||||
@foreach (var key in Model.Keys.OrderByDescending(k => k.ClaimedOn))
|
||||
{
|
||||
<tr>
|
||||
<td class="game-key">@Html.DisplayFor(m => key.Value)</td>
|
||||
<td>@Html.DisplayFor(m => key.AllocationMethod)</td>
|
||||
<td>
|
||||
@switch (key.AllocationMethod)
|
||||
{
|
||||
case KeyAllocationMethod.MacAddress:
|
||||
<text>@key.ClaimedByMacAddress</text>
|
||||
break;
|
||||
|
||||
case KeyAllocationMethod.UserAccount:
|
||||
<text>@key.ClaimedByUser?.UserName</text>
|
||||
break;
|
||||
}
|
||||
</td>
|
||||
<td>@key.ClaimedOn</td>
|
||||
<td>
|
||||
<div class="btn-list flex-nowrap justify-content-end">
|
||||
@if ((key.AllocationMethod == KeyAllocationMethod.MacAddress && !String.IsNullOrWhiteSpace(key.ClaimedByMacAddress)) || (key.AllocationMethod == KeyAllocationMethod.UserAccount && key.ClaimedByUser != null))
|
||||
{
|
||||
<a asp-action="Release" asp-controller="Keys" asp-route-id="@key.Id" class="btn btn-sm btn-ghost-dark">Release</a>
|
||||
}
|
||||
<a asp-action="Delete" asp-controller="Keys" asp-route-id="@key.Id" class="btn btn-sm btn-ghost-danger">Delete</a>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
}
|
||||
else
|
||||
{
|
||||
<div class="empty">
|
||||
<p class="empty-title">No Key</p>
|
||||
<p class="empty-subtitle text-muted">There have been no keys added for this game.</p>
|
||||
<div class="empty-action">
|
||||
<a asp-action="Edit" asp-controller="Keys" asp-route-id="@Model.Id" class="btn btn-primary">Edit Keys</a>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.game-key {
|
||||
font-family: var(--tblr-font-monospace);
|
||||
}
|
||||
</style>
|
||||
|
||||
@section Scripts {
|
||||
@{ await Html.RenderPartialAsync("_ValidationScriptsPartial"); }
|
||||
}
|
|
@ -1,73 +0,0 @@
|
|||
@model LANCommander.Models.EditKeysViewModel
|
||||
|
||||
@{
|
||||
ViewData["Title"] = "Edit Keys | " + Model.Game.Title;
|
||||
}
|
||||
|
||||
<div class="container-xl">
|
||||
<!-- Page title -->
|
||||
<div class="page-header d-print-none">
|
||||
<div class="row align-items-center">
|
||||
<div class="col">
|
||||
<div class="page-pretitle">@Model.Game.Title</div>
|
||||
<h2 class="page-title">
|
||||
Edit Keys
|
||||
</h2>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="page-body">
|
||||
<div class="container-xl">
|
||||
<div class="row row-cards">
|
||||
<div class="col-12">
|
||||
<form asp-action="Edit" class="card">
|
||||
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
|
||||
|
||||
<input type="hidden" asp-for="Keys" />
|
||||
<input type="hidden" asp-for="Game.Id" />
|
||||
|
||||
<div id="KeyEditor" style="height: 100%; min-height: 600px;"></div>
|
||||
|
||||
<div class="card-footer">
|
||||
<div class="d-flex">
|
||||
<a asp-action="Details" asp-route-id="@Model.Game.Id" class="btn btn-ghost-primary">Cancel</a>
|
||||
<button type="submit" class="btn btn-primary ms-auto">Save</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@section Scripts {
|
||||
@{ await Html.RenderPartialAsync("_ValidationScriptsPartial"); }
|
||||
|
||||
<script src="~/lib/monaco-editor/min/vs/loader.js"></script>
|
||||
|
||||
<script>
|
||||
require.config({ paths: { vs: '/lib/monaco-editor/min/vs' } });
|
||||
require(['vs/editor/editor.main'], function () {
|
||||
var editor = monaco.editor.create(document.getElementById('KeyEditor'), {
|
||||
value: $('#Keys').val(),
|
||||
readOnly: false,
|
||||
theme: 'vs-dark',
|
||||
automaticLayout: true
|
||||
});
|
||||
|
||||
editor.onDidChangeModelContent(function (e) {
|
||||
$('#Keys').val(editor.getModel().getValue());
|
||||
});
|
||||
});
|
||||
|
||||
document.addEventListener('keydown', e => {
|
||||
if (e.ctrlKey && e.key === 's') {
|
||||
e.preventDefault();
|
||||
|
||||
$('form').submit();
|
||||
}
|
||||
});
|
||||
</script>
|
||||
}
|
|
@ -1,125 +0,0 @@
|
|||
@using LANCommander.Components;
|
||||
@using LANCommander.Data.Enums
|
||||
@model LANCommander.Data.Models.Script
|
||||
|
||||
@{
|
||||
ViewData["Title"] = "Add Script | " + Model.Game.Title;
|
||||
}
|
||||
|
||||
<div class="container-xl">
|
||||
<!-- Page title -->
|
||||
<div class="page-header d-print-none">
|
||||
<div class="row align-items-center">
|
||||
<div class="col">
|
||||
<div class="page-pretitle">@Model.Game.Title</div>
|
||||
<h2 class="page-title">
|
||||
Add Script
|
||||
</h2>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="page-body">
|
||||
<div class="container-xl">
|
||||
<div class="row row-cards">
|
||||
<div class="col-12">
|
||||
<form asp-action="Add" class="card">
|
||||
<div class="card-body pb-0">
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-3">
|
||||
<div class="mb-3">
|
||||
<label asp-for="Type" class="control-label"></label>
|
||||
<select asp-for="Type" class="form-control" asp-items="Html.GetEnumSelectList<ScriptType>()"></select>
|
||||
<span asp-validation-for="Type" class="text-danger"></span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-9">
|
||||
<div class="mb-3">
|
||||
<label asp-for="Name" class="control-label"></label>
|
||||
<input asp-for="Name" class="form-control" />
|
||||
<span asp-validation-for="Name" class="text-danger"></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<div class="mb-3">
|
||||
<label asp-for="Description" class="control-label"></label>
|
||||
<textarea asp-for="Description" class="form-control"></textarea>
|
||||
<span asp-validation-for="Description" class="text-danger"></span>
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label class="form-check">
|
||||
<input asp-for="RequiresAdmin" type="checkbox" class="form-check-input" />
|
||||
<span class="form-check-label">Requires Admin Privileges</span>
|
||||
<span class="form-check-description">Marks the script as needing admin privileges. Recommended for any changes to the system e.g. Windows Registry.</span>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<input type="hidden" asp-for="Contents" />
|
||||
<input type="hidden" asp-for="GameId" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col btn-list mb-3">
|
||||
<component type="typeof(SnippetBar)" render-mode="Server" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="ScriptEditor" style="height: 100%; min-height: 600px;"></div>
|
||||
|
||||
<div class="card-footer">
|
||||
<div class="d-flex">
|
||||
<a asp-action="Edit" asp-controller="Games" asp-route-id="@Model.Game.Id" class="btn btn-ghost-primary">Cancel</a>
|
||||
<button type="submit" class="btn btn-primary ms-auto">Save</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@section Scripts {
|
||||
@{ await Html.RenderPartialAsync("_ValidationScriptsPartial"); }
|
||||
|
||||
<script src="~/lib/monaco-editor/min/vs/loader.js"></script>
|
||||
|
||||
<script>
|
||||
window.Editor = {};
|
||||
|
||||
require.config({ paths: { vs: '/lib/monaco-editor/min/vs' } });
|
||||
require(['vs/editor/editor.main'], function () {
|
||||
window.Editor = monaco.editor.create(document.getElementById('ScriptEditor'), {
|
||||
value: $('#Contents').val(),
|
||||
language: 'powershell',
|
||||
readOnly: false,
|
||||
theme: 'vs-dark',
|
||||
automaticLayout: true
|
||||
});
|
||||
|
||||
window.Editor.onDidChangeModelContent(function (e) {
|
||||
$('#Contents').val(window.Editor.getModel().getValue());
|
||||
});
|
||||
});
|
||||
|
||||
document.addEventListener('keydown', e => {
|
||||
if (e.ctrlKey && e.key === 's') {
|
||||
e.preventDefault();
|
||||
|
||||
$('form').submit();
|
||||
}
|
||||
});
|
||||
</script>
|
||||
}
|
|
@ -1,126 +0,0 @@
|
|||
@using LANCommander.Components;
|
||||
@using LANCommander.Data.Enums
|
||||
@model LANCommander.Data.Models.Script
|
||||
|
||||
@{
|
||||
ViewData["Title"] = "Edit Script | " + Model.Game.Title;
|
||||
}
|
||||
|
||||
<div class="container-xl">
|
||||
<!-- Page title -->
|
||||
<div class="page-header d-print-none">
|
||||
<div class="row align-items-center">
|
||||
<div class="col">
|
||||
<div class="page-pretitle">@Model.Game.Title</div>
|
||||
<h2 class="page-title">
|
||||
Edit Script
|
||||
</h2>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="page-body">
|
||||
<div class="container-xl">
|
||||
<div class="row row-cards">
|
||||
<div class="col-12">
|
||||
<form asp-action="Edit" class="card">
|
||||
<div class="card-body pb-0">
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-3">
|
||||
<div class="mb-3">
|
||||
<label asp-for="Type" class="control-label"></label>
|
||||
<select asp-for="Type" class="form-control" asp-items="Html.GetEnumSelectList<ScriptType>()"></select>
|
||||
<span asp-validation-for="Type" class="text-danger"></span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-9">
|
||||
<div class="mb-3">
|
||||
<label asp-for="Name" class="control-label"></label>
|
||||
<input asp-for="Name" class="form-control" />
|
||||
<span asp-validation-for="Name" class="text-danger"></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<div class="mb-3">
|
||||
<label asp-for="Description" class="control-label"></label>
|
||||
<textarea asp-for="Description" class="form-control"></textarea>
|
||||
<span asp-validation-for="Description" class="text-danger"></span>
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label class="form-check">
|
||||
<input asp-for="RequiresAdmin" type="checkbox" class="form-check-input" />
|
||||
<span class="form-check-label">Requires Admin Privileges</span>
|
||||
<span class="form-check-description">Marks the script as needing admin privileges. Recommended for any changes to the system e.g. Windows Registry.</span>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<input type="hidden" asp-for="Contents" />
|
||||
<input type="hidden" asp-for="GameId" />
|
||||
<input type="hidden" asp-for="Id" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col btn-list mb-3">
|
||||
<component type="typeof(SnippetBar)" render-mode="Server" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="ScriptEditor" style="height: 100%; min-height: 600px;"></div>
|
||||
|
||||
<div class="card-footer">
|
||||
<div class="d-flex">
|
||||
<a asp-action="Edit" asp-controller="Games" asp-route-id="@Model.Game.Id" class="btn btn-ghost-primary">Cancel</a>
|
||||
<button type="submit" class="btn btn-primary ms-auto">Save</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@section Scripts {
|
||||
@{ await Html.RenderPartialAsync("_ValidationScriptsPartial"); }
|
||||
|
||||
<script src="~/lib/monaco-editor/min/vs/loader.js"></script>
|
||||
|
||||
<script>
|
||||
window.Editor = {};
|
||||
|
||||
require.config({ paths: { vs: '/lib/monaco-editor/min/vs' } });
|
||||
require(['vs/editor/editor.main'], function () {
|
||||
window.Editor = monaco.editor.create(document.getElementById('ScriptEditor'), {
|
||||
value: $('#Contents').val(),
|
||||
language: 'powershell',
|
||||
readOnly: false,
|
||||
theme: 'vs-dark',
|
||||
automaticLayout: true
|
||||
});
|
||||
|
||||
window.Editor.onDidChangeModelContent(function (e) {
|
||||
$('#Contents').val(window.Editor.getModel().getValue());
|
||||
});
|
||||
});
|
||||
|
||||
document.addEventListener('keydown', e => {
|
||||
if (e.ctrlKey && e.key === 's') {
|
||||
e.preventDefault();
|
||||
|
||||
$('form').submit();
|
||||
}
|
||||
});
|
||||
</script>
|
||||
}
|
|
@ -1,43 +0,0 @@
|
|||
@model LANCommander.Data.Models.Tag
|
||||
|
||||
@{
|
||||
ViewData["Title"] = "Create";
|
||||
}
|
||||
|
||||
<h1>Create</h1>
|
||||
|
||||
<h4>Tag</h4>
|
||||
<hr />
|
||||
<div class="row">
|
||||
<div class="col-md-4">
|
||||
<form asp-action="Create">
|
||||
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
|
||||
<div class="form-group">
|
||||
<label asp-for="Name" class="control-label"></label>
|
||||
<input asp-for="Name" class="form-control" />
|
||||
<span asp-validation-for="Name" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label asp-for="CreatedOn" class="control-label"></label>
|
||||
<input asp-for="CreatedOn" class="form-control" />
|
||||
<span asp-validation-for="CreatedOn" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label asp-for="UpdatedOn" class="control-label"></label>
|
||||
<input asp-for="UpdatedOn" class="form-control" />
|
||||
<span asp-validation-for="UpdatedOn" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<input type="submit" value="Create" class="btn btn-primary" />
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<a asp-action="Index">Back to List</a>
|
||||
</div>
|
||||
|
||||
@section Scripts {
|
||||
@{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
|
||||
}
|
|
@ -1,39 +0,0 @@
|
|||
@model LANCommander.Data.Models.Tag
|
||||
|
||||
@{
|
||||
ViewData["Title"] = "Delete";
|
||||
}
|
||||
|
||||
<h1>Delete</h1>
|
||||
|
||||
<h3>Are you sure you want to delete this?</h3>
|
||||
<div>
|
||||
<h4>Tag</h4>
|
||||
<hr />
|
||||
<dl class="row">
|
||||
<dt class = "col-sm-2">
|
||||
@Html.DisplayNameFor(model => model.Name)
|
||||
</dt>
|
||||
<dd class = "col-sm-10">
|
||||
@Html.DisplayFor(model => model.Name)
|
||||
</dd>
|
||||
<dt class = "col-sm-2">
|
||||
@Html.DisplayNameFor(model => model.CreatedOn)
|
||||
</dt>
|
||||
<dd class = "col-sm-10">
|
||||
@Html.DisplayFor(model => model.CreatedOn)
|
||||
</dd>
|
||||
<dt class = "col-sm-2">
|
||||
@Html.DisplayNameFor(model => model.UpdatedOn)
|
||||
</dt>
|
||||
<dd class = "col-sm-10">
|
||||
@Html.DisplayFor(model => model.UpdatedOn)
|
||||
</dd>
|
||||
</dl>
|
||||
|
||||
<form asp-action="Delete">
|
||||
<input type="hidden" asp-for="Id" />
|
||||
<input type="submit" value="Delete" class="btn btn-danger" /> |
|
||||
<a asp-action="Index">Back to List</a>
|
||||
</form>
|
||||
</div>
|
|
@ -1,36 +0,0 @@
|
|||
@model LANCommander.Data.Models.Tag
|
||||
|
||||
@{
|
||||
ViewData["Title"] = "Details";
|
||||
}
|
||||
|
||||
<h1>Details</h1>
|
||||
|
||||
<div>
|
||||
<h4>Tag</h4>
|
||||
<hr />
|
||||
<dl class="row">
|
||||
<dt class = "col-sm-2">
|
||||
@Html.DisplayNameFor(model => model.Name)
|
||||
</dt>
|
||||
<dd class = "col-sm-10">
|
||||
@Html.DisplayFor(model => model.Name)
|
||||
</dd>
|
||||
<dt class = "col-sm-2">
|
||||
@Html.DisplayNameFor(model => model.CreatedOn)
|
||||
</dt>
|
||||
<dd class = "col-sm-10">
|
||||
@Html.DisplayFor(model => model.CreatedOn)
|
||||
</dd>
|
||||
<dt class = "col-sm-2">
|
||||
@Html.DisplayNameFor(model => model.UpdatedOn)
|
||||
</dt>
|
||||
<dd class = "col-sm-10">
|
||||
@Html.DisplayFor(model => model.UpdatedOn)
|
||||
</dd>
|
||||
</dl>
|
||||
</div>
|
||||
<div>
|
||||
<a asp-action="Edit" asp-route-id="@Model?.Id">Edit</a> |
|
||||
<a asp-action="Index">Back to List</a>
|
||||
</div>
|
|
@ -1,44 +0,0 @@
|
|||
@model LANCommander.Data.Models.Tag
|
||||
|
||||
@{
|
||||
ViewData["Title"] = "Edit";
|
||||
}
|
||||
|
||||
<h1>Edit</h1>
|
||||
|
||||
<h4>Tag</h4>
|
||||
<hr />
|
||||
<div class="row">
|
||||
<div class="col-md-4">
|
||||
<form asp-action="Edit">
|
||||
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
|
||||
<div class="form-group">
|
||||
<label asp-for="Name" class="control-label"></label>
|
||||
<input asp-for="Name" class="form-control" />
|
||||
<span asp-validation-for="Name" class="text-danger"></span>
|
||||
</div>
|
||||
<input type="hidden" asp-for="Id" />
|
||||
<div class="form-group">
|
||||
<label asp-for="CreatedOn" class="control-label"></label>
|
||||
<input asp-for="CreatedOn" class="form-control" />
|
||||
<span asp-validation-for="CreatedOn" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label asp-for="UpdatedOn" class="control-label"></label>
|
||||
<input asp-for="UpdatedOn" class="form-control" />
|
||||
<span asp-validation-for="UpdatedOn" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<input type="submit" value="Save" class="btn btn-primary" />
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<a asp-action="Index">Back to List</a>
|
||||
</div>
|
||||
|
||||
@section Scripts {
|
||||
@{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
|
||||
}
|
|
@ -1,47 +0,0 @@
|
|||
@model IEnumerable<LANCommander.Data.Models.Tag>
|
||||
|
||||
@{
|
||||
ViewData["Title"] = "Index";
|
||||
}
|
||||
|
||||
<h1>Index</h1>
|
||||
|
||||
<p>
|
||||
<a asp-action="Create">Create New</a>
|
||||
</p>
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>
|
||||
@Html.DisplayNameFor(model => model.Name)
|
||||
</th>
|
||||
<th>
|
||||
@Html.DisplayNameFor(model => model.CreatedOn)
|
||||
</th>
|
||||
<th>
|
||||
@Html.DisplayNameFor(model => model.UpdatedOn)
|
||||
</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach (var item in Model) {
|
||||
<tr>
|
||||
<td>
|
||||
@Html.DisplayFor(modelItem => item.Name)
|
||||
</td>
|
||||
<td>
|
||||
@Html.DisplayFor(modelItem => item.CreatedOn)
|
||||
</td>
|
||||
<td>
|
||||
@Html.DisplayFor(modelItem => item.UpdatedOn)
|
||||
</td>
|
||||
<td>
|
||||
<a asp-action="Edit" asp-route-id="@item.Id">Edit</a> |
|
||||
<a asp-action="Details" asp-route-id="@item.Id">Details</a> |
|
||||
<a asp-action="Delete" asp-route-id="@item.Id">Delete</a>
|
||||
</td>
|
||||
</tr>
|
||||
}
|
||||
</tbody>
|
||||
</table>
|
|
@ -1,16 +0,0 @@
|
|||
class Modal {
|
||||
constructor(id) {
|
||||
this.ElementId = id;
|
||||
// @ts-ignore
|
||||
this.Instance = new bootstrap.Modal(`#${this.ElementId}`, {
|
||||
keyboard: false
|
||||
});
|
||||
}
|
||||
Show(header, message) {
|
||||
document.getElementById(`${this.ElementId}Header`).innerText = header;
|
||||
document.getElementById(`${this.ElementId}Message`).innerText = message;
|
||||
this.Instance.show();
|
||||
}
|
||||
}
|
||||
const ErrorModal = new Modal('ErrorModal');
|
||||
//# sourceMappingURL=Modal.js.map
|
|
@ -1 +0,0 @@
|
|||
{"version":3,"file":"Modal.js","sourceRoot":"","sources":["Modal.ts"],"names":[],"mappings":"AAAA,MAAM,KAAK;IAIP,YAAY,EAAU;QAClB,IAAI,CAAC,SAAS,GAAG,EAAE,CAAC;QAEpB,aAAa;QACb,IAAI,CAAC,QAAQ,GAAG,IAAI,SAAS,CAAC,KAAK,CAAC,IAAI,IAAI,CAAC,SAAS,EAAE,EAAE;YACtD,QAAQ,EAAE,KAAK;SAClB,CAAC,CAAC;IACP,CAAC;IAED,IAAI,CAAC,MAAc,EAAE,OAAe;QAChC,QAAQ,CAAC,cAAc,CAAC,GAAG,IAAI,CAAC,SAAS,QAAQ,CAAC,CAAC,SAAS,GAAG,MAAM,CAAC;QACtE,QAAQ,CAAC,cAAc,CAAC,GAAG,IAAI,CAAC,SAAS,SAAS,CAAC,CAAC,SAAS,GAAG,OAAO,CAAC;QAExE,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC;IACzB,CAAC;CACJ;AAED,MAAM,UAAU,GAAG,IAAI,KAAK,CAAC,YAAY,CAAC,CAAC"}
|
|
@ -1,22 +0,0 @@
|
|||
class Modal {
|
||||
Instance: any;
|
||||
ElementId: string;
|
||||
|
||||
constructor(id: string) {
|
||||
this.ElementId = id;
|
||||
|
||||
// @ts-ignore
|
||||
this.Instance = new bootstrap.Modal(`#${this.ElementId}`, {
|
||||
keyboard: false
|
||||
});
|
||||
}
|
||||
|
||||
Show(header: string, message: string) {
|
||||
document.getElementById(`${this.ElementId}Header`).innerText = header;
|
||||
document.getElementById(`${this.ElementId}Message`).innerText = message;
|
||||
|
||||
this.Instance.show();
|
||||
}
|
||||
}
|
||||
|
||||
const ErrorModal = new Modal('ErrorModal');
|
|
@ -1,118 +0,0 @@
|
|||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||||
return new (P || (P = Promise))(function (resolve, reject) {
|
||||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||||
});
|
||||
};
|
||||
class Chunk {
|
||||
constructor(start, end, index) {
|
||||
this.Start = start;
|
||||
this.End = end;
|
||||
this.Index = index;
|
||||
}
|
||||
}
|
||||
class Uploader {
|
||||
constructor() {
|
||||
this.InitRoute = "/Upload/Init";
|
||||
this.ChunkRoute = "/Upload/Chunk";
|
||||
this.ValidateRoute = "/Archives/Validate";
|
||||
this.MaxChunkSize = 1024 * 1024 * 25;
|
||||
}
|
||||
Init(fileInputId, uploadButtonId) {
|
||||
this.FileInput = document.getElementById("File");
|
||||
this.UploadButton = document.getElementById("UploadButton");
|
||||
this.VersionInput = document.getElementById("Version");
|
||||
this.ChangelogTextArea = document.getElementById("Changelog");
|
||||
this.LastVersionIdInput = document.getElementById("LastVersion_Id");
|
||||
this.GameIdInput = document.getElementById("GameId");
|
||||
this.ParentForm = this.FileInput.closest("form");
|
||||
this.Chunks = [];
|
||||
this.UploadButton.onclick = (e) => __awaiter(this, void 0, void 0, function* () {
|
||||
yield this.OnUploadButtonClicked(e);
|
||||
});
|
||||
}
|
||||
OnUploadButtonClicked(e) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
e.preventDefault();
|
||||
this.OnStart();
|
||||
this.File = this.FileInput.files.item(0);
|
||||
this.TotalChunks = Math.ceil(this.File.size / this.MaxChunkSize);
|
||||
var response = yield fetch(this.InitRoute, {
|
||||
method: "POST"
|
||||
});
|
||||
const data = yield response.json();
|
||||
if (response.ok) {
|
||||
this.Key = data.key;
|
||||
this.GetChunks();
|
||||
try {
|
||||
for (let chunk of this.Chunks) {
|
||||
yield this.UploadChunk(chunk);
|
||||
}
|
||||
var isValid = yield this.Validate();
|
||||
if (isValid)
|
||||
this.OnComplete(this.Id, this.Key);
|
||||
else
|
||||
this.OnError();
|
||||
}
|
||||
catch (ex) {
|
||||
this.OnError();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
UploadChunk(chunk) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
let formData = new FormData();
|
||||
formData.append('file', this.File.slice(chunk.Start, chunk.End + 1));
|
||||
formData.append('start', chunk.Start.toString());
|
||||
formData.append('end', chunk.End.toString());
|
||||
formData.append('key', this.Key);
|
||||
formData.append('total', this.File.size.toString());
|
||||
console.info(`Uploading chunk ${chunk.Index}/${this.TotalChunks}...`);
|
||||
let chunkResponse = yield fetch(this.ChunkRoute, {
|
||||
method: "POST",
|
||||
body: formData
|
||||
});
|
||||
if (!chunkResponse)
|
||||
throw `Error uploading chunk ${chunk.Index}/${this.TotalChunks}`;
|
||||
this.OnProgress(chunk.Index / this.TotalChunks);
|
||||
});
|
||||
}
|
||||
Validate() {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
let formData = new FormData();
|
||||
formData.append('Version', this.VersionInput.value);
|
||||
formData.append('Changelog', this.ChangelogTextArea.value);
|
||||
formData.append('GameId', this.GameIdInput.value);
|
||||
formData.append('ObjectKey', this.Key);
|
||||
let validationResponse = yield fetch(`${this.ValidateRoute}/${this.Key}`, {
|
||||
method: "POST",
|
||||
body: formData
|
||||
});
|
||||
if (!validationResponse.ok) {
|
||||
ErrorModal.Show("Archive Invalid", yield validationResponse.text());
|
||||
return false;
|
||||
}
|
||||
let data = yield validationResponse.json();
|
||||
if (data == null || data.Id === "") {
|
||||
ErrorModal.Show("Upload Error", "Something interfered with the upload. Try again.");
|
||||
return false;
|
||||
}
|
||||
this.Id = data.Id;
|
||||
return true;
|
||||
});
|
||||
}
|
||||
GetChunks() {
|
||||
for (let currentChunk = 1; currentChunk <= this.TotalChunks; currentChunk++) {
|
||||
let start = (currentChunk - 1) * this.MaxChunkSize;
|
||||
let end = (currentChunk * this.MaxChunkSize) - 1;
|
||||
if (currentChunk == this.TotalChunks)
|
||||
end = this.File.size;
|
||||
this.Chunks.push(new Chunk(start, end, currentChunk));
|
||||
}
|
||||
}
|
||||
}
|
||||
//# sourceMappingURL=Upload.js.map
|
|
@ -1 +0,0 @@
|
|||
{"version":3,"file":"Upload.js","sourceRoot":"","sources":["Upload.ts"],"names":[],"mappings":";;;;;;;;;AAAA,MAAM,KAAK;IAKP,YAAY,KAAa,EAAE,GAAW,EAAE,KAAa;QACjD,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;QACnB,IAAI,CAAC,GAAG,GAAG,GAAG,CAAC;QACf,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;IACvB,CAAC;CACJ;AAED,MAAM,QAAQ;IAAd;QAaI,cAAS,GAAW,cAAc,CAAC;QACnC,eAAU,GAAW,eAAe,CAAC;QACrC,kBAAa,GAAW,oBAAoB,CAAC;QAE7C,iBAAY,GAAW,IAAI,GAAG,IAAI,GAAG,EAAE,CAAC;IAmI5C,CAAC;IA3HG,IAAI,CAAC,WAAmB,EAAE,cAAsB;QAC5C,IAAI,CAAC,SAAS,GAAG,QAAQ,CAAC,cAAc,CAAC,MAAM,CAAqB,CAAC;QACrE,IAAI,CAAC,YAAY,GAAG,QAAQ,CAAC,cAAc,CAAC,cAAc,CAAsB,CAAC;QACjF,IAAI,CAAC,YAAY,GAAG,QAAQ,CAAC,cAAc,CAAC,SAAS,CAAqB,CAAC;QAC3E,IAAI,CAAC,iBAAiB,GAAG,QAAQ,CAAC,cAAc,CAAC,WAAW,CAAwB,CAAC;QACrF,IAAI,CAAC,kBAAkB,GAAG,QAAQ,CAAC,cAAc,CAAC,gBAAgB,CAAqB,CAAC;QACxF,IAAI,CAAC,WAAW,GAAG,QAAQ,CAAC,cAAc,CAAC,QAAQ,CAAqB,CAAC;QACzE,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;QAEjD,IAAI,CAAC,MAAM,GAAG,EAAE,CAAC;QAEjB,IAAI,CAAC,YAAY,CAAC,OAAO,GAAG,CAAO,CAAC,EAAE,EAAE;YACpC,MAAM,IAAI,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC;QACxC,CAAC,CAAA,CAAA;IACL,CAAC;IAEK,qBAAqB,CAAC,CAAa;;YACrC,CAAC,CAAC,cAAc,EAAE,CAAC;YAEnB,IAAI,CAAC,OAAO,EAAE,CAAC;YAEf,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YACzC,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,YAAY,CAAC,CAAC;YAEjE,IAAI,QAAQ,GAAG,MAAM,KAAK,CAAC,IAAI,CAAC,SAAS,EAAE;gBACvC,MAAM,EAAE,MAAM;aACjB,CAAC,CAAC;YAEH,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;YAEnC,IAAI,QAAQ,CAAC,EAAE,EAAE;gBACb,IAAI,CAAC,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC;gBAEpB,IAAI,CAAC,SAAS,EAAE,CAAC;gBAEjB,IAAI;oBACA,KAAK,IAAI,KAAK,IAAI,IAAI,CAAC,MAAM,EAAE;wBAC3B,MAAM,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;qBACjC;oBAED,IAAI,OAAO,GAAG,MAAM,IAAI,CAAC,QAAQ,EAAE,CAAC;oBAEpC,IAAI,OAAO;wBACP,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC;;wBAEnC,IAAI,CAAC,OAAO,EAAE,CAAC;iBACtB;gBACD,OAAO,EAAE,EAAE;oBACP,IAAI,CAAC,OAAO,EAAE,CAAC;iBAClB;aACJ;QACL,CAAC;KAAA;IAEK,WAAW,CAAC,KAAY;;YAC1B,IAAI,QAAQ,GAAG,IAAI,QAAQ,EAAE,CAAC;YAE9B,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,KAAK,EAAE,KAAK,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC;YACrE,QAAQ,CAAC,MAAM,CAAC,OAAO,EAAE,KAAK,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC,CAAC;YACjD,QAAQ,CAAC,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAC,CAAC;YAC7C,QAAQ,CAAC,MAAM,CAAC,KAAK,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC;YACjC,QAAQ,CAAC,MAAM,CAAC,OAAO,EAAE,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC;YAEpD,OAAO,CAAC,IAAI,CAAC,mBAAmB,KAAK,CAAC,KAAK,IAAI,IAAI,CAAC,WAAW,KAAK,CAAC,CAAC;YAEtE,IAAI,aAAa,GAAG,MAAM,KAAK,CAAC,IAAI,CAAC,UAAU,EAAE;gBAC7C,MAAM,EAAE,MAAM;gBACd,IAAI,EAAE,QAAQ;aACjB,CAAC,CAAC;YAEH,IAAI,CAAC,aAAa;gBACd,MAAM,yBAAyB,KAAK,CAAC,KAAK,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC;YAErE,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,KAAK,GAAG,IAAI,CAAC,WAAW,CAAC,CAAC;QACpD,CAAC;KAAA;IAEK,QAAQ;;YACV,IAAI,QAAQ,GAAG,IAAI,QAAQ,EAAE,CAAC;YAE9B,QAAQ,CAAC,MAAM,CAAC,SAAS,EAAE,IAAI,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC;YACpD,QAAQ,CAAC,MAAM,CAAC,WAAW,EAAE,IAAI,CAAC,iBAAiB,CAAC,KAAK,CAAC,CAAC;YAC3D,QAAQ,CAAC,MAAM,CAAC,QAAQ,EAAE,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;YAClD,QAAQ,CAAC,MAAM,CAAC,WAAW,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC;YAEvC,IAAI,kBAAkB,GAAG,MAAM,KAAK,CAAC,GAAG,IAAI,CAAC,aAAa,IAAI,IAAI,CAAC,GAAG,EAAE,EAAE;gBACtE,MAAM,EAAE,MAAM;gBACd,IAAI,EAAE,QAAQ;aACjB,CAAC,CAAC;YAEH,IAAI,CAAC,kBAAkB,CAAC,EAAE,EAAE;gBACxB,UAAU,CAAC,IAAI,CAAC,iBAAiB,EAAE,MAAM,kBAAkB,CAAC,IAAI,EAAE,CAAC,CAAA;gBAEnE,OAAO,KAAK,CAAC;aAChB;YAED,IAAI,IAAI,GAAG,MAAM,kBAAkB,CAAC,IAAI,EAAE,CAAC;YAE3C,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,CAAC,EAAE,KAAK,EAAE,EAAE;gBAChC,UAAU,CAAC,IAAI,CAAC,cAAc,EAAE,kDAAkD,CAAC,CAAC;gBAEpF,OAAO,KAAK,CAAC;aAChB;YAED,IAAI,CAAC,EAAE,GAAG,IAAI,CAAC,EAAE,CAAC;YAElB,OAAO,IAAI,CAAC;QAChB,CAAC;KAAA;IAED,SAAS;QACL,KAAK,IAAI,YAAY,GAAG,CAAC,EAAE,YAAY,IAAI,IAAI,CAAC,WAAW,EAAE,YAAY,EAAE,EAAE;YACzE,IAAI,KAAK,GAAG,CAAC,YAAY,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,YAAY,CAAC;YACnD,IAAI,GAAG,GAAG,CAAC,YAAY,GAAG,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC;YAEjD,IAAI,YAAY,IAAI,IAAI,CAAC,WAAW;gBAChC,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC;YAEzB,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,KAAK,CAAC,KAAK,EAAE,GAAG,EAAE,YAAY,CAAC,CAAC,CAAC;SACzD;IACL,CAAC;CAMJ"}
|
|
@ -1,161 +0,0 @@
|
|||
class Chunk {
|
||||
Index: number;
|
||||
Start: number;
|
||||
End: number;
|
||||
|
||||
constructor(start: number, end: number, index: number) {
|
||||
this.Start = start;
|
||||
this.End = end;
|
||||
this.Index = index;
|
||||
}
|
||||
}
|
||||
|
||||
class Uploader {
|
||||
ParentForm: HTMLFormElement;
|
||||
FileInput: HTMLInputElement;
|
||||
UploadButton: HTMLButtonElement;
|
||||
VersionInput: HTMLInputElement;
|
||||
LastVersionIdInput: HTMLInputElement;
|
||||
GameIdInput: HTMLInputElement;
|
||||
ChangelogTextArea: HTMLTextAreaElement;
|
||||
ObjectKeyInput: HTMLInputElement;
|
||||
IdInput: HTMLInputElement;
|
||||
|
||||
File: File;
|
||||
|
||||
InitRoute: string = "/Upload/Init";
|
||||
ChunkRoute: string = "/Upload/Chunk";
|
||||
ValidateRoute: string = "/Archives/Validate";
|
||||
|
||||
MaxChunkSize: number = 1024 * 1024 * 25;
|
||||
TotalChunks: number;
|
||||
CurrentChunk: number;
|
||||
Chunks: Chunk[];
|
||||
|
||||
Key: string;
|
||||
Id: string;
|
||||
|
||||
Init(fileInputId: string, uploadButtonId: string) {
|
||||
this.FileInput = document.getElementById("File") as HTMLInputElement;
|
||||
this.UploadButton = document.getElementById("UploadButton") as HTMLButtonElement;
|
||||
this.VersionInput = document.getElementById("Version") as HTMLInputElement;
|
||||
this.ChangelogTextArea = document.getElementById("Changelog") as HTMLTextAreaElement;
|
||||
this.LastVersionIdInput = document.getElementById("LastVersion_Id") as HTMLInputElement;
|
||||
this.GameIdInput = document.getElementById("GameId") as HTMLInputElement;
|
||||
this.ParentForm = this.FileInput.closest("form");
|
||||
|
||||
this.Chunks = [];
|
||||
|
||||
this.UploadButton.onclick = async (e) => {
|
||||
await this.OnUploadButtonClicked(e);
|
||||
}
|
||||
}
|
||||
|
||||
async OnUploadButtonClicked(e: MouseEvent) {
|
||||
e.preventDefault();
|
||||
|
||||
this.OnStart();
|
||||
|
||||
this.File = this.FileInput.files.item(0);
|
||||
this.TotalChunks = Math.ceil(this.File.size / this.MaxChunkSize);
|
||||
|
||||
var response = await fetch(this.InitRoute, {
|
||||
method: "POST"
|
||||
});
|
||||
|
||||
const data = await response.json();
|
||||
|
||||
if (response.ok) {
|
||||
this.Key = data.key;
|
||||
|
||||
this.GetChunks();
|
||||
|
||||
try {
|
||||
for (let chunk of this.Chunks) {
|
||||
await this.UploadChunk(chunk);
|
||||
}
|
||||
|
||||
var isValid = await this.Validate();
|
||||
|
||||
if (isValid)
|
||||
this.OnComplete(this.Id, this.Key);
|
||||
else
|
||||
this.OnError();
|
||||
}
|
||||
catch (ex) {
|
||||
this.OnError();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async UploadChunk(chunk: Chunk) {
|
||||
let formData = new FormData();
|
||||
|
||||
formData.append('file', this.File.slice(chunk.Start, chunk.End + 1));
|
||||
formData.append('start', chunk.Start.toString());
|
||||
formData.append('end', chunk.End.toString());
|
||||
formData.append('key', this.Key);
|
||||
formData.append('total', this.File.size.toString());
|
||||
|
||||
console.info(`Uploading chunk ${chunk.Index}/${this.TotalChunks}...`);
|
||||
|
||||
let chunkResponse = await fetch(this.ChunkRoute, {
|
||||
method: "POST",
|
||||
body: formData
|
||||
});
|
||||
|
||||
if (!chunkResponse)
|
||||
throw `Error uploading chunk ${chunk.Index}/${this.TotalChunks}`;
|
||||
|
||||
this.OnProgress(chunk.Index / this.TotalChunks);
|
||||
}
|
||||
|
||||
async Validate(): Promise<boolean> {
|
||||
let formData = new FormData();
|
||||
|
||||
formData.append('Version', this.VersionInput.value);
|
||||
formData.append('Changelog', this.ChangelogTextArea.value);
|
||||
formData.append('GameId', this.GameIdInput.value);
|
||||
formData.append('ObjectKey', this.Key);
|
||||
|
||||
let validationResponse = await fetch(`${this.ValidateRoute}/${this.Key}`, {
|
||||
method: "POST",
|
||||
body: formData
|
||||
});
|
||||
|
||||
if (!validationResponse.ok) {
|
||||
ErrorModal.Show("Archive Invalid", await validationResponse.text())
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
let data = await validationResponse.json();
|
||||
|
||||
if (data == null || data.Id === "") {
|
||||
ErrorModal.Show("Upload Error", "Something interfered with the upload. Try again.");
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
this.Id = data.Id;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
GetChunks() {
|
||||
for (let currentChunk = 1; currentChunk <= this.TotalChunks; currentChunk++) {
|
||||
let start = (currentChunk - 1) * this.MaxChunkSize;
|
||||
let end = (currentChunk * this.MaxChunkSize) - 1;
|
||||
|
||||
if (currentChunk == this.TotalChunks)
|
||||
end = this.File.size;
|
||||
|
||||
this.Chunks.push(new Chunk(start, end, currentChunk));
|
||||
}
|
||||
}
|
||||
|
||||
OnStart: () => void;
|
||||
OnComplete: (id: string, key: string) => void;
|
||||
OnProgress: (percent: number) => void;
|
||||
OnError: () => void;
|
||||
}
|
Loading…
Add table
Reference in a new issue