Skip to content

Commit

Permalink
Dashboard improvements.
Browse files Browse the repository at this point in the history
  • Loading branch information
impworks committed Mar 19, 2020
1 parent ebbd218 commit 6105747
Show file tree
Hide file tree
Showing 9 changed files with 202 additions and 53 deletions.
53 changes: 42 additions & 11 deletions src/Bonsai/Areas/Admin/Logic/DashboardPresenterService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,13 @@
using System.Linq;
using System.Threading.Tasks;
using AutoMapper;
using Bonsai.Areas.Admin.ViewModels.Common;
using Bonsai.Areas.Admin.ViewModels.Dashboard;
using Bonsai.Areas.Admin.ViewModels.Users;
using Bonsai.Areas.Front.Logic;
using Bonsai.Areas.Front.ViewModels.Media;
using Bonsai.Code.DomainModel.Media;
using Bonsai.Code.Utils.Date;
using Bonsai.Code.Utils.Helpers;
using Bonsai.Data;
using Bonsai.Data.Models;
Expand Down Expand Up @@ -68,31 +73,57 @@ public async IAsyncEnumerable<ChangesetEventVM> GetEventsAsync(int page = 0)
.AsNoTracking()
.Include(x => x.EditedMedia)
.Include(x => x.EditedPage)
.Include(x => x.EditedRelation)
.Include(x => x.EditedRelation.Destination)
.Include(x => x.EditedRelation.Source)
.Include(x => x.Author)
.Where(x => changeIds.Contains(x.Id))
.ToDictionaryAsync(x => x.Id, x => x);

foreach (var group in parsedGroups)
{
var firstChange = changes[group.Ids.First()];
var vm = _mapper.Map<ChangesetEventVM>(firstChange);

if (firstChange.Type == ChangesetEntityType.Page)
var chg = changes[group.Ids.First()];
var vm = _mapper.Map<ChangesetEventVM>(chg);
if (chg.Type == ChangesetEntityType.Page)
{
vm.Title = firstChange.EditedPage.Title;
vm.Url = _url.Action("Description", "Page", new {area = "Front", key = firstChange.EditedPage.Key});
vm.MainLink = GetLinkToPage(chg.EditedPage);
}
else if (firstChange.Type == ChangesetEntityType.Relation)
else if (chg.Type == ChangesetEntityType.Relation)
{
vm.Title = "связь " + firstChange.EditedRelation.Type.GetEnumDescription();
var rel = chg.EditedRelation;
vm.MainLink = new LinkVM
{
Title = chg.EditedRelation.Type.GetEnumDescription(),
Url = _url.Action("Update", "Relations", new { area = "Admin", id = rel.Id })
};
vm.ExtraLinks = new[] {GetLinkToPage(rel.Destination), GetLinkToPage(rel.Source)};
}
else if (firstChange.Type == ChangesetEntityType.Media)
else if (chg.Type == ChangesetEntityType.Media)
{
vm.MediaThumbnails = group.Ids.Select(x => _mapper.Map<MediaThumbnailVM>(changes[x].EditedMedia)).ToList();
vm.MediaThumbnails = group.Ids
.Select(x => changes[x].EditedMedia)
.Select(x => new MediaThumbnailVM
{
Key = x.Key,
Type = x.Type,
ThumbnailUrl = MediaPresenterService.GetSizedMediaPath(x.FilePath, MediaSize.Small),
})
.ToList();
}

yield return vm;
}
}

/// <summary>
/// Builds a link to the page.
/// </summary>
private LinkVM GetLinkToPage(Page page)
{
return new LinkVM
{
Title = page.Title,
Url = _url.Action("Description", "Page", new {area = "Front", key = page.Key})
};
}
}
}
18 changes: 18 additions & 0 deletions src/Bonsai/Areas/Admin/ViewModels/Common/LinkVM.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
namespace Bonsai.Areas.Admin.ViewModels.Common
{
/// <summary>
/// Info about a single link used somewhere in a message.
/// </summary>
public class LinkVM
{
/// <summary>
/// Displayed title.
/// </summary>
public string Title { get; set; }

/// <summary>
/// URL of the link.
/// </summary>
public string Url { get; set; }
}
}
21 changes: 11 additions & 10 deletions src/Bonsai/Areas/Admin/ViewModels/Dashboard/ChangesetEventVM.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using System.Collections.Generic;
using AutoMapper;
using Bonsai.Areas.Admin.ViewModels.Changesets;
using Bonsai.Areas.Admin.ViewModels.Common;
using Bonsai.Areas.Admin.ViewModels.Users;
using Bonsai.Areas.Front.ViewModels.Media;
using Bonsai.Code.Infrastructure;
Expand Down Expand Up @@ -31,24 +32,24 @@ public class ChangesetEventVM: IMapped
public ChangesetType ChangeType { get; set; }

