Added events and projects. Finished the basic community features

This commit is contained in:
Marcel Baumgartner 2023-10-28 22:27:25 +02:00
parent 6d83c31f42
commit c4e7e10f5e
10 changed files with 310 additions and 15 deletions

View file

@ -0,0 +1,16 @@
using System.ComponentModel.DataAnnotations;
namespace Moonlight.App.Models.Forms.Community;
public class AddPostForm
{
[Required(ErrorMessage = "You need to enter a title")]
[MaxLength(40, ErrorMessage = "The title can only be 40 characters long")]
[MinLength(8, ErrorMessage = "The title must at least have 8 characters")]
public string Title { get; set; } = "";
[Required(ErrorMessage = "You need to enter post content")]
[MaxLength(2048, ErrorMessage = "The post content can only be 2048 characters long")]
[MinLength(8, ErrorMessage = "The post content must at least have 8 characters")]
public string Content { get; set; } = "";
}

View file

@ -11,11 +11,11 @@ public class ModalService
JsRuntime = jsRuntime;
}
public async Task Show(string id)
public async Task Show(string id, bool focus = true) // Focus can be specified to fix issues with other components
{
try
{
await JsRuntime.InvokeVoidAsync("moonlight.modals.show", id);
await JsRuntime.InvokeVoidAsync("moonlight.modals.show", id, focus);
}
catch (Exception)
{

View file

@ -8,6 +8,13 @@
<style>
:root {
/*
Fix from https://ckeditor.com/docs/ckeditor5/latest/installation/integrations/css.html
to make the editor work with bootstrap
*/
--ck-z-default: 100;
--ck-z-modal: calc( var(--ck-z-default) + 999 );
/* Overrides the border radius setting in the theme. */
--ck-border-radius: 4px;
@ -111,13 +118,19 @@
}
</style>
<div id="@Id" class="card card-body bg-black" @onfocusout="Callback"></div>
<div id="@Id" class="card card-body bg-black @(CssClasses)" @onfocusout="Callback" style="@(Styles)"></div>
@code
{
[Parameter]
public string InitialContent { get; set; }
[Parameter]
public string CssClasses { get; set; } = "";
[Parameter]
public string Styles { get; set; } = ""; // We added this parameter to allow custom heights to be set
private string Id;
private bool IsInitialized = false;

View file

@ -0,0 +1,64 @@
@using Moonlight.App.Models.Forms.Community
@using Moonlight.App.Services
@using Moonlight.App.Services.Community
@using Moonlight.App.Database.Enums
@inject PostService PostService
@inject IdentityService IdentityService
@inject ToastService ToastService
<SmartModal @ref="Modal" CssClasses="modal-fullscreen">
<div class="modal-header">
<h5 class="modal-title fs-3">Create a new post</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<SmartForm Model="Form" OnValidSubmit="Submit">
<div class="modal-body">
<div class="mb-3">
<label class="form-label">Title</label>
<input @bind="Form.Title" class="form-control form-control-solid-bg"/>
</div>
<div>
<TextEditor @bind-Value="Form.Content" InitialContent="A well written post content from you" Styles="height: 55vh"/>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
<button type="submit" class="btn btn-primary">Save changes</button>
</div>
</SmartForm>
</SmartModal>
@code
{
[Parameter]
public Func<Task>? OnUpdate { get; set; }
[Parameter]
public PostType PostType { get; set; }
private AddPostForm Form = new();
private SmartModal Modal;
public async Task Show()
{
Form = new();
await Modal.Show(false);
}
private async Task Submit()
{
await PostService.Create(
IdentityService.CurrentUser,
Form.Title,
Form.Content,
PostType
);
await Modal.Hide();
await ToastService.Success("Successfully created post");
if (OnUpdate != null)
await OnUpdate.Invoke();
}
}

View file

@ -0,0 +1,41 @@
<div class="card">
<div class="card-header border-0 pt-5">
<h3 class="card-title align-items-start flex-column">
<span class="card-label fw-bold text-gray-900">Post channels</span>
</h3>
</div>
<div class="card-body pt-5">
<div class="d-flex flex-stack">
<div class="symbol symbol-40px me-5">
<i class="bx bx-sm bx-envelope text-gray-500"></i>
</div>
<div class="d-flex align-items-center flex-row-fluid flex-wrap">
<a href="/community" class="text-gray-800 fs-5 fw-bold text-active-primary @(Index == 0 ? "active" : "")">Announcements</a>
</div>
</div>
<div class="separator separator-dashed my-4"></div>
<div class="d-flex flex-stack">
<div class="symbol symbol-40px me-5">
<i class="bx bx-sm bx-calendar-event text-gray-500"></i>
</div>
<div class="d-flex align-items-center flex-row-fluid flex-wrap">
<a href="/community/events" class="text-gray-800 fs-5 fw-bold text-active-primary @(Index == 1 ? "active" : "")">Events</a>
</div>
</div>
<div class="separator separator-dashed my-4"></div>
<div class="d-flex flex-stack">
<div class="symbol symbol-40px me-5">
<i class="bx bx-sm bxs-inbox text-gray-500"></i>
</div>
<div class="d-flex align-items-center flex-row-fluid flex-wrap">
<a href="/community/projects" class="text-gray-800 fs-5 fw-bold text-active-primary @(Index == 2 ? "active" : "")">Projects</a>
</div>
</div>
</div>
</div>
@code
{
[Parameter]
public int Index { get; set; }
}

View file

@ -27,12 +27,12 @@
Id = GetHashCode();
}
public async Task Show()
public async Task Show(bool focus = true) // Focus can be specified to fix issues with other components
{
ShouldShow = true;
await InvokeAsync(StateHasChanged);
await ModalService.Show("modal" + Id);
await ModalService.Show("modal" + Id, focus);
}
public async Task Hide()

View file

@ -0,0 +1,67 @@
@page "/community/events"
@using Moonlight.App.Repositories
@using Moonlight.App.Database.Entities.Community
@using Microsoft.EntityFrameworkCore
@using Moonlight.App.Database.Enums
@using Moonlight.App.Models.Enums
@using Moonlight.App.Services
@using Moonlight.Shared.Components.Community
@using Moonlight.Shared.Components.Modals.Community
@inject IdentityService IdentityService
@inject Repository<Post> PostRepository
<div class="row">
<div class="col-md-2 col-12 mb-5">
<CommunityNavigation Index="1" />
@if (IdentityService.Permissions[Permission.AdminCommunity])
{
<div class="card card-body mt-5">
<button @onclick="() => CreateModal.Show()" class="btn btn-success">Create new post</button>
</div>
}
</div>
<div class="col-md-10 col-12">
<div class="card border-primary">
<div class="card-body fs-5">
Planned events and current happenings can be found here.
If you want to know what will happen in the future or is going on now have a look at the posts below
</div>
</div>
<div class="row mt-3">
<LazyLoader @ref="LazyLoader" Load="Load">
@foreach (var post in Posts)
{
<PostView Post="post" OnUpdate="() => LazyLoader.Reload()"/>
<div class="mb-10"></div>
}
</LazyLoader>
</div>
</div>
</div>
@if (IdentityService.Permissions[Permission.AdminCommunity])
{
<CreatePostModal @ref="CreateModal" OnUpdate="() => LazyLoader.Reload()" PostType="PostType.Event" />
}
@code
{
private LazyLoader LazyLoader;
private CreatePostModal CreateModal;
private Post[] Posts;
private Task Load(LazyLoader _)
{
Posts = PostRepository
.Get()
.Include(x => x.Author)
.Where(x => x.Type == PostType.Event)
.ToArray();
return Task.CompletedTask;
}
}

View file

@ -3,23 +3,54 @@
@using Moonlight.App.Repositories
@using Moonlight.App.Database.Entities.Community
@using Microsoft.EntityFrameworkCore
@using Moonlight.App.Database.Enums
@using Moonlight.App.Models.Enums
@using Moonlight.App.Services
@using Moonlight.Shared.Components.Community
@using Moonlight.Shared.Components.Modals.Community
@inject Repository<Post> PostRepository
@inject IdentityService IdentityService
<div class="row">
<LazyLoader @ref="LazyLoader" Load="Load">
@foreach (var post in Posts)
<div class="col-md-2 col-12 mb-5">
<CommunityNavigation Index="0"/>
@if (IdentityService.Permissions[Permission.AdminCommunity])
{
<PostView Post="post" OnUpdate="() => LazyLoader.Reload()" />
<div class="mb-10"></div>
<div class="card card-body mt-5">
<button @onclick="() => CreateModal.Show()" class="btn btn-success">Create new post</button>
</div>
}
</LazyLoader>
</div>
<div class="col-md-10 col-12">
<div class="card border-primary mb-5">
<div class="card-body fs-5">
These announcements provide you with the latest news and information.
The posts here have been created by an admin and can contain valuable information
so consider reading it from time to time
</div>
</div>
<LazyLoader @ref="LazyLoader" Load="Load">
@foreach (var post in Posts)
{
<PostView Post="post" OnUpdate="() => LazyLoader.Reload()"/>
<div class="mb-10"></div>
}
</LazyLoader>
</div>
</div>
@if (IdentityService.Permissions[Permission.AdminCommunity])
{
<CreatePostModal @ref="CreateModal" OnUpdate="() => LazyLoader.Reload()" PostType="PostType.Announcement"/>
}
@code
{
private LazyLoader LazyLoader;
private CreatePostModal CreateModal;
private Post[] Posts;
private Task Load(LazyLoader _)
@ -27,6 +58,7 @@
Posts = PostRepository
.Get()
.Include(x => x.Author)
.Where(x => x.Type == PostType.Announcement)
.ToArray();
return Task.CompletedTask;

View file

@ -0,0 +1,59 @@
@page "/community/projects"
@using Moonlight.App.Repositories
@using Moonlight.App.Database.Entities.Community
@using Microsoft.EntityFrameworkCore
@using Moonlight.App.Database.Enums
@using Moonlight.Shared.Components.Community
@using Moonlight.Shared.Components.Modals.Community
@inject Repository<Post> PostRepository
<div class="row">
<div class="col-md-2 col-12 mb-5">
<CommunityNavigation Index="2" />
<div class="card card-body mt-5">
<button @onclick="() => CreateModal.Show()" class="btn btn-success">Create new post</button>
</div>
</div>
<div class="col-md-10 col-12">
<div class="card border-primary">
<div class="card-body fs-5">
You have a interesting project or a fun game server you want to share with the community?
You can share it here. Please keep in mind to follow basic rules and dont offend anyone.
Be nice and respectful
</div>
</div>
<div class="row mt-3">
<LazyLoader @ref="LazyLoader" Load="Load">
@foreach (var post in Posts)
{
<PostView Post="post" OnUpdate="() => LazyLoader.Reload()"/>
<div class="mb-10"></div>
}
</LazyLoader>
</div>
</div>
</div>
<CreatePostModal @ref="CreateModal" OnUpdate="() => LazyLoader.Reload()" PostType="PostType.Event" />
@code
{
private LazyLoader LazyLoader;
private CreatePostModal CreateModal;
private Post[] Posts;
private Task Load(LazyLoader _)
{
Posts = PostRepository
.Get()
.Include(x => x.Author)
.Where(x => x.Type == PostType.Project)
.ToArray();
return Task.CompletedTask;
}
}

View file

@ -23,9 +23,12 @@ window.moonlight = {
}
},
modals: {
show: function (id)
show: function (id, focus)
{
let modal = new bootstrap.Modal(document.getElementById(id));
let modal = new bootstrap.Modal(document.getElementById(id), {
focus: focus
});
modal.show();
},
hide: function (id)