Introduced SharedEditor.razor and SharedPreview.razor for editing and viewing shared documents via tokenized links. Includes auto-save, markdown preview, permission checks, and dedicated responsive styles for both editable and view-only modes. Enables secure sharing of documents with user-friendly interfaces.
138 lines
3.7 KiB
Plaintext
138 lines
3.7 KiB
Plaintext
@page "/s/{token}"
|
|
@rendermode InteractiveServer
|
|
@using Notemark.Services
|
|
@inject IShareService ShareService
|
|
@inject ISessionService SessionService
|
|
@inject IMarkdownService MarkdownService
|
|
@inject NavigationManager Navigation
|
|
|
|
<PageTitle>Notemark - Shared Document</PageTitle>
|
|
|
|
@if (isLoading)
|
|
{
|
|
<div class="share-loading">
|
|
<div class="loading-content">
|
|
<h2>Loading shared document...</h2>
|
|
</div>
|
|
</div>
|
|
}
|
|
else if (errorMessage != null)
|
|
{
|
|
<div class="share-error">
|
|
<div class="error-content">
|
|
<h2>⚠️ Unable to Load Document</h2>
|
|
<p>@errorMessage</p>
|
|
<button class="btn-home" @onclick="GoHome">Create New Document</button>
|
|
</div>
|
|
</div>
|
|
}
|
|
else
|
|
{
|
|
<div class="shared-container">
|
|
<!-- Header Bar -->
|
|
<div class="shared-header">
|
|
<div class="header-left">
|
|
<h1>Notemark</h1>
|
|
<span class="share-badge readonly">View Only</span>
|
|
</div>
|
|
|
|
<div class="header-right">
|
|
@if (shareToken?.Mode == "editable")
|
|
{
|
|
<button class="btn-edit" @onclick="GoToEditor">✏️ Edit</button>
|
|
}
|
|
<button class="btn-home" @onclick="GoHome">Create New</button>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Content Area -->
|
|
<div class="shared-content">
|
|
@if (string.IsNullOrEmpty(markdownContent))
|
|
{
|
|
<div class="empty-content">
|
|
<h3>Empty Document</h3>
|
|
<p>This document doesn't have any content yet.</p>
|
|
</div>
|
|
}
|
|
else
|
|
{
|
|
<div class="preview-content">
|
|
@((MarkupString)renderedHtml)
|
|
</div>
|
|
}
|
|
</div>
|
|
</div>
|
|
}
|
|
|
|
@code {
|
|
[Parameter] public string Token { get; set; } = "";
|
|
|
|
private bool isLoading = true;
|
|
private string? errorMessage = null;
|
|
private ShareToken? shareToken = null;
|
|
private string markdownContent = "";
|
|
private string renderedHtml = "";
|
|
|
|
protected override async Task OnInitializedAsync()
|
|
{
|
|
await LoadSharedDocument();
|
|
}
|
|
|
|
private async Task LoadSharedDocument()
|
|
{
|
|
try
|
|
{
|
|
isLoading = true;
|
|
|
|
// Validate token
|
|
if (string.IsNullOrEmpty(Token))
|
|
{
|
|
errorMessage = "Invalid share link.";
|
|
return;
|
|
}
|
|
|
|
// Get share token info
|
|
shareToken = await ShareService.GetShareTokenAsync(Token);
|
|
if (shareToken == null)
|
|
{
|
|
errorMessage = "Share link not found or has expired.";
|
|
return;
|
|
}
|
|
|
|
// Check if token is still valid
|
|
if (!await ShareService.IsValidTokenAsync(Token))
|
|
{
|
|
errorMessage = "This share link has been revoked or has expired.";
|
|
return;
|
|
}
|
|
|
|
// Load the document content
|
|
markdownContent = await SessionService.LoadSessionContentAsync(shareToken.SessionId);
|
|
|
|
// Render to HTML
|
|
renderedHtml = MarkdownService.RenderToHtml(markdownContent);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
errorMessage = "An error occurred while loading the document.";
|
|
}
|
|
finally
|
|
{
|
|
isLoading = false;
|
|
await InvokeAsync(StateHasChanged);
|
|
}
|
|
}
|
|
|
|
private void GoToEditor()
|
|
{
|
|
if (shareToken?.Mode == "editable")
|
|
{
|
|
Navigation.NavigateTo($"/e/{Token}");
|
|
}
|
|
}
|
|
|
|
private void GoHome()
|
|
{
|
|
Navigation.NavigateTo("/");
|
|
}
|
|
} |