Added wishlist
This commit is contained in:
@@ -0,0 +1,43 @@
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using MyWebsite.Controllers;
|
||||
using MyWebsite.Models;
|
||||
using MyWebsite.Models.Databases;
|
||||
using System;
|
||||
using System.Linq;
|
||||
|
||||
namespace MyWebsite.Areas.Admin.Controllers
|
||||
{
|
||||
[Authorize]
|
||||
[Area("Admin")]
|
||||
public class WishlistController : ExtendedController
|
||||
{
|
||||
private const string ViewPath = "Areas/Admin/Views/Shared/Wishlist.cshtml";
|
||||
public WishlistController(DatabaseContext context) : base(context) { }
|
||||
|
||||
[HttpGet]
|
||||
public IActionResult Index() =>
|
||||
View(ViewPath, Database.Wishlist.FirstOrDefault());
|
||||
|
||||
[HttpPost]
|
||||
public IActionResult Index(WishlistModel model)
|
||||
{
|
||||
if (model == null)
|
||||
throw new ArgumentNullException(nameof(model));
|
||||
|
||||
if (!ModelState.IsValid)
|
||||
{
|
||||
ModelState.AddModelError("Error", "Invalid data");
|
||||
return View(ViewPath, model);
|
||||
}
|
||||
|
||||
model.LastUpdated = DateTime.Now;
|
||||
|
||||
Database.Wishlist.RemoveRange(Database.Wishlist);
|
||||
Database.Wishlist.Add(model);
|
||||
Database.SaveChanges();
|
||||
|
||||
return RedirectToAction("Index", "Admin");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
@model WishlistModel
|
||||
@{
|
||||
ViewData["Title"] = "Wishlist";
|
||||
}
|
||||
|
||||
<header>
|
||||
 <a asp-action="Index">Back to the list</a>
|
||||
<h1>Edit wishlist</h1>
|
||||
<p>
|
||||
Previously updated on @Model?.LastUpdated
|
||||
</p>
|
||||
|
||||
<a class="comment" asp-area="" asp-controller="Home" asp-action="Wishlist" target="_blank">// Open wishlist</a>
|
||||
</header>
|
||||
|
||||
<article>
|
||||
<form method="post">
|
||||
<div asp-validation-summary="All" class="text-danger"></div>
|
||||
|
||||
<div class="cols">
|
||||
<label asp-for="EnglishContent"></label>
|
||||
<label asp-for="RussianContent"></label>
|
||||
<textarea asp-for="EnglishContent" spellcheck="false" required></textarea>
|
||||
<textarea asp-for="RussianContent" spellcheck="false" required></textarea>
|
||||
</div>
|
||||
|
||||
<span asp-validation-for="EnglishContent" class="text-danger"></span>
|
||||
<span asp-validation-for="RussianContent" class="text-danger"></span>
|
||||
|
||||
<br />
|
||||
<input type="submit" value="Save" />
|
||||
</form>
|
||||
</article>
|
||||
|
||||
@section Imports
|
||||
{
|
||||
<style>
|
||||
.cols
|
||||
{
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
}
|
||||
form
|
||||
{
|
||||
max-width: initial;
|
||||
}
|
||||
</style>
|
||||
}
|
||||
@@ -67,5 +67,9 @@ namespace MyWebsite.Controllers
|
||||
|
||||
return Redirect(Extensions.CheckNullOrWhitespace(Request.Headers["Referer"], "/"));
|
||||
}
|
||||
|
||||
[Route("Wishlist")]
|
||||
public IActionResult Wishlist() =>
|
||||
View(new WishlistViewModel(Database, CultureInfo.CurrentUICulture));
|
||||
}
|
||||
}
|
||||
@@ -12,6 +12,7 @@ namespace MyWebsite.Models.Databases
|
||||
public DbSet<ResumeModel> Resume { get; set; }
|
||||
public DbSet<ShortLinkModel> ShortLinks { get; set; }
|
||||
public DbSet<CustomData> CustomData { get; set; }
|
||||
public DbSet<WishlistModel> Wishlist { get;set; }
|
||||
|
||||
public DatabaseContext(DbContextOptions<DatabaseContext> options) : base(options) =>
|
||||
Database.EnsureCreated();
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
|
||||
namespace MyWebsite.Models
|
||||
{
|
||||
public class WishlistModel
|
||||
{
|
||||
[Key]
|
||||
[Required]
|
||||
public Guid Id { get; set; } = Guid.NewGuid();
|
||||
[Required]
|
||||
[Column(TypeName = "text")]
|
||||
[DisplayName("English list")]
|
||||
|
||||
public string EnglishContent { get; set; }
|
||||
[Column(TypeName = "text")]
|
||||
[DisplayName("Russian list")]
|
||||
public string RussianContent { get;set; }
|
||||
[DisplayName("Last chagnge")]
|
||||
public DateTime LastUpdated { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,129 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<data name="My wishlist" xml:space="preserve">
|
||||
<value>Список желаемого</value>
|
||||
</data>
|
||||
<data name="In case you don't know what to give me" xml:space="preserve">
|
||||
<value>На тот случай, если вы не знаете что мне подарить</value>
|
||||
</data>
|
||||
<data name="Last update" xml:space="preserve">
|
||||
<value>Последнее обновление</value>
|
||||
</data>
|
||||
</root>
|
||||
@@ -0,0 +1,19 @@
|
||||
using MyWebsite.Models;
|
||||
using MyWebsite.Models.Databases;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
|
||||
namespace MyWebsite.ViewModels
|
||||
{
|
||||
public class WishlistViewModel : ViewModelBase
|
||||
{
|
||||
public WishlistModel Wishlist { get; }
|
||||
public string Content { get; }
|
||||
public WishlistViewModel(DatabaseContext context, CultureInfo language) : base(context)
|
||||
{
|
||||
Wishlist = context.Wishlist.FirstOrDefault();
|
||||
Content = language?.TwoLetterISOLanguageName == "ru" ? Wishlist?.RussianContent : Wishlist?.EnglishContent;
|
||||
Content ??= Wishlist?.EnglishContent;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -12,7 +12,8 @@
|
||||
<a asp-action="Projects" class="comment">// Projects</a><br />
|
||||
<a asp-action="Badges" class="comment">// Badges</a><br />
|
||||
<a asp-action="Resume" class="comment">// Resume</a><br />
|
||||
<a asp-action="Contacts" class="comment">// Contact links</a>
|
||||
<a asp-action="Contacts" class="comment">// Contact links</a><br />
|
||||
<a asp-action="Wishlist" class="comment">// Wishlist</a>
|
||||
</p>
|
||||
<p>
|
||||
<a asp-action="Shortener" class="comment">// Link shortener & Files</a>
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
@model WishlistViewModel
|
||||
@{
|
||||
ViewData["Title"] = Localizer["My wishlist"];
|
||||
}
|
||||
|
||||
@section OpenGraph
|
||||
{
|
||||
<meta name="author" content="@SharedLocalizer["Michael 'XFox' Gordeev"]" />
|
||||
<meta name="description" content="@SharedLocalizer["In case you don't know what to give me"]" />
|
||||
|
||||
<meta property="og:type" content="article" />
|
||||
<meta property="og:site_name" content="@SharedLocalizer["Michael 'XFox' Gordeev"]" />
|
||||
<meta property="og:url" content="https://XFox111.NET/Wishlist" />
|
||||
<meta property="og:locale" content="@SharedLocalizer["en"]" />
|
||||
<meta property="og:image" content="https://xfox111.net/images/me.jpg" />
|
||||
<meta property="og:description" content="@SharedLocalizer["In case you don't know what to give me"]" />
|
||||
<meta property="og:title" content="@Localizer["My wishlist"]" />
|
||||
|
||||
<meta property="article:modified_time" content="@(((DateTime?)Model?.Wishlist?.LastUpdated)?.ToString("o"))" />
|
||||
}
|
||||
|
||||
<header>
|
||||
<h1>@Localizer["My wishlist"]</h1>
|
||||
<p>@Localizer["In case you don't know what to give me"]</p>
|
||||
<p>@Localizer["Last update"]: @Model?.Wishlist?.LastUpdated</p>
|
||||
</header>
|
||||
|
||||
<article allow-select>
|
||||
@Html.Raw(Model?.Content)
|
||||
</article>
|
||||
Reference in New Issue
Block a user