1
0
This commit is contained in:
Debug_pro
2026-06-07 18:19:53 +03:00
commit fb13e5a20a
33 changed files with 2382 additions and 0 deletions

View File

@@ -0,0 +1,147 @@
using System.Windows;
using System.Windows.Threading;
using Microsoft.EntityFrameworkCore;
using SimpleWiki.Data;
using SimpleWiki.Models;
using SimpleWiki.Services;
namespace SimpleWiki.Views;
public partial class ArticleEditorWindow : Window
{
private readonly User _currentUser;
private readonly int? _articleId;
private bool _isPreviewBrowserReady;
private string _pendingPreviewHtml = string.Empty;
public ArticleEditorWindow(User currentUser, int? articleId = null)
{
InitializeComponent();
_currentUser = currentUser;
_articleId = articleId;
_pendingPreviewHtml = MarkdownService.ToHtmlDocument("Предпросмотр", "# Предпросмотр\n\nПодготовка предпросмотра...");
Loaded += ArticleEditorWindow_Loaded;
ContentRendered += ArticleEditorWindow_ContentRendered;
}
private void ArticleEditorWindow_ContentRendered(object? sender, EventArgs e)
{
_isPreviewBrowserReady = true;
Dispatcher.BeginInvoke(RenderPreviewIfReady, DispatcherPriority.ApplicationIdle);
}
private void ArticleEditorWindow_Loaded(object sender, RoutedEventArgs e)
{
if (_articleId.HasValue)
{
using var db = new AppDbContext();
var article = db.Articles.AsNoTracking().FirstOrDefault(x => x.Id == _articleId.Value);
if (article is not null)
{
TitleTextBox.Text = article.Title;
SummaryTextBox.Text = article.Summary;
MarkdownTextBox.Text = article.MarkdownContent;
}
}
UpdatePreview();
}
private void AnyInput_TextChanged(object sender, System.Windows.Controls.TextChangedEventArgs e)
{
UpdatePreview();
}
private void UpdatePreview()
{
var title = string.IsNullOrWhiteSpace(TitleTextBox.Text) ? "Новая статья" : TitleTextBox.Text.Trim();
var content = string.IsNullOrWhiteSpace(MarkdownTextBox.Text)
? "# Предпросмотр\n\nЗдесь появится отрендеренный markdown."
: MarkdownTextBox.Text;
_pendingPreviewHtml = MarkdownService.ToHtmlDocument(title, content);
RenderPreviewIfReady();
}
private void RenderPreviewIfReady()
{
if (!_isPreviewBrowserReady)
{
return;
}
PreviewBrowser.NavigateToString(_pendingPreviewHtml);
}
private void SaveButton_Click(object sender, RoutedEventArgs e)
{
var titleError = InputValidator.ValidateArticleTitle(TitleTextBox.Text);
var summaryError = InputValidator.ValidateArticleSummary(SummaryTextBox.Text);
var markdownError = InputValidator.ValidateArticleMarkdown(MarkdownTextBox.Text);
var errors = InputValidator.JoinErrors(titleError, summaryError, markdownError);
if (!string.IsNullOrWhiteSpace(errors))
{
MessageBox.Show(errors, "Ошибка валидации", MessageBoxButton.OK, MessageBoxImage.Warning);
return;
}
using var db = new AppDbContext();
var slug = SlugHelper.Generate(TitleTextBox.Text);
if (_articleId.HasValue)
{
var article = db.Articles.FirstOrDefault(x => x.Id == _articleId.Value);
if (article is null)
{
MessageBox.Show("Статья не найдена.", "Ошибка", MessageBoxButton.OK, MessageBoxImage.Error);
return;
}
var duplicate = db.Articles.AsNoTracking().Any(x => x.Slug == slug && x.Id != article.Id);
if (duplicate)
{
MessageBox.Show("Статья с таким заголовком уже существует.", "Ошибка", MessageBoxButton.OK, MessageBoxImage.Error);
return;
}
article.Title = TitleTextBox.Text.Trim();
article.Summary = SummaryTextBox.Text.Trim();
article.MarkdownContent = MarkdownTextBox.Text.Trim();
article.Slug = slug;
article.UpdatedAt = DateTime.UtcNow;
}
else
{
var duplicate = db.Articles.AsNoTracking().Any(x => x.Slug == slug);
if (duplicate)
{
MessageBox.Show("Статья с таким заголовком уже существует.", "Ошибка", MessageBoxButton.OK, MessageBoxImage.Error);
return;
}
var article = new Article
{
Title = TitleTextBox.Text.Trim(),
Summary = SummaryTextBox.Text.Trim(),
MarkdownContent = MarkdownTextBox.Text.Trim(),
Slug = slug,
AuthorId = _currentUser.Id,
CreatedAt = DateTime.UtcNow
};
db.Articles.Add(article);
}
db.SaveChanges();
DialogResult = true;
Close();
}
private void CancelButton_Click(object sender, RoutedEventArgs e)
{
DialogResult = false;
Close();
}
}