Added events and projects. Finished the basic community features
This commit is contained in:
16
Moonlight/App/Models/Forms/Community/AddPostForm.cs
Normal file
16
Moonlight/App/Models/Forms/Community/AddPostForm.cs
Normal 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; } = "";
|
||||||
|
}
|
||||||
@@ -11,11 +11,11 @@ public class ModalService
|
|||||||
JsRuntime = jsRuntime;
|
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
|
try
|
||||||
{
|
{
|
||||||
await JsRuntime.InvokeVoidAsync("moonlight.modals.show", id);
|
await JsRuntime.InvokeVoidAsync("moonlight.modals.show", id, focus);
|
||||||
}
|
}
|
||||||
catch (Exception)
|
catch (Exception)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -8,6 +8,13 @@
|
|||||||
|
|
||||||
<style>
|
<style>
|
||||||
:root {
|
: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. */
|
/* Overrides the border radius setting in the theme. */
|
||||||
--ck-border-radius: 4px;
|
--ck-border-radius: 4px;
|
||||||
|
|
||||||
@@ -111,13 +118,19 @@
|
|||||||
}
|
}
|
||||||
</style>
|
</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
|
@code
|
||||||
{
|
{
|
||||||
[Parameter]
|
[Parameter]
|
||||||
public string InitialContent { get; set; }
|
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 string Id;
|
||||||
private bool IsInitialized = false;
|
private bool IsInitialized = false;
|
||||||
|
|
||||||
|
|||||||
@@ -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();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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; }
|
||||||
|
}
|
||||||
@@ -27,12 +27,12 @@
|
|||||||
Id = GetHashCode();
|
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;
|
ShouldShow = true;
|
||||||
await InvokeAsync(StateHasChanged);
|
await InvokeAsync(StateHasChanged);
|
||||||
|
|
||||||
await ModalService.Show("modal" + Id);
|
await ModalService.Show("modal" + Id, focus);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task Hide()
|
public async Task Hide()
|
||||||
|
|||||||
67
Moonlight/Shared/Views/Community/Events.razor
Normal file
67
Moonlight/Shared/Views/Community/Events.razor
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -3,23 +3,54 @@
|
|||||||
@using Moonlight.App.Repositories
|
@using Moonlight.App.Repositories
|
||||||
@using Moonlight.App.Database.Entities.Community
|
@using Moonlight.App.Database.Entities.Community
|
||||||
@using Microsoft.EntityFrameworkCore
|
@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.Community
|
||||||
|
@using Moonlight.Shared.Components.Modals.Community
|
||||||
|
|
||||||
@inject Repository<Post> PostRepository
|
@inject Repository<Post> PostRepository
|
||||||
|
@inject IdentityService IdentityService
|
||||||
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
|
<div class="col-md-2 col-12 mb-5">
|
||||||
|
<CommunityNavigation Index="0"/>
|
||||||
|
|
||||||
|
@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 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">
|
<LazyLoader @ref="LazyLoader" Load="Load">
|
||||||
@foreach (var post in Posts)
|
@foreach (var post in Posts)
|
||||||
{
|
{
|
||||||
<PostView Post="post" OnUpdate="() => LazyLoader.Reload()" />
|
<PostView Post="post" OnUpdate="() => LazyLoader.Reload()"/>
|
||||||
<div class="mb-10"></div>
|
<div class="mb-10"></div>
|
||||||
}
|
}
|
||||||
</LazyLoader>
|
</LazyLoader>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@if (IdentityService.Permissions[Permission.AdminCommunity])
|
||||||
|
{
|
||||||
|
<CreatePostModal @ref="CreateModal" OnUpdate="() => LazyLoader.Reload()" PostType="PostType.Announcement"/>
|
||||||
|
}
|
||||||
|
|
||||||
@code
|
@code
|
||||||
{
|
{
|
||||||
private LazyLoader LazyLoader;
|
private LazyLoader LazyLoader;
|
||||||
|
private CreatePostModal CreateModal;
|
||||||
private Post[] Posts;
|
private Post[] Posts;
|
||||||
|
|
||||||
private Task Load(LazyLoader _)
|
private Task Load(LazyLoader _)
|
||||||
@@ -27,6 +58,7 @@
|
|||||||
Posts = PostRepository
|
Posts = PostRepository
|
||||||
.Get()
|
.Get()
|
||||||
.Include(x => x.Author)
|
.Include(x => x.Author)
|
||||||
|
.Where(x => x.Type == PostType.Announcement)
|
||||||
.ToArray();
|
.ToArray();
|
||||||
|
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
|
|||||||
59
Moonlight/Shared/Views/Community/Projects.razor
Normal file
59
Moonlight/Shared/Views/Community/Projects.razor
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
7
Moonlight/wwwroot/js/moonlight.js
vendored
7
Moonlight/wwwroot/js/moonlight.js
vendored
@@ -23,9 +23,12 @@ window.moonlight = {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
modals: {
|
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();
|
modal.show();
|
||||||
},
|
},
|
||||||
hide: function (id)
|
hide: function (id)
|
||||||
|
|||||||
Reference in New Issue
Block a user