Now Page Markdown Editor
This commit is contained in:
parent
295ea4834e
commit
57885b4c5e
12 changed files with 284 additions and 9 deletions
52
Components/Pages/EditNow.razor
Normal file
52
Components/Pages/EditNow.razor
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
@page "/editNow"
|
||||||
|
@inject NavigationManager Nav
|
||||||
|
@inject RestService api
|
||||||
|
@inject State State
|
||||||
|
|
||||||
|
|
||||||
|
<div class="max markdown-editor">
|
||||||
|
<MarkdownEditor @ref="Editor"
|
||||||
|
@bind-Value="@markdownValue"
|
||||||
|
Theme="material-darker"
|
||||||
|
MaxHeight="100%"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<nav>
|
||||||
|
<label class="checkbox">
|
||||||
|
<InputCheckbox @bind-Value="listed"></InputCheckbox>
|
||||||
|
<span>Include my page in the Now Garden</span>
|
||||||
|
</label>
|
||||||
|
<div class="max"></div>
|
||||||
|
<button class="transparent link" onclick="history.back();">Cancel</button>
|
||||||
|
<button @onclick="Save">
|
||||||
|
<i class="fa-solid fa-floppy-disk"></i> <span>Save</span>
|
||||||
|
</button>
|
||||||
|
</nav>
|
||||||
|
|
||||||
|
@code {
|
||||||
|
MarkdownEditor Editor;
|
||||||
|
bool listed;
|
||||||
|
string markdownValue;
|
||||||
|
string markdownHtml;
|
||||||
|
|
||||||
|
protected override async Task OnInitializedAsync() {
|
||||||
|
await base.OnInitializedAsync();
|
||||||
|
NowContentData? data = await api.GetNowPage(State.SelectedAddressName);
|
||||||
|
if (data != null)
|
||||||
|
{
|
||||||
|
listed = data.Listed == 1;
|
||||||
|
markdownValue = data.Content;
|
||||||
|
await Editor.SetValueAsync(markdownValue);
|
||||||
|
}
|
||||||
|
InvokeAsync(StateHasChanged);
|
||||||
|
}
|
||||||
|
|
||||||
|
Task OnMarkdownValueChanged(string value) {
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task Save() {
|
||||||
|
await api.PostNowPage(State.SelectedAddressName, markdownValue, listed);
|
||||||
|
}
|
||||||
|
}
|
|
@ -27,7 +27,7 @@
|
||||||
<i class="fa-solid fa-images"></i>
|
<i class="fa-solid fa-images"></i>
|
||||||
<span>Some.pics</span>
|
<span>Some.pics</span>
|
||||||
</a>
|
</a>
|
||||||
@if(now != null){
|
@if(now != null || IsMe){
|
||||||
<a data-ui="#now" @onclick="ReloadNow">
|
<a data-ui="#now" @onclick="ReloadNow">
|
||||||
<i class="fa-duotone fa-seedling"></i>
|
<i class="fa-duotone fa-seedling"></i>
|
||||||
<span>/Now</span>
|
<span>/Now</span>
|
||||||
|
@ -73,10 +73,16 @@
|
||||||
<NewPicDialog id="post-modal"></NewPicDialog>
|
<NewPicDialog id="post-modal"></NewPicDialog>
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
@if(now != null){
|
@if(now != null || IsMe){
|
||||||
<div id="now" class="page no-padding">
|
<div id="now" class="page no-padding">
|
||||||
<a href="@now.Url" target="_blank" class="hover absolute top right chip fill large-elevate">Open in browser <i class="fa-solid fa-arrow-up-right-from-square tiny"></i></a>
|
<a href="@NowPageUrl" target="_blank" class="hover absolute top right chip fill large-elevate">Open in browser <i class="fa-solid fa-arrow-up-right-from-square tiny"></i></a>
|
||||||
<ExternalPageComponent id="now_page" @ref="NowPage" Url="@now.Url"></ExternalPageComponent>
|
<ExternalPageComponent id="now_page" @ref="NowPage" Url="@NowPageUrl"></ExternalPageComponent>
|
||||||
|
@if (IsMe) {
|
||||||
|
<a href="/editNow" class="button fab circle extra large-elevate center-align middle-align">
|
||||||
|
<i class="square fa-solid fa-file-pen" style="line-height:56px;"></i>
|
||||||
|
<span>Edit</span>
|
||||||
|
</a>
|
||||||
|
}
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
|
@ -96,6 +102,10 @@
|
||||||
get => $"https://{Address}.omg.lol/";
|
get => $"https://{Address}.omg.lol/";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public string NowPageUrl {
|
||||||
|
get => now?.Url ?? $"https://{Address}.omg.lol/now";
|
||||||
|
}
|
||||||
|
|
||||||
public ExternalPageComponent? NowPage { get; set; }
|
public ExternalPageComponent? NowPage { get; set; }
|
||||||
public ExternalPageComponent? ProfilePage { get; set; }
|
public ExternalPageComponent? ProfilePage { get; set; }
|
||||||
|
|
||||||
|
|
|
@ -12,3 +12,5 @@
|
||||||
@using Neighbourhood.omg.lol.Components
|
@using Neighbourhood.omg.lol.Components
|
||||||
@using Neighbourhood.omg.lol.Models
|
@using Neighbourhood.omg.lol.Models
|
||||||
@using Markdig
|
@using Markdig
|
||||||
|
@using PSC.Blazor.Components.MarkdownEditor
|
||||||
|
@using PSC.Blazor.Components.MarkdownEditor.EventsArgs
|
||||||
|
|
|
@ -5,7 +5,7 @@ using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace Neighbourhood.omg.lol.Models {
|
namespace Neighbourhood.omg.lol.Models {
|
||||||
public class DeleteResponseData : IOmgLolResponseData {
|
public class BasicResponseData : IOmgLolResponseData {
|
||||||
public string Message { get; set; }
|
public string Message { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
15
Models/NowContentData.cs
Normal file
15
Models/NowContentData.cs
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Neighbourhood.omg.lol.Models {
|
||||||
|
public class NowContentData {
|
||||||
|
public string? Content { get; set; }
|
||||||
|
public long? Updated { get; set; }
|
||||||
|
public int? Listed { get; set; }
|
||||||
|
public int? Nudge { get; set; }
|
||||||
|
public string? Metadata { get; set; }
|
||||||
|
}
|
||||||
|
}
|
12
Models/NowPageResponseData.cs
Normal file
12
Models/NowPageResponseData.cs
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Neighbourhood.omg.lol.Models {
|
||||||
|
public class NowPageResponseData : IOmgLolResponseData {
|
||||||
|
public string Message { get; set; }
|
||||||
|
public NowContentData Now { get; set; }
|
||||||
|
}
|
||||||
|
}
|
|
@ -207,6 +207,7 @@
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Components.WebView.Maui" Version="$(MauiVersion)" />
|
<PackageReference Include="Microsoft.AspNetCore.Components.WebView.Maui" Version="$(MauiVersion)" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="8.0.0" />
|
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="8.0.0" />
|
||||||
<PackageReference Include="Microsoft.Maui.Essentials" Version="8.0.40" />
|
<PackageReference Include="Microsoft.Maui.Essentials" Version="8.0.40" />
|
||||||
|
<PackageReference Include="PSC.Blazor.Components.MarkdownEditor" Version="8.0.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|
|
@ -195,15 +195,15 @@ namespace Neighbourhood.omg.lol {
|
||||||
|
|
||||||
public async Task<PutPicResponseData?> PostPicDescription(string address, string id, string description) =>
|
public async Task<PutPicResponseData?> PostPicDescription(string address, string id, string description) =>
|
||||||
(await Post<PutPicResponseData, PostPic>($"/address/{address}/pics/{id}", new PostPic { Description = description }));
|
(await Post<PutPicResponseData, PostPic>($"/address/{address}/pics/{id}", new PostPic { Description = description }));
|
||||||
public async Task<DeleteResponseData?> DeletePic(string address, string id) =>
|
public async Task<BasicResponseData?> DeletePic(string address, string id) =>
|
||||||
(await Delete<DeleteResponseData>($"/address/{address}/pics/{id}"));
|
(await Delete<BasicResponseData>($"/address/{address}/pics/{id}"));
|
||||||
|
|
||||||
|
|
||||||
public async Task<PatchStatusResponseData?> PatchStatus(string address, string id, string content, string? emoji) =>
|
public async Task<PatchStatusResponseData?> PatchStatus(string address, string id, string content, string? emoji) =>
|
||||||
(await Patch<PatchStatusResponseData, PatchStatus>($"/address/{address}/statuses/", new PatchStatus { Id = id, Content = content, Emoji = emoji }));
|
(await Patch<PatchStatusResponseData, PatchStatus>($"/address/{address}/statuses/", new PatchStatus { Id = id, Content = content, Emoji = emoji }));
|
||||||
|
|
||||||
public async Task<DeleteResponseData?> DeleteStatus(string address, string id) =>
|
public async Task<BasicResponseData?> DeleteStatus(string address, string id) =>
|
||||||
(await Delete<DeleteResponseData>($"/address/{address}/statuses/{id}"));
|
(await Delete<BasicResponseData>($"/address/{address}/statuses/{id}"));
|
||||||
|
|
||||||
public async Task<List<NowData>?> NowGarden() =>
|
public async Task<List<NowData>?> NowGarden() =>
|
||||||
(await Get<NowResponseData>($"/now/garden"))?.Garden ?? new List<NowData>();
|
(await Get<NowResponseData>($"/now/garden"))?.Garden ?? new List<NowData>();
|
||||||
|
@ -211,6 +211,12 @@ namespace Neighbourhood.omg.lol {
|
||||||
public async Task<List<string>?> Directory() =>
|
public async Task<List<string>?> Directory() =>
|
||||||
(await Get<DirectoryResponseData>($"/directory"))?.Directory ?? new List<string>();
|
(await Get<DirectoryResponseData>($"/directory"))?.Directory ?? new List<string>();
|
||||||
|
|
||||||
|
public async Task<NowContentData?> GetNowPage(string address) =>
|
||||||
|
(await Get<NowPageResponseData>($"/address/{address}/now"))?.Now;
|
||||||
|
|
||||||
|
public async Task<BasicResponseData?> PostNowPage(string address, string content, bool listed) =>
|
||||||
|
await Post<BasicResponseData, NowContentData>($"/address/{address}/now", new NowContentData { Content = content, Listed = listed ? 1 : 0 });
|
||||||
|
|
||||||
public async Task<List<MarkupString>> Ephemeral() {
|
public async Task<List<MarkupString>> Ephemeral() {
|
||||||
List<string> notes = new List<string>();
|
List<string> notes = new List<string>();
|
||||||
Uri Uri = new Uri($"https://eph.emer.al/");
|
Uri Uri = new Uri($"https://eph.emer.al/");
|
||||||
|
|
|
@ -417,3 +417,38 @@ article#directory ul{
|
||||||
#directoryIndex a {
|
#directoryIndex a {
|
||||||
font-size: 1.5rem;
|
font-size: 1.5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.editor-toolbar .easymde-dropdown, .editor-toolbar button {
|
||||||
|
color: inherit;
|
||||||
|
}
|
||||||
|
.editor-toolbar i.separator {
|
||||||
|
---size: unset;
|
||||||
|
opacity: 0.25;
|
||||||
|
border-radius: 0
|
||||||
|
}
|
||||||
|
.markdown-editor .editor-preview {
|
||||||
|
background: var(--surface);
|
||||||
|
}
|
||||||
|
|
||||||
|
.markdown-editor {
|
||||||
|
flex: auto;
|
||||||
|
display: flex;
|
||||||
|
flex-direction:column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.markdown-editor + nav {
|
||||||
|
flex: none;
|
||||||
|
}
|
||||||
|
.markdown-editor > .EasyMDEContainer {
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.markdown-editor > .EasyMDEContainer > .editor-toolbar{
|
||||||
|
flex: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.markdown-editor > .EasyMDEContainer > .CodeMirror {
|
||||||
|
flex: auto;
|
||||||
|
}
|
|
@ -10,9 +10,14 @@
|
||||||
<link rel="stylesheet" href="css/app.css" />
|
<link rel="stylesheet" href="css/app.css" />
|
||||||
<link rel="stylesheet" href="css/style.css" />
|
<link rel="stylesheet" href="css/style.css" />
|
||||||
<link rel="stylesheet" href="Neighbourhood.omg.lol.styles.css" />
|
<link rel="stylesheet" href="Neighbourhood.omg.lol.styles.css" />
|
||||||
|
<script src="vendor/jquery-3.7.1.min.js"></script>
|
||||||
<script type="module" src="vendor/beer.min.js"></script>
|
<script type="module" src="vendor/beer.min.js"></script>
|
||||||
<script type="module" src="vendor/material-dynamic-colors.min.js"></script>
|
<script type="module" src="vendor/material-dynamic-colors.min.js"></script>
|
||||||
<script src="vendor/iframe-resizer/parent.js"></script>
|
<script src="vendor/iframe-resizer/parent.js"></script>
|
||||||
|
<link href="/_content/PSC.Blazor.Components.MarkdownEditor/css/easymde.min.css" rel="stylesheet" />
|
||||||
|
<link href="/vendor/cm-material.css" rel="stylesheet" />
|
||||||
|
<script src="/_content/PSC.Blazor.Components.MarkdownEditor/js/easymde.min.js"></script>
|
||||||
|
<script src="/_content/PSC.Blazor.Components.MarkdownEditor/js/markdownEditor.js"></script>
|
||||||
<script src="/js/csharp.js"></script>
|
<script src="/js/csharp.js"></script>
|
||||||
<link rel="icon" type="image/png" href="favicon.png" />
|
<link rel="icon" type="image/png" href="favicon.png" />
|
||||||
</head>
|
</head>
|
||||||
|
|
135
wwwroot/vendor/cm-material.css
vendored
Normal file
135
wwwroot/vendor/cm-material.css
vendored
Normal file
|
@ -0,0 +1,135 @@
|
||||||
|
/*
|
||||||
|
Name: material
|
||||||
|
Author: Mattia Astorino (http://github.com/equinusocio)
|
||||||
|
Website: https://material-theme.site/
|
||||||
|
*/
|
||||||
|
|
||||||
|
.cm-s-material-darker.CodeMirror {
|
||||||
|
background-color: #212121;
|
||||||
|
color: #EEFFFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cm-s-material-darker .CodeMirror-gutters {
|
||||||
|
background: #212121;
|
||||||
|
color: #545454;
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cm-s-material-darker .CodeMirror-guttermarker,
|
||||||
|
.cm-s-material-darker .CodeMirror-guttermarker-subtle,
|
||||||
|
.cm-s-material-darker .CodeMirror-linenumber {
|
||||||
|
color: #545454;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cm-s-material-darker .CodeMirror-cursor {
|
||||||
|
border-left: 1px solid #FFCC00;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cm-s-material-darker div.CodeMirror-selected {
|
||||||
|
background: rgba(97, 97, 97, 0.2);
|
||||||
|
}
|
||||||
|
|
||||||
|
.cm-s-material-darker.CodeMirror-focused div.CodeMirror-selected {
|
||||||
|
background: rgba(97, 97, 97, 0.2);
|
||||||
|
}
|
||||||
|
|
||||||
|
.cm-s-material-darker .CodeMirror-line::selection,
|
||||||
|
.cm-s-material-darker .CodeMirror-line > span::selection,
|
||||||
|
.cm-s-material-darker .CodeMirror-line > span > span::selection {
|
||||||
|
background: rgba(128, 203, 196, 0.2);
|
||||||
|
}
|
||||||
|
|
||||||
|
.cm-s-material-darker .CodeMirror-line::-moz-selection,
|
||||||
|
.cm-s-material-darker .CodeMirror-line > span::-moz-selection,
|
||||||
|
.cm-s-material-darker .CodeMirror-line > span > span::-moz-selection {
|
||||||
|
background: rgba(128, 203, 196, 0.2);
|
||||||
|
}
|
||||||
|
|
||||||
|
.cm-s-material-darker .CodeMirror-activeline-background {
|
||||||
|
background: rgba(0, 0, 0, 0.5);
|
||||||
|
}
|
||||||
|
|
||||||
|
.cm-s-material-darker .cm-keyword {
|
||||||
|
color: #C792EA;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cm-s-material-darker .cm-operator {
|
||||||
|
color: #89DDFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cm-s-material-darker .cm-variable-2 {
|
||||||
|
color: #EEFFFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cm-s-material-darker .cm-variable-3,
|
||||||
|
.cm-s-material-darker .cm-type {
|
||||||
|
color: #f07178;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cm-s-material-darker .cm-builtin {
|
||||||
|
color: #FFCB6B;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cm-s-material-darker .cm-atom {
|
||||||
|
color: #F78C6C;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cm-s-material-darker .cm-number {
|
||||||
|
color: #FF5370;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cm-s-material-darker .cm-def {
|
||||||
|
color: #82AAFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cm-s-material-darker .cm-string {
|
||||||
|
color: #C3E88D;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cm-s-material-darker .cm-string-2 {
|
||||||
|
color: #f07178;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cm-s-material-darker .cm-comment {
|
||||||
|
color: #545454;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cm-s-material-darker .cm-variable {
|
||||||
|
color: #f07178;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cm-s-material-darker .cm-tag {
|
||||||
|
color: #FF5370;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cm-s-material-darker .cm-meta {
|
||||||
|
color: #FFCB6B;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cm-s-material-darker .cm-attribute {
|
||||||
|
color: #C792EA;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cm-s-material-darker .cm-property {
|
||||||
|
color: #C792EA;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cm-s-material-darker .cm-qualifier {
|
||||||
|
color: #DECB6B;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cm-s-material-darker .cm-variable-3,
|
||||||
|
.cm-s-material-darker .cm-type {
|
||||||
|
color: #DECB6B;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.cm-s-material-darker .cm-error {
|
||||||
|
color: rgba(255, 255, 255, 1.0);
|
||||||
|
background-color: #FF5370;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cm-s-material-darker .CodeMirror-matchingbracket {
|
||||||
|
text-decoration: underline;
|
||||||
|
color: white !important;
|
||||||
|
}
|
2
wwwroot/vendor/jquery-3.7.1.min.js
vendored
Normal file
2
wwwroot/vendor/jquery-3.7.1.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
Loading…
Reference in a new issue