Added a way to edit the profile page

Including custom css and head content, but not custom themes or metadata (yet)
This commit is contained in:
Gordon Pedersen 2024-07-05 15:47:05 +10:00
parent b42bf2023d
commit 25f362bfc5
7 changed files with 145 additions and 0 deletions

View file

@ -223,6 +223,15 @@ namespace Neighbourhood.omg.lol
public async Task<BasicResponseData?> PostEphemeral(string content) => public async Task<BasicResponseData?> PostEphemeral(string content) =>
await Post<BasicResponseData, EphemeralData>("/ephemeral", new EphemeralData { Content = content }); await Post<BasicResponseData, EphemeralData>("/ephemeral", new EphemeralData { Content = content });
public async Task<ProfileResponseData?> GetProfile(string address) =>
await Get<ProfileResponseData>($"/address/{address}/web");
public async Task<BasicResponseData?> PostProfile(string address, string content, bool publish = true) =>
await Post<BasicResponseData, PostProfile>($"/address/{address}/web", new PostProfile { Content = content, Publish = publish });
public async Task<BasicResponseData?> PostProfile(string address, PostProfile data) =>
await Post<BasicResponseData, PostProfile>($"/address/{address}/web", data);
public async Task<List<MarkupString>> EphemeralScrape() { public async Task<List<MarkupString>> EphemeralScrape() {
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/");

View file

@ -0,0 +1,83 @@
@page "/editProfile"
@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>
<details id="advanced">
<summary> Advanced </summary>
<small>Style you include here will be places in a &lt;style&gt; element in your pages &lt;head&gt;.</small>
<div class="field textarea label border max">
<InputTextArea @bind-Value="css"></InputTextArea>
<label>Custom CSS</label>
</div>
<small>Anything you put here will be included in your pages &lt;head&gt; element.</small>
<div class="field textarea label border max">
<InputTextArea @bind-Value="head"></InputTextArea>
<label>Additional &lt;head&gt; Content</label>
</div>
</details>
<nav>
<div class="max"></div>
<button class="transparent link" onclick="history.back();" disabled="@loading">Cancel</button>
<button @onclick="Save" disabled="@loading">
@if (loading) {
<span>Saving...</span>
}
else {
<i class="fa-solid fa-floppy-disk"></i> <span>Save & Publish</span>
}
</button>
</nav>
@code {
private MarkdownEditor? Editor;
private string? markdownValue;
private string? css;
private string? head;
private bool loading = false;
protected override async Task OnInitializedAsync() {
await base.OnInitializedAsync();
ProfileResponseData? data = await api.GetProfile(State.SelectedAddressName!);
if (data != null) {
markdownValue = data.Content;
css = data.Css;
head = data.Head;
await Editor!.SetValueAsync(markdownValue);
}
await InvokeAsync(StateHasChanged);
}
Task OnMarkdownValueChanged(string value) {
return Task.CompletedTask;
}
public async Task Save() {
loading = true;
await InvokeAsync(StateHasChanged);
var result = await api.PostProfile(State.SelectedAddressName!,
new PostProfile() {
Content = markdownValue ?? string.Empty,
Css = string.IsNullOrEmpty(css) ? null : css,
Head = string.IsNullOrEmpty(head) ? null : head
});
if (result != null) {
await State.RefreshNow();
await InvokeAsync(StateHasChanged);
Nav.NavigateTo($"/person/{State.SelectedAddressName}#profile");
}
loading = false;
}
}

View file

@ -52,6 +52,12 @@
<div id="profile" class="page no-padding"> <div id="profile" class="page no-padding">
<a href="@ProfileUrl" 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="@ProfileUrl" 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="profile_page" @ref="ProfilePage" Url="@ProfileUrl"></ExternalPageComponent> <ExternalPageComponent id="profile_page" @ref="ProfilePage" Url="@ProfileUrl"></ExternalPageComponent>
@if (IsMe) {
<a href="/editProfile" 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 id="statuses" class="page padding active"> <div id="statuses" class="page padding active">

14
Models/API/PostProfile.cs Normal file
View file

@ -0,0 +1,14 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Neighbourhood.omg.lol.Models {
public class PostProfile {
public string Content { get; set; } = string.Empty;
public bool Publish { get; set; } = true;
public string? Css { get; set; }
public string? Head { get; set; }
}
}

View file

@ -0,0 +1,21 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Neighbourhood.omg.lol.Models {
public class ProfileResponseData: IOmgLolResponseData {
public string Message { get; set; } = string.Empty;
public string Content { get; set; } = string.Empty;
public string Type { get; set; } = string.Empty;
public string Theme { get; set; } = string.Empty;
public string Css { get; set; } = string.Empty;
public string Head { get; set; } = string.Empty;
public string Verified { get; set; } = string.Empty;
public string Pfp { get; set; } = string.Empty;
public string Metadata { get; set; } = string.Empty;
public string Branding { get; set; } = string.Empty;
}
}

View file

@ -495,4 +495,10 @@ article {
article.now { article.now {
margin: 0; margin: 0;
width:auto; width:auto;
}
#advanced textarea, #advanced .field.textarea {
background-color: #212121;
color: #EEFFFF;
font-family: monospace;
} }

View file

@ -22,4 +22,10 @@ function scrollToId(id) {
inline: "nearest" inline: "nearest"
}); });
} }
}
function toggleDetails(id) {
const element = document.getElementById(id)
if (element instanceof HTMLDetailsElement)
element.open = !element.open
} }