/// <summary>
/// Changed element title.
/// Thumbnails for media.
/// </summary>
public string Title { get; set; }
public IReadOnlyList<MediaThumbnailVM> MediaThumbnails { get; set; }

/// <summary>
/// URL for page/relation filter.
/// Author of the change.
/// </summary>
public string Url { get; set; }
public UserTitleVM User { get; set; }

/// <summary>
/// Thumbnails for media.
/// Link to the entity.
/// </summary>
public IReadOnlyList<MediaThumbnailVM> MediaThumbnails { get; set; }
public LinkVM MainLink { get; set; }

/// <summary>
/// Author of the change.
/// Related links.
/// </summary>
public UserTitleVM User { get; set; }
public IReadOnlyList<LinkVM> ExtraLinks { get; set; }

public void Configure(IProfileExpression profile)
{
Expand All @@ -58,8 +59,8 @@ public void Configure(IProfileExpression profile)
.ForMember(x => x.Date, opt => opt.MapFrom(x => x.Date))
.ForMember(x => x.User, opt => opt.MapFrom(x => x.Author))
.Ignore(x => x.MediaThumbnails)
.Ignore(x => x.Title)
.Ignore(x => x.Url);
.Ignore(x => x.MainLink)
.Ignore(x => x.ExtraLinks);

ChangesetType GetChangesetType(Changeset chg)
{
Expand Down
1 change: 1 addition & 0 deletions src/Bonsai/Areas/Admin/ViewModels/Users/UserTitleVM.cs
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ public void Configure(IProfileExpression profile)
{
profile.CreateMap<AppUser, UserTitleVM>()
.ForMember(x => x.Role, opt => opt.Ignore())
.ForMember(x => x.Email, opt => opt.MapFrom(y => y.Email))
.ForMember(x => x.FullName, opt => opt.MapFrom(y => y.FirstName + " " + y.LastName))
.ForMember(x => x.AuthType, opt => opt.MapFrom(x => x.AuthType))
.ForMember(x => x.LockoutEnd, opt => opt.MapFrom(x => x.LockoutEnd));
Expand Down
114 changes: 87 additions & 27 deletions src/Bonsai/Areas/Admin/Views/Dashboard/Index.cshtml
Original file line number Diff line number Diff line change
@@ -1,27 +1,48 @@
@using Bonsai.Areas.Admin.ViewModels.Changesets
@using Bonsai.Code.Utils.Helpers
@using Bonsai.Data.Models
@using Humanizer
@using Impworks.Utils.Format
@using Impworks.Utils.Strings
@model Bonsai.Areas.Admin.ViewModels.Dashboard.DashboardVM
@addTagHelper *, Bonsai
@{
ViewBag.Title = "Панель администрации";
Layout = "~/Areas/Admin/Views/Layout.cshtml";

string GetChangeClass(ChangesetType type)
string GetChangeDescription(ChangesetType type, ChangesetEntityType entity)
{
switch (type)
{
case ChangesetType.Created:
return "plus";
case ChangesetType.Removed:
return "times";
case ChangesetType.Updated:
return "pencil";
case ChangesetType.Restored:
return "undo";
default:
return "";
}
return entity == ChangesetEntityType.Media
? type switch
{
ChangesetType.Created => "Загружен",
ChangesetType.Removed => "Удален",
ChangesetType.Updated => "Обновлен",
ChangesetType.Restored => "Восстановлен"
}
: type switch
{
ChangesetType.Created => "Создана",
ChangesetType.Removed => "Удалена",
ChangesetType.Updated => "Обновлена",
ChangesetType.Restored => "Восстановлена"
};
}

string GetEntityName(ChangesetEntityType entity) => entity switch
{
ChangesetEntityType.Page => "cтраница",
ChangesetEntityType.Media => "медиа-файл",
ChangesetEntityType.Relation => "связь"
};

string GetChangeClass(ChangesetType type) => type switch
{
ChangesetType.Created => "plus",
ChangesetType.Removed => "times",
ChangesetType.Updated => "pencil",
ChangesetType.Restored => "undo"
};
}

<div class="dashboard-cards">
Expand Down Expand Up @@ -70,22 +91,61 @@
<div class="dashboard-events">
@if (Model.Events?.Count > 0)
{
<ul class="list-unstyled">
<div>
@foreach (var evt in Model.Events)
{
<li>
<span class="fa fa-@(GetChangeClass(evt.ChangeType))"></span>
@if (evt.Url != null)
{
<span><a href="@evt.Url">@evt.Title</a></span>
}
else
{
<span>@evt.Title</span>
}
</li>
<div class="media dashboard-event">
<img src="@ViewHelper.GetGravatarUrl(evt.User.Email)" class="dashboard-event-image" title="@evt.User.FullName" />
<div class="media-body">
<h5 class="dashboard-event-header" title="@evt.Date.LocalDateTime.ToInvariantString()">@evt.Date.Humanize().Capitalize()</h5>
@if (evt.ChangeType == ChangesetType.Created && evt.EntityType == ChangesetEntityType.Media)
{
<span>
@(evt.MediaThumbnails.Count == 1 ? "Загружен" : "Загружено") @evt.MediaThumbnails.Count.DisplayNumeric("медиа-файл", "медиа-файла", "медиа-файлов"):
</span>
}
else
{
<span>
@GetChangeDescription(evt.ChangeType, evt.EntityType)
@GetEntityName(evt.EntityType)
</span>
@if (!string.IsNullOrEmpty(evt.MainLink.Url))
{
<a href="@evt.MainLink.Url">@evt.MainLink.Title</a>
}
else
{
<span>@evt.MainLink.Title</span>
}
@if (evt.EntityType == ChangesetEntityType.Relation && evt.ExtraLinks != null)
{
<span>
между страницами: <a href="@evt.ExtraLinks[0].Url">@evt.ExtraLinks[0].Title</a> и <a href="@evt.ExtraLinks[1].Url">@evt.ExtraLinks[1].Title</a>
</span>
}
<text>.</text>
}

@if (evt.MediaThumbnails?.Count > 0)
{
<ul class="list-inline dashboard-event-media">
@foreach (var elem in evt.MediaThumbnails)
{
<li class="list-inline-item">
<div class="media-thumb-wrapper">
<a href="@Url.Action("ViewMedia", "Media", new {key = elem.Key})" class="media-thumb-link" data-media="@elem.Key">
<div class="media-thumb-square" style="background-image: url('@Url.Content(elem.ThumbnailUrl)')"></div>
</a>
</div>
</li>
}
</ul>
}
</div>
</div>
}
</ul>
</div>
}
else
{
Expand Down
37 changes: 37 additions & 0 deletions src/Bonsai/Areas/Common/Styles/Components/admin/dashboard.scss
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,40 @@
}
}
}

.dashboard-events {
.dashboard-event {
margin-bottom: 1rem;

.dashboard-event-image {
width: 64px;
height: 64px;
margin-right: 0.75rem;
}

.dashboard-event-header {
padding-top: 0;
margin-top: -2px;
margin-bottom: 0.25rem;
}

.dashboard-event-media {
margin-top: -0.5rem;
margin-bottom: 0;

.list-inline-item {
margin-right: 0.25rem;
}

.media-thumb-wrapper {
width: unset;
padding: 5px;

.media-thumb-square {
width: 64px;
height: 64px;
}
}
}
}
}
2 changes: 1 addition & 1 deletion src/Bonsai/Areas/Front/Logic/Auth/AuthService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ public async Task<UserVM> GetCurrentUserAsync(ClaimsPrincipal principal)
return new UserVM
{
Name = user.FirstName + " " + user.LastName,
Avatar = ViewHelper.GetGravatarUrl(user.Email),
Email = user.Email,
PageKey = user.Page?.Key,
IsAdministrator = isAdmin,
IsValidated = user.IsValidated
Expand Down
4 changes: 2 additions & 2 deletions src/Bonsai/Areas/Front/ViewModels/Auth/UserVM.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@ public class UserVM
public string Name { get; set; }

/// <summary>
/// URL to the avatar.
/// User's registered email.
/// </summary>
public string Avatar { get; set; }
public string Email { get; set; }

/// <summary>
/// Flag indicating that this user has access to admin panel.
Expand Down
5 changes: 3 additions & 2 deletions src/Bonsai/Areas/Front/Views/Components/UserHeader.cshtml
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
@model Bonsai.Areas.Front.ViewModels.Auth.UserVM
@using Bonsai.Code.Utils.Helpers
@model Bonsai.Areas.Front.ViewModels.Auth.UserVM
<div class="account">
<div class="row align-items-center">
@if (Model != null)
{
<div class="col">
<span class="user-popover-toggle user-image">
<img src="@Model.Avatar" />
<img src="@ViewHelper.GetGravatarUrl(Model.Email)" />
</span>
</div>
<div class="col">
Expand Down

0 comments on commit 6105747

Please sign in to comment.