This commit is contained in:
Michael 2017-05-18 21:25:20 -04:00
parent cb9e12c980
commit 9b06522c66
7 changed files with 200 additions and 43 deletions

View file

@ -44,6 +44,15 @@ public static IHtmlString NewestUser(this HtmlHelper hpr)
return hpr.Raw("<a href=\"/Profiles/ViewProfile/" + user.DisplayName + "\"><span class=\"glyphicon glyphicon-star\"></span> Our newest user, <strong>" + user.DisplayName + "</strong></a>"); return hpr.Raw("<a href=\"/Profiles/ViewProfile/" + user.DisplayName + "\"><span class=\"glyphicon glyphicon-star\"></span> Our newest user, <strong>" + user.DisplayName + "</strong></a>");
} }
internal static string MarkdownRaw(string md)
{
if (md == null)
return "";
md = ResolveUserLinksInMarkdown(md);
return CommonMark.CommonMarkConverter.Convert(md);
}
public static IHtmlString GetLatestUnread(this HtmlHelper hpr, string userName) public static IHtmlString GetLatestUnread(this HtmlHelper hpr, string userName)
{ {
var db = new ApplicationDbContext(); var db = new ApplicationDbContext();

View file

@ -4,12 +4,58 @@
using System.Net; using System.Net;
using System.Web; using System.Web;
using System.Web.Mvc; using System.Web.Mvc;
using Microsoft.AspNet.Identity;
using Project_Unite.Models; using Project_Unite.Models;
namespace Project_Unite.Controllers namespace Project_Unite.Controllers
{ {
public class HomeController : Controller public class HomeController : Controller
{ {
public ActionResult SendFeedback()
{
var sfm = new SendFeedbackViewModel();
if(Request.IsAuthenticated)
{
var db = new ApplicationDbContext();
var user = db.Users.FirstOrDefault(x => x.UserName == User.Identity.Name);
sfm.Name = (string.IsNullOrWhiteSpace(user.FullName)) ? user.DisplayName : user.FullName;
sfm.Email = user.Email;
}
return View(sfm);
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult SendFeedback(SendFeedbackViewModel model)
{
if (!ModelState.IsValid)
return View(model);
var db = new ApplicationDbContext();
var siteconfig = db.Configs.FirstOrDefault();
var mailsender = new EmailService();
var message = new IdentityMessage
{
Destination = siteconfig.FeedbackEmail,
Subject = "[Feedback] " + model.Name,
Body = $@"<h1>Project: Unite Feedback</h1>
<dl>
<dt>From:</dt>
<dd>{model.Name} [{model.Email}]</dd>
<dt>Type:</dt>
<dd>{model.FeedbackType}</dd>
</dl>
<hr/>
{ACL.MarkdownRaw(model.Body)}"
};
mailsender.SendAsync(message);
return RedirectToAction("Index");
}
public ActionResult AccessDenied() public ActionResult AccessDenied()
{ {
return View(); return View();

View file

@ -75,6 +75,7 @@ public enum AuditLogLevel
public class Configuration public class Configuration
{ {
public string Id { get; set; } public string Id { get; set; }
public string FeedbackEmail { get; set; }
public string SiteName { get; set; } public string SiteName { get; set; }
public string ReturnEmail { get; set; } public string ReturnEmail { get; set; }
public string UniteBotToken { get; set; } public string UniteBotToken { get; set; }

View file

@ -0,0 +1,56 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Web;
using System.Web.Mvc;
namespace Project_Unite.Models
{
public class SendFeedbackViewModel
{
[Required(AllowEmptyStrings = false, ErrorMessage ="You must provide a name so we can address you properly.")]
public string Name { get; set; }
[DataType(DataType.EmailAddress)]
[Required(AllowEmptyStrings = false, ErrorMessage = "You must provide a valid email address so we can reply to your feedback.")]
public string Email { get; set; }
[Required(AllowEmptyStrings = false, ErrorMessage = "Please provide a subject.")]
[MinLength(5, ErrorMessage ="Your subject must be at least 5 characters long.")]
[MaxLength(35, ErrorMessage = "Your subject must be less than 35 characters long.")]
public string Subject { get; set; }
[Required(AllowEmptyStrings =false, ErrorMessage ="Please enter a body for your feedback email.")]
[AllowHtml]
public string Body { get; set; }
public string FeedbackType { get; set; }
public List<SelectListItem> FeedbackTypes
{
get
{
string[] types = new string[]
{
"Feature Request - Website",
"Feature Request - ShiftOS Client",
"Feature Request - API",
"Security and Privacy",
"Discord",
"YouTube Channel",
"Ban Appeals",
"Other"
};
List<SelectListItem> items = new List<SelectListItem>();
foreach (var type in types)
items.Add(new SelectListItem
{
Value = type,
Text = type
});
return items;
}
}
}
}

View file

@ -820,6 +820,7 @@
<Compile Include="Models\PongHighscore.cs" /> <Compile Include="Models\PongHighscore.cs" />
<Compile Include="Models\Role.cs" /> <Compile Include="Models\Role.cs" />
<Compile Include="Models\SearchModels.cs" /> <Compile Include="Models\SearchModels.cs" />
<Compile Include="Models\SendFeedbackViewModel.cs" />
<Compile Include="Models\Skin.cs" /> <Compile Include="Models\Skin.cs" />
<Compile Include="Models\WikiModels.cs" /> <Compile Include="Models\WikiModels.cs" />
<Compile Include="NotificationDaemon.cs" /> <Compile Include="NotificationDaemon.cs" />
@ -963,6 +964,7 @@
<Content Include="Views\Groups\ViewGroup.cshtml" /> <Content Include="Views\Groups\ViewGroup.cshtml" />
<Content Include="Views\Groups\CreateGroup.cshtml" /> <Content Include="Views\Groups\CreateGroup.cshtml" />
<Content Include="Views\Home\AccessDenied.cshtml" /> <Content Include="Views\Home\AccessDenied.cshtml" />
<Content Include="Views\Home\SendFeedback.cshtml" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Folder Include="App_Data\" /> <Folder Include="App_Data\" />

View file

@ -0,0 +1,42 @@
@model Project_Unite.Models.SendFeedbackViewModel
@{
ViewBag.Title = "Send feedback";
}
<h2>Send feedback</h2>
<p>Hey there, Shifter! Michael here. So, you want to get in touch with the ShiftOS team, do ya? Well, just fill out this form!</p>
@using (Html.BeginForm())
{
@Html.AntiForgeryToken()
@Html.ValidationSummary()
<dl>
<dt>Your name:</dt>
<dd>Just in case I need it, can you please enter your name here? @Html.TextBoxFor(x=>x.Name, new{@class="form-control"})</dd>
<dt>Your email:</dt>
<dd>May you please enter your email address so I can reply to you if needed? @Html.TextBoxFor(x => x.Email, new { type="email", @class = "form-control" })</dd>
<dt>Feedback type:</dt>
<dd>@Html.DropDownListFor(x => x.Name, Model.FeedbackTypes, new { @class = "form-control" })</dd>
<dt>Subject:</dt>
<dd>@Html.TextBoxFor(x => x.Subject, new { @class = "form-control" })</dd>
<dt>Body:</dt>
<dd>@Html.TextAreaFor(x => x.Body, new { @class = "form-control" })</dd>
</dl>
<input type="submit" class="btn btn-primary" value="Send" />
}
<h2>Bogus email addresses</h2>
<p>Please note that if you enter a bogus email address, we will completely ignore your feedback. This is because I want to be talking with real people, not spammers. If I can't reach you, I just won't listen to you.</p>
<h2>This is NOT for general communication!</h2>
<p>Please only use this form for feedback/support for ShiftOS. If you want to get in contact with me for other reasons, join our Discord server or email me directly at <a href="mailto:michaelshiftos@gmail.com">this address.</a></p>

View file

@ -1,51 +1,52 @@
@using Microsoft.AspNet.Identity @using Microsoft.AspNet.Identity
<ul class="nav navbar-nav navbar-right" style="margin-right:15px;">
@if (Request.IsAuthenticated) <li><a href="@Url.Action("SendFeedback", "Home")"><span class="glyphicon glyphicon-star"></span> Send feedback</a></li>
{ @if (Request.IsAuthenticated)
using (Html.BeginForm("LogOff", "Account", FormMethod.Post, new { id = "logoutForm", @class = "navbar-right" }))
{ {
@Html.AntiForgeryToken() using (Html.BeginForm("LogOff", "Account", FormMethod.Post, new { id = "logoutForm", @class = "navbar-right" }))
{
@Html.AntiForgeryToken()
<ul class="nav navbar-nav navbar-right" style="margin-right:15px;"> <li><a href="@Url.Action("ViewUnread", "Forum")"><span class="glyphicon glyphicon-star-empty"></span> @ACL.UnreadPostsCount(User.Identity.Name) unread posts</a></li>
<li><a href="@Url.Action("ViewUnread", "Forum")"><span class="glyphicon glyphicon-star-empty"></span> @ACL.UnreadPostsCount(User.Identity.Name) unread posts</a></li> <li id="notification_body" class="dropdown">
<li id="notification_body" class="dropdown"><a href="#" data-toggle="dropdown" class="dropdown-toggle"><span class="glyphicon glyphicon-bullhorn"></span> <strong id="notification_count">@Html.NotificationCount(User.Identity.GetUserId())</strong></a> <a href="#" data-toggle="dropdown" class="dropdown-toggle"><span class="glyphicon glyphicon-bullhorn"></span> <strong id="notification_count">@Html.NotificationCount(User.Identity.GetUserId())</strong></a>
<ul class="dropdown-menu"> <ul class="dropdown-menu">
<li class="dropdown-header">Notifications (@Html.NotificationCount(User.Identity.Name) unread)</li> <li class="dropdown-header">Notifications (@Html.NotificationCount(User.Identity.Name) unread)</li>
@Html.GetLatestUnread(User.Identity.Name) @Html.GetLatestUnread(User.Identity.Name)
<li><a href="@Url.Action("Index", "Manage")#t_notifications">View all</a></li> <li><a href="@Url.Action("Index", "Manage")#t_notifications">View all</a></li>
</ul> </ul>
</li> </li>
<li class="dropdown"><a href="#" data-toggle="dropdown" class="dropdown-toggle"><span class="glyphicon glyphicon-user"></span> @Html.UserName(User.Identity.GetUserId()) <span class="caret"></span></a> <li class="dropdown">
<ul class="dropdown-menu"> <a href="#" data-toggle="dropdown" class="dropdown-toggle"><span class="glyphicon glyphicon-user"></span> @Html.UserName(User.Identity.GetUserId()) <span class="caret"></span></a>
<li><a href="@Url.Action("ViewProfile", "Profiles", new { id = ACL.UserNameRaw(User.Identity.GetUserId()) })"><span class="glyphicon glyphicon-user"></span> Profile</a></li> <ul class="dropdown-menu">
<li class="divider"></li> <li><a href="@Url.Action("ViewProfile", "Profiles", new { id = ACL.UserNameRaw(User.Identity.GetUserId()) })"><span class="glyphicon glyphicon-user"></span> Profile</a></li>
<li class="dropdown-header">Settings</li> <li class="divider"></li>
@if((bool)User.Identity?.IsAdmin()) <li class="dropdown-header">Settings</li>
{ @if ((bool)User.Identity?.IsAdmin())
<li><a href="@Url.Action("Index", "Admin")"><span class="glyphicon glyphicon-cog"></span> Admin CP</a></li> {
} <li><a href="@Url.Action("Index", "Admin")"><span class="glyphicon glyphicon-cog"></span> Admin CP</a></li>
@if ((bool)User.Identity?.IsModerator()) }
{ @if ((bool)User.Identity?.IsModerator())
<li><a href="@Url.Action("Index", "Moderator")"><span class="glyphicon glyphicon-warning-sign"></span> Mod CP</a></li> {
} <li><a href="@Url.Action("Index", "Moderator")"><span class="glyphicon glyphicon-warning-sign"></span> Mod CP</a></li>
@if ((bool)User.Identity?.IsDeveloper()) }
{ @if ((bool)User.Identity?.IsDeveloper())
<li><a href="@Url.Action("Index", "Developer")"><span class="glyphicon glyphicon-star"></span> Developer CP</a></li> {
} <li><a href="@Url.Action("Index", "Developer")"><span class="glyphicon glyphicon-star"></span> Developer CP</a></li>
<li><a href="@Url.Action("Index", "Manage")"><span class="glyphicon glyphicon-adjust"></span> Account</a></li> }
<li class="divider"></li> <li><a href="@Url.Action("Index", "Manage")"><span class="glyphicon glyphicon-adjust"></span> Account</a></li>
<li><a href="javascript:document.getElementById('logoutForm').submit()"><span class="glyphicon glyphicon-log-out"></span> Log off</a></li> <li class="divider"></li>
</ul> <li><a href="javascript:document.getElementById('logoutForm').submit()"><span class="glyphicon glyphicon-log-out"></span> Log off</a></li>
</li> </ul>
</ul> </li>
}
} }
} else
else {
{
<ul class="nav navbar-nav navbar-right" style="margin-right:15px;">
<li>@Html.ActionLink("Register", "Register", "Account", routeValues: null, htmlAttributes: new { id = "registerLink" })</li> <li>@Html.ActionLink("Register", "Register", "Account", routeValues: null, htmlAttributes: new { id = "registerLink" })</li>
<li>@Html.ActionLink("Log in", "Login", "Account", routeValues: null, htmlAttributes: new { id = "loginLink" })</li> <li>@Html.ActionLink("Log in", "Login", "Account", routeValues: null, htmlAttributes: new { id = "loginLink" })</li>
</ul>
} }
</ul>