From 6cdb23e78d7694e728d3571d0d9067d837bf67ed Mon Sep 17 00:00:00 2001 From: Shankar Date: Wed, 13 Nov 2024 15:38:25 +0530 Subject: [PATCH] Basic Markdown Rendering and Bibliography - Added basic support for markdown rendering. - Update to the new BookReference. --- Directory.Packages.props | 19 +- Symptum.sln | 19 ++ global.json | 2 +- src/Symptum.Common/Helpers/PackageHelper.cs | 1 - src/Symptum.Common/Symptum.Common.csproj | 9 +- .../Data/Bibliography/BookReference.cs | 87 ++++++- .../Data/Bibliography/IReference.cs | 6 - .../Bibliography/JournalArticleReference.cs | 6 +- .../Data/Bibliography/LinkReference.cs | 2 +- .../Data/Bibliography/LiteratureReference.cs | 20 +- .../Data/Bibliography/ReferenceBase.cs | 30 ++- src/Symptum.Core/Subjects/Books/Book.cs | 12 +- .../Subjects/Books/BookReference.cs | 115 -------- src/Symptum.Core/Subjects/Books/BookStore.cs | 2 +- .../Subjects/QuestionBanks/QuestionEntry.cs | 51 ++-- src/Symptum.Core/Symptum.Core.csproj | 2 +- src/Symptum.Core/TypeConversion/Converters.cs | 20 +- src/Symptum.Editor/App.xaml | 4 +- src/Symptum.Editor/App.xaml.cs | 3 + .../Controls/AddNewItemDialog.xaml.cs | 19 -- .../Controls/BookReferencePicker.xaml | 2 +- .../Controls/BookReferencePicker.xaml.cs | 22 +- .../Controls/ListEditorControl.xaml | 16 +- .../Controls/ListEditorControl.xaml.cs | 123 ++++++++- src/Symptum.Editor/Controls/NewItemType.cs | 20 ++ ...QuestionBankContextConfigureDialog.xaml.cs | 9 +- .../Controls/QuestionEditorDialog.xaml | 38 ++- .../Controls/QuestionEditorDialog.xaml.cs | 102 +++----- .../Controls/ReferenceBaseTemplateSelector.cs | 27 ++ .../Converters/ListToStringConverters.cs | 19 +- .../EditorPages/MarkdownEditorPage.xaml | 20 ++ .../EditorPages/MarkdownEditorPage.xaml.cs | 31 +++ .../EditorPages/QuestionTopicEditorPage.xaml | 3 +- src/Symptum.Editor/Helpers/MarkdownHelper.cs | 8 +- .../Helpers/QuestionBankContextHelper.cs | 2 +- src/Symptum.Editor/MainPage.xaml | 1 + src/Symptum.Editor/MainPage.xaml.cs | 70 +++++ src/Symptum.Editor/Package.appxmanifest | 4 +- .../Properties/launchSettings.json | 4 +- src/Symptum.Editor/Symptum.Editor.csproj | 19 +- src/Symptum.Markdown/Symptum.Markdown.csproj | 2 +- src/Symptum.UI/Markdown/DefaultSVGRenderer.cs | 42 +++ src/Symptum.UI/Markdown/Extensions.cs | 246 ++++++++++++++++++ src/Symptum.UI/Markdown/ISVGRenderer.cs | 10 + src/Symptum.UI/Markdown/ImageProvider.cs | 12 + src/Symptum.UI/Markdown/MarkdownConfig.cs | 18 ++ .../Markdown/MarkdownTextBlock.xaml | 27 ++ .../Markdown/MarkdownTextBlock.xaml.cs | 116 +++++++++ src/Symptum.UI/Markdown/MarkdownThemes.cs | 118 +++++++++ .../ObjectRenderers/CodeBlockRenderer.cs | 18 ++ .../Extensions/TableRenderer.cs | 60 +++++ .../Extensions/TaskListRenderer.cs | 20 ++ .../ObjectRenderers/HeadingRenderer.cs | 22 ++ .../Inlines/AutoLinkInlineRenderer.cs | 35 +++ .../Inlines/CodeInlineRenderer.cs | 19 ++ .../Inlines/ContainerInlineRenderer.cs | 23 ++ .../Inlines/DelimiterInlineRenderer.cs | 21 ++ .../Inlines/EmphasisInlineRenderer.cs | 47 ++++ .../Inlines/HtmlEntityInlineRenderer.cs | 25 ++ .../Inlines/LineBreakInlineRenderer.cs | 27 ++ .../Inlines/LinkInlineRenderer.cs | 46 ++++ .../Inlines/LiteralInlineRenderer.cs | 21 ++ .../Renderers/ObjectRenderers/ListRenderer.cs | 32 +++ .../ObjectRenderers/ParagraphRenderer.cs | 23 ++ .../ObjectRenderers/QuoteBlockRenderer.cs | 24 ++ .../ObjectRenderers/ThematicBreakRenderer.cs | 21 ++ .../Markdown/Renderers/WinUIObjectRenderer.cs | 13 + .../Markdown/Renderers/WinUIRenderer.cs | 172 ++++++++++++ .../Markdown/TextElements/IAddChild.cs | 12 + .../Markdown/TextElements/MyAutolinkInline.cs | 45 ++++ .../Markdown/TextElements/MyBlockContainer.cs | 34 +++ .../Markdown/TextElements/MyCodeBlock.cs | 88 +++++++ .../Markdown/TextElements/MyEmphasisInline.cs | 81 ++++++ .../Markdown/TextElements/MyFlowDocument.cs | 59 +++++ .../Markdown/TextElements/MyHeading.cs | 63 +++++ .../Markdown/TextElements/MyHyperlink.cs | 50 ++++ .../TextElements/MyHyperlinkButton.cs | 51 ++++ .../Markdown/TextElements/MyImage.cs | 117 +++++++++ .../Markdown/TextElements/MyInlineCode.cs | 47 ++++ .../Markdown/TextElements/MyInlineText.cs | 30 +++ .../Markdown/TextElements/MyLineBreak.cs | 32 +++ .../Markdown/TextElements/MyList.cs | 121 +++++++++ .../Markdown/TextElements/MyParagraph.cs | 38 +++ .../Markdown/TextElements/MyQuote.cs | 82 ++++++ .../Markdown/TextElements/MyTable.cs | 52 ++++ .../Markdown/TextElements/MyTableCell.cs | 86 ++++++ .../Markdown/TextElements/MyTableRow.cs | 39 +++ .../Markdown/TextElements/MyTableUIElement.cs | 217 +++++++++++++++ .../TextElements/MyTaskListCheckBox.cs | 43 +++ .../Markdown/TextElements/MyThematicBreak.cs | 36 +++ .../Markdown/TextElements/STextElements.cs | 109 ++++++++ src/Symptum.UI/Symptum.UI.csproj | 49 ++++ src/Symptum.UI/Themes/Generic.xaml | 8 + src/Symptum.UI/Themes/Styles.xaml | 58 +++++ src/Symptum/Symptum.csproj | 13 +- tests/Playground/Playground.csproj | 5 +- .../SymptumCore.Test/SymptumCore.Test.csproj | 2 +- 97 files changed, 3536 insertions(+), 360 deletions(-) delete mode 100644 src/Symptum.Core/Data/Bibliography/IReference.cs delete mode 100644 src/Symptum.Core/Subjects/Books/BookReference.cs create mode 100644 src/Symptum.Editor/Controls/NewItemType.cs create mode 100644 src/Symptum.Editor/Controls/ReferenceBaseTemplateSelector.cs create mode 100644 src/Symptum.Editor/EditorPages/MarkdownEditorPage.xaml create mode 100644 src/Symptum.Editor/EditorPages/MarkdownEditorPage.xaml.cs create mode 100644 src/Symptum.UI/Markdown/DefaultSVGRenderer.cs create mode 100644 src/Symptum.UI/Markdown/Extensions.cs create mode 100644 src/Symptum.UI/Markdown/ISVGRenderer.cs create mode 100644 src/Symptum.UI/Markdown/ImageProvider.cs create mode 100644 src/Symptum.UI/Markdown/MarkdownConfig.cs create mode 100644 src/Symptum.UI/Markdown/MarkdownTextBlock.xaml create mode 100644 src/Symptum.UI/Markdown/MarkdownTextBlock.xaml.cs create mode 100644 src/Symptum.UI/Markdown/MarkdownThemes.cs create mode 100644 src/Symptum.UI/Markdown/Renderers/ObjectRenderers/CodeBlockRenderer.cs create mode 100644 src/Symptum.UI/Markdown/Renderers/ObjectRenderers/Extensions/TableRenderer.cs create mode 100644 src/Symptum.UI/Markdown/Renderers/ObjectRenderers/Extensions/TaskListRenderer.cs create mode 100644 src/Symptum.UI/Markdown/Renderers/ObjectRenderers/HeadingRenderer.cs create mode 100644 src/Symptum.UI/Markdown/Renderers/ObjectRenderers/Inlines/AutoLinkInlineRenderer.cs create mode 100644 src/Symptum.UI/Markdown/Renderers/ObjectRenderers/Inlines/CodeInlineRenderer.cs create mode 100644 src/Symptum.UI/Markdown/Renderers/ObjectRenderers/Inlines/ContainerInlineRenderer.cs create mode 100644 src/Symptum.UI/Markdown/Renderers/ObjectRenderers/Inlines/DelimiterInlineRenderer.cs create mode 100644 src/Symptum.UI/Markdown/Renderers/ObjectRenderers/Inlines/EmphasisInlineRenderer.cs create mode 100644 src/Symptum.UI/Markdown/Renderers/ObjectRenderers/Inlines/HtmlEntityInlineRenderer.cs create mode 100644 src/Symptum.UI/Markdown/Renderers/ObjectRenderers/Inlines/LineBreakInlineRenderer.cs create mode 100644 src/Symptum.UI/Markdown/Renderers/ObjectRenderers/Inlines/LinkInlineRenderer.cs create mode 100644 src/Symptum.UI/Markdown/Renderers/ObjectRenderers/Inlines/LiteralInlineRenderer.cs create mode 100644 src/Symptum.UI/Markdown/Renderers/ObjectRenderers/ListRenderer.cs create mode 100644 src/Symptum.UI/Markdown/Renderers/ObjectRenderers/ParagraphRenderer.cs create mode 100644 src/Symptum.UI/Markdown/Renderers/ObjectRenderers/QuoteBlockRenderer.cs create mode 100644 src/Symptum.UI/Markdown/Renderers/ObjectRenderers/ThematicBreakRenderer.cs create mode 100644 src/Symptum.UI/Markdown/Renderers/WinUIObjectRenderer.cs create mode 100644 src/Symptum.UI/Markdown/Renderers/WinUIRenderer.cs create mode 100644 src/Symptum.UI/Markdown/TextElements/IAddChild.cs create mode 100644 src/Symptum.UI/Markdown/TextElements/MyAutolinkInline.cs create mode 100644 src/Symptum.UI/Markdown/TextElements/MyBlockContainer.cs create mode 100644 src/Symptum.UI/Markdown/TextElements/MyCodeBlock.cs create mode 100644 src/Symptum.UI/Markdown/TextElements/MyEmphasisInline.cs create mode 100644 src/Symptum.UI/Markdown/TextElements/MyFlowDocument.cs create mode 100644 src/Symptum.UI/Markdown/TextElements/MyHeading.cs create mode 100644 src/Symptum.UI/Markdown/TextElements/MyHyperlink.cs create mode 100644 src/Symptum.UI/Markdown/TextElements/MyHyperlinkButton.cs create mode 100644 src/Symptum.UI/Markdown/TextElements/MyImage.cs create mode 100644 src/Symptum.UI/Markdown/TextElements/MyInlineCode.cs create mode 100644 src/Symptum.UI/Markdown/TextElements/MyInlineText.cs create mode 100644 src/Symptum.UI/Markdown/TextElements/MyLineBreak.cs create mode 100644 src/Symptum.UI/Markdown/TextElements/MyList.cs create mode 100644 src/Symptum.UI/Markdown/TextElements/MyParagraph.cs create mode 100644 src/Symptum.UI/Markdown/TextElements/MyQuote.cs create mode 100644 src/Symptum.UI/Markdown/TextElements/MyTable.cs create mode 100644 src/Symptum.UI/Markdown/TextElements/MyTableCell.cs create mode 100644 src/Symptum.UI/Markdown/TextElements/MyTableRow.cs create mode 100644 src/Symptum.UI/Markdown/TextElements/MyTableUIElement.cs create mode 100644 src/Symptum.UI/Markdown/TextElements/MyTaskListCheckBox.cs create mode 100644 src/Symptum.UI/Markdown/TextElements/MyThematicBreak.cs create mode 100644 src/Symptum.UI/Markdown/TextElements/STextElements.cs create mode 100644 src/Symptum.UI/Symptum.UI.csproj create mode 100644 src/Symptum.UI/Themes/Generic.xaml create mode 100644 src/Symptum.UI/Themes/Styles.xaml diff --git a/Directory.Packages.props b/Directory.Packages.props index 490c939..7d72f1e 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -6,16 +6,19 @@ --> - + + - - - - + + + + + + - - - + + + \ No newline at end of file diff --git a/Symptum.sln b/Symptum.sln index 04f298b..63b2860 100644 --- a/Symptum.sln +++ b/Symptum.sln @@ -36,6 +36,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Symptum.Core.SourceGenerato EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Symptum.Editor.SourceGenerators", "src\Symptum.Editor.SourceGenerators\Symptum.Editor.SourceGenerators.csproj", "{581A06AB-1776-4673-8104-5E55DC4D77F7}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Symptum.UI", "src\Symptum.UI\Symptum.UI.csproj", "{A4BC2540-9288-4723-BCC3-485E3C172AAB}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -208,6 +210,22 @@ Global {581A06AB-1776-4673-8104-5E55DC4D77F7}.Release|x64.Build.0 = Release|Any CPU {581A06AB-1776-4673-8104-5E55DC4D77F7}.Release|x86.ActiveCfg = Release|Any CPU {581A06AB-1776-4673-8104-5E55DC4D77F7}.Release|x86.Build.0 = Release|Any CPU + {A4BC2540-9288-4723-BCC3-485E3C172AAB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A4BC2540-9288-4723-BCC3-485E3C172AAB}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A4BC2540-9288-4723-BCC3-485E3C172AAB}.Debug|ARM64.ActiveCfg = Debug|Any CPU + {A4BC2540-9288-4723-BCC3-485E3C172AAB}.Debug|ARM64.Build.0 = Debug|Any CPU + {A4BC2540-9288-4723-BCC3-485E3C172AAB}.Debug|x64.ActiveCfg = Debug|Any CPU + {A4BC2540-9288-4723-BCC3-485E3C172AAB}.Debug|x64.Build.0 = Debug|Any CPU + {A4BC2540-9288-4723-BCC3-485E3C172AAB}.Debug|x86.ActiveCfg = Debug|Any CPU + {A4BC2540-9288-4723-BCC3-485E3C172AAB}.Debug|x86.Build.0 = Debug|Any CPU + {A4BC2540-9288-4723-BCC3-485E3C172AAB}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A4BC2540-9288-4723-BCC3-485E3C172AAB}.Release|Any CPU.Build.0 = Release|Any CPU + {A4BC2540-9288-4723-BCC3-485E3C172AAB}.Release|ARM64.ActiveCfg = Release|Any CPU + {A4BC2540-9288-4723-BCC3-485E3C172AAB}.Release|ARM64.Build.0 = Release|Any CPU + {A4BC2540-9288-4723-BCC3-485E3C172AAB}.Release|x64.ActiveCfg = Release|Any CPU + {A4BC2540-9288-4723-BCC3-485E3C172AAB}.Release|x64.Build.0 = Release|Any CPU + {A4BC2540-9288-4723-BCC3-485E3C172AAB}.Release|x86.ActiveCfg = Release|Any CPU + {A4BC2540-9288-4723-BCC3-485E3C172AAB}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -222,6 +240,7 @@ Global {42B5F44B-A67E-44DF-968F-0E425C6F8BE5} = {106EE3C2-3796-4F0F-B5B9-67569B46AB40} {8CFD07E1-A509-462A-A568-00E6DEADCF07} = {832124A0-8184-48DC-A66D-E8B6106F68C2} {581A06AB-1776-4673-8104-5E55DC4D77F7} = {832124A0-8184-48DC-A66D-E8B6106F68C2} + {A4BC2540-9288-4723-BCC3-485E3C172AAB} = {832124A0-8184-48DC-A66D-E8B6106F68C2} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {82DC91FF-5CA7-40EF-9E24-FB9538FFEC75} diff --git a/global.json b/global.json index e3d5b9e..a4a3ec7 100644 --- a/global.json +++ b/global.json @@ -1,6 +1,6 @@ { // To update the version of Uno please update the version of the Uno.Sdk here. See https://aka.platform.uno/upgrade-uno-packages for more information. "msbuild-sdks": { - "Uno.Sdk": "5.4.0-dev.188" + "Uno.Sdk": "5.6.0-dev.144" } } diff --git a/src/Symptum.Common/Helpers/PackageHelper.cs b/src/Symptum.Common/Helpers/PackageHelper.cs index e2c34b8..156bdfa 100644 --- a/src/Symptum.Common/Helpers/PackageHelper.cs +++ b/src/Symptum.Common/Helpers/PackageHelper.cs @@ -1,7 +1,6 @@ using System.Diagnostics.CodeAnalysis; using System.Globalization; using System.IO.Compression; -using System.Runtime.InteropServices.WindowsRuntime; using System.Text.Json; using CsvHelper; using Symptum.Core.Management.Deployment; diff --git a/src/Symptum.Common/Symptum.Common.csproj b/src/Symptum.Common/Symptum.Common.csproj index a8474f3..301676d 100644 --- a/src/Symptum.Common/Symptum.Common.csproj +++ b/src/Symptum.Common/Symptum.Common.csproj @@ -1,10 +1,12 @@ - net8.0;net8.0-ios;net8.0-maccatalyst;net8.0-android;net8.0-windows10.0.19041;net8.0-browserwasm;net8.0-desktop + net9.0;net9.0-ios;net9.0-maccatalyst;net9.0-android;net9.0-windows10.0.22621;;net9.0-desktop true Library true + enable + enable + + + + + \ No newline at end of file diff --git a/src/Symptum.Core/Data/Bibliography/BookReference.cs b/src/Symptum.Core/Data/Bibliography/BookReference.cs index 61951b4..d1e7cfe 100644 --- a/src/Symptum.Core/Data/Bibliography/BookReference.cs +++ b/src/Symptum.Core/Data/Bibliography/BookReference.cs @@ -1,10 +1,89 @@ +using Symptum.Core.Helpers; +using Symptum.Core.Subjects.Books; +using System.Diagnostics.CodeAnalysis; +using System.Web; + namespace Symptum.Core.Data.Bibliography; -internal class BookReference : LiteratureReference +public record BookReference : LiteratureReference { - public string Section { get; set; } + private static readonly string _bookId = "n"; + private static readonly string _bookEdition = "ed"; + private static readonly string _bookVolume = "vol"; + + #region Properties + + public string? Section { get; init; } + + public int Edition { get; init; } + + public int ISBN { get; init; } + + #endregion + + // @book?n={id}&ed={edition}&vol={volume}#{pages} + public static bool TryParse(string? text, [NotNullWhen(true)] out BookReference? bookReference) + { + bool parsed = false; + bookReference = null; + if (!string.IsNullOrEmpty(text)) + { + var values = text.Split(ParserHelper.BookReferenceDelimiter); + if (values.Length == 2) + { + string bookString = values[0][0] == '@' && values[0].Length > 6 ? values[0].Remove(0, 6) : values[0]; + (Book? book, int edition, int volume) = ParseBookString(bookString); + + bookReference = new() + { + Id = book?.Id, + Title = book?.Title, + Authors = book?.Authors, + Edition = edition, + Volume = volume, + Pages = values[1] + }; + parsed = true; + } + } + + return parsed; + } + + private static (Book? book, int edition, int volume) ParseBookString(string bookString) + { + Book? book = null; + int edition = 0; + int volume = 0; + var col = HttpUtility.ParseQueryString(bookString); + if (col != null && col.Count > 0) + { + string? bookCode = col[_bookId]; + string? bookEdition = col[_bookEdition]; + string? bookVolume = col[_bookVolume]; + if (!string.IsNullOrEmpty(bookCode)) + book = BookStore.Books.FirstOrDefault(x => x.Id == bookCode); + if (int.TryParse(bookEdition, out int edNo)) + edition = edNo; + if (int.TryParse(bookVolume, out int volNo)) + volume = volNo; + } + + return (book, edition, volume); + } - public int Edition { get; set; } + public override string ToString() + { + var col = HttpUtility.ParseQueryString(string.Empty); + col.Add(_bookId, Id ?? string.Empty); + col.Add(_bookEdition, Edition.ToString()); + col.Add(_bookVolume, Volume.ToString()); + return "@book?" + col.ToString() + ParserHelper.BookReferenceDelimiter + Pages; + } - public int ISBN { get; set; } + public override string GetPreviewText() + { + return $"{Title} by {Authors}, " + + $"Edition: {Edition}, Volume: {Volume}, Pages: {Pages}"; + } } diff --git a/src/Symptum.Core/Data/Bibliography/IReference.cs b/src/Symptum.Core/Data/Bibliography/IReference.cs deleted file mode 100644 index ca5dd77..0000000 --- a/src/Symptum.Core/Data/Bibliography/IReference.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace Symptum.Core.Data.Bibliography; - -internal class IReference -{ - -} diff --git a/src/Symptum.Core/Data/Bibliography/JournalArticleReference.cs b/src/Symptum.Core/Data/Bibliography/JournalArticleReference.cs index 582c2a1..7725b2f 100644 --- a/src/Symptum.Core/Data/Bibliography/JournalArticleReference.cs +++ b/src/Symptum.Core/Data/Bibliography/JournalArticleReference.cs @@ -1,8 +1,8 @@ namespace Symptum.Core.Data.Bibliography; -internal class JournalArticleReference : LiteratureReference +public record JournalArticleReference : LiteratureReference { - public string JournalName { get; set; } + public string? JournalName { get; init; } - public int Issue { get; set; } + public int Issue { get; init; } } diff --git a/src/Symptum.Core/Data/Bibliography/LinkReference.cs b/src/Symptum.Core/Data/Bibliography/LinkReference.cs index 5075fca..6a7b95e 100644 --- a/src/Symptum.Core/Data/Bibliography/LinkReference.cs +++ b/src/Symptum.Core/Data/Bibliography/LinkReference.cs @@ -1,6 +1,6 @@ namespace Symptum.Core.Data.Bibliography; -internal class LinkReference : ReferenceBase +public record LinkReference : ReferenceBase { } diff --git a/src/Symptum.Core/Data/Bibliography/LiteratureReference.cs b/src/Symptum.Core/Data/Bibliography/LiteratureReference.cs index 8a3d327..9e9eb46 100644 --- a/src/Symptum.Core/Data/Bibliography/LiteratureReference.cs +++ b/src/Symptum.Core/Data/Bibliography/LiteratureReference.cs @@ -1,22 +1,22 @@ namespace Symptum.Core.Data.Bibliography; -public class LiteratureReference : ReferenceBase +public record LiteratureReference : ReferenceBase { - public string Authors { get; set; } + public string? Authors { get; init; } - public string Title { get; set; } + public string? Title { get; init; } - public string Description { get; set; } + public string? Description { get; init; } - public int Volume { get; set; } + public int Volume { get; init; } - public string Pages { get; set; } + public string? Pages { get; init; } - public int Year { get; set; } + public int Year { get; init; } - public string Editors { get; set; } + public string? Editors { get; init; } - public string Publisher { get; set; } + public string? Publisher { get; init; } - public Uri Url { get; set; } + public Uri? Url { get; init; } } diff --git a/src/Symptum.Core/Data/Bibliography/ReferenceBase.cs b/src/Symptum.Core/Data/Bibliography/ReferenceBase.cs index 92fdf45..1493ab3 100644 --- a/src/Symptum.Core/Data/Bibliography/ReferenceBase.cs +++ b/src/Symptum.Core/Data/Bibliography/ReferenceBase.cs @@ -1,8 +1,34 @@ -using CommunityToolkit.Mvvm.ComponentModel; +using System.Diagnostics.CodeAnalysis; namespace Symptum.Core.Data.Bibliography; -public class ReferenceBase : ObservableObject +public abstract record ReferenceBase { + #region Properties + public string? Id { get; init; } + + #endregion + + public static bool TryParse(string? text, [NotNullWhen(true)] out ReferenceBase? reference) + { + bool parsed = false; + reference = null; + + if (!string.IsNullOrEmpty(text)) + { + if (text.StartsWith("@book?")) + { + if (BookReference.TryParse(text, out BookReference? bookReference)) + { + parsed = true; + reference = bookReference; + } + } + } + + return parsed; + } + + public virtual string GetPreviewText() => string.Empty; } diff --git a/src/Symptum.Core/Subjects/Books/Book.cs b/src/Symptum.Core/Subjects/Books/Book.cs index b2d5e29..3c74193 100644 --- a/src/Symptum.Core/Subjects/Books/Book.cs +++ b/src/Symptum.Core/Subjects/Books/Book.cs @@ -7,12 +7,12 @@ public class Book : ObservableObject { #region Properties - private string _code = string.Empty; + private string _id = string.Empty; - public string Code + public string Id { - get => _code; - set => SetProperty(ref _code, value); + get => _id; + set => SetProperty(ref _id, value); } private string _title = string.Empty; @@ -48,13 +48,13 @@ public Book() public Book(string code, string title, string author) { - _code = code; + _id = code; _title = title; _authors = author; } public override string ToString() { - return Title + " by " + Authors + " (" + Code + ")"; + return Title + " by " + Authors + " (" + Id + ")"; } } diff --git a/src/Symptum.Core/Subjects/Books/BookReference.cs b/src/Symptum.Core/Subjects/Books/BookReference.cs deleted file mode 100644 index b50f5cb..0000000 --- a/src/Symptum.Core/Subjects/Books/BookReference.cs +++ /dev/null @@ -1,115 +0,0 @@ -using System.Diagnostics.CodeAnalysis; -using System.Web; -using CommunityToolkit.Mvvm.ComponentModel; -using Symptum.Core.Helpers; - -namespace Symptum.Core.Subjects.Books; - -public class BookReference : ObservableObject -{ - private static readonly string _bookCodeId = "n"; - private static readonly string _bookEditionId = "ed"; - private static readonly string _bookVolumeId = "vol"; - - #region Properties - - private Book? _book; - - public Book? Book - { - get => _book; - set => SetProperty(ref _book, value); - } - - private int _edition = 0; - - public int Edition - { - get => _edition; - set => SetProperty(ref _edition, value); - } - - private int _volume = 0; - - public int Volume - { - get => _volume; - set => SetProperty(ref _volume, value); - } - - private string? _pageNumbers; - - public string? PageNumbers - { - get => _pageNumbers; - set => SetProperty(ref _pageNumbers, value); - } - - #endregion - - public BookReference() - { - } - - public static bool TryParse(string? text, [NotNullWhen(true)] out BookReference? bookReference) - { - bool parsed = false; - bookReference = null; - if (!string.IsNullOrEmpty(text)) - { - var values = text.Split(ParserHelper.BookReferenceDelimiter); - if (values.Length == 2) - { - bookReference = new BookReference(); - - string bookString = values[0]; - (Book? book, int edition, int volume) = ParseBookString(bookString); - bookReference.Book = book; - bookReference.Edition = edition; - bookReference.Volume = volume; - if (!string.IsNullOrEmpty(values[1])) - bookReference.PageNumbers = values[1]; - parsed = true; - } - } - - return parsed; - } - - private static (Book? book, int edition, int volume) ParseBookString(string bookString) - { - Book? book = null; - int edition = 0; - int volume = 0; - var col = HttpUtility.ParseQueryString(bookString); - if (col != null && col.Count > 0) - { - string? bookCode = col[_bookCodeId]; - string? bookEdition = col[_bookEditionId]; - string? bookVolume = col[_bookVolumeId]; - if (!string.IsNullOrEmpty(bookCode)) - book = BookStore.Books.FirstOrDefault(x => x.Code == bookCode); - if (int.TryParse(bookEdition, out int edNo)) - edition = edNo; - if (int.TryParse(bookVolume, out int volNo)) - volume = volNo; - } - - return (book, edition, volume); - } - - public override string ToString() - { - var col = HttpUtility.ParseQueryString(string.Empty); - col.Add(_bookCodeId, _book?.Code ?? string.Empty); - col.Add(_bookEditionId, _edition.ToString()); - col.Add(_bookVolumeId, _volume.ToString()); - return col.ToString() + ParserHelper.BookReferenceDelimiter + _pageNumbers; - } - - public string GetPreviewText() - { - return $"{Book?.Title} by {Book?.Authors}, " + - $"Edition: {Edition}, Volume: {Volume}, Page Numbers: {PageNumbers}"; - } -} diff --git a/src/Symptum.Core/Subjects/Books/BookStore.cs b/src/Symptum.Core/Subjects/Books/BookStore.cs index 7e41b78..2bc76cf 100644 --- a/src/Symptum.Core/Subjects/Books/BookStore.cs +++ b/src/Symptum.Core/Subjects/Books/BookStore.cs @@ -30,7 +30,7 @@ public static void LoadBooks(string csv) var books = csvReader.GetRecords(); foreach (var book in books) { - string subCode = book.Code[..2]; + string subCode = book.Id[..2]; book.Subject = SubjectMap.SubjectCodes.FirstOrDefault(x => x.Key == subCode).Value; Books.Add(book); } diff --git a/src/Symptum.Core/Subjects/QuestionBanks/QuestionEntry.cs b/src/Symptum.Core/Subjects/QuestionBanks/QuestionEntry.cs index 2ec1b7d..773d425 100644 --- a/src/Symptum.Core/Subjects/QuestionBanks/QuestionEntry.cs +++ b/src/Symptum.Core/Subjects/QuestionBanks/QuestionEntry.cs @@ -1,7 +1,7 @@ using CommunityToolkit.Mvvm.ComponentModel; using CsvHelper.Configuration.Attributes; +using Symptum.Core.Data.Bibliography; using Symptum.Core.Extensions; -using Symptum.Core.Subjects.Books; using Symptum.Core.TypeConversion; namespace Symptum.Core.Subjects.QuestionBanks; @@ -73,22 +73,13 @@ public List? ProbableCases set => SetProperty(ref probableCases, value); } - private List? bookReferences; + private List? references; - [TypeConverter(typeof(BookReferenceListConverter))] - public List? BookReferences - { - get => bookReferences; - set => SetProperty(ref bookReferences, value); - } - - private List? linkReferences; - - [TypeConverter(typeof(UriListConverter))] - public List? LinkReferences + [TypeConverter(typeof(ReferenceListConverter))] + public List? References { - get => linkReferences; - set => SetProperty(ref linkReferences, value); + get => references; + set => SetProperty(ref references, value); } #endregion @@ -104,8 +95,7 @@ public QuestionEntry Clone() Importance = importance, YearsAsked = yearsAsked.CloneList(), ProbableCases = probableCases.CloneList(), - BookReferences = bookReferences.CloneList(x => new() { Book = x.Book, Edition = x.Edition, Volume = x.Volume, PageNumbers = x.PageNumbers }), - LinkReferences = linkReferences.CloneList() + References = references.CloneList(x => x with { }) }; } @@ -143,3 +133,30 @@ public int CompareTo(object? obj) return CompareTo(obj as QuestionEntry); } } + +public class QuestionEntryO +{ + [TypeConverter(typeof(QuestionIdConverter))] + public QuestionId Id { get; set; } + + public string Title { get; set; } + + [TypeConverter(typeof(StringListConverter))] + public List Descriptions { get; set; } + + public bool HasPreviouslyBeenAsked { get; set; } + + public int Importance { get; set; } + + [TypeConverter(typeof(DateOnlyListConverter))] + public List YearsAsked { get; set; } + + [TypeConverter(typeof(StringListConverter))] + public List ProbableCases { get; set; } + + [TypeConverter(typeof(BookReferenceListConverter))] + public List BookReferences { get; set; } + + [TypeConverter(typeof(UriListConverter))] + public List LinkReferences { get; set; } +} diff --git a/src/Symptum.Core/Symptum.Core.csproj b/src/Symptum.Core/Symptum.Core.csproj index b6ddc07..7be4f44 100644 --- a/src/Symptum.Core/Symptum.Core.csproj +++ b/src/Symptum.Core/Symptum.Core.csproj @@ -1,7 +1,7 @@ - net8.0 + net9.0 diff --git a/src/Symptum.Core/TypeConversion/Converters.cs b/src/Symptum.Core/TypeConversion/Converters.cs index c6e5720..2093696 100644 --- a/src/Symptum.Core/TypeConversion/Converters.cs +++ b/src/Symptum.Core/TypeConversion/Converters.cs @@ -3,10 +3,10 @@ using CsvHelper.Configuration; using CsvHelper.TypeConversion; using Symptum.Core.Data; +using Symptum.Core.Data.Bibliography; using Symptum.Core.Data.Nutrition; using Symptum.Core.Data.ReferenceValues; using Symptum.Core.Helpers; -using Symptum.Core.Subjects.Books; using Symptum.Core.Subjects.QuestionBanks; namespace Symptum.Core.TypeConversion; @@ -83,6 +83,11 @@ public class QuantityCsvConverter : DefaultTypeConverter } } +public class ReferenceListConverter : ListConverter +{ + public override void ValidateData(string text, List list) => ListToStringConversion.ValidateDataForReference(text, list); +} + #endregion #region Nutrition @@ -166,6 +171,14 @@ public static void ValidateDataForBookReference(string text, List } } + public static void ValidateDataForReference(string text, List list) + { + if (ReferenceBase.TryParse(text, out ReferenceBase? reference)) + { + list.Add(reference); + } + } + public static void ValidateDataForReferenceValueEntry(string text, List list) { if (ReferenceValueEntry.TryParse(text, out ReferenceValueEntry? entry)) @@ -182,10 +195,7 @@ public static void ValidateDataForFoodMeasure(string text, List lis } } - public static string ElementToStringForDateOnly(DateOnly data) - { - return data.ToString("yyyy-MM"); - } + public static string ElementToStringForDateOnly(DateOnly data) => data.ToString("yyyy-MM"); public static string ElementToStringDefault(T? data) => data?.ToString() ?? string.Empty; } diff --git a/src/Symptum.Editor/App.xaml b/src/Symptum.Editor/App.xaml index f9f069b..9c090cc 100644 --- a/src/Symptum.Editor/App.xaml +++ b/src/Symptum.Editor/App.xaml @@ -12,13 +12,13 @@ + - + - diff --git a/src/Symptum.Editor/App.xaml.cs b/src/Symptum.Editor/App.xaml.cs index 8414cfe..2964a8a 100644 --- a/src/Symptum.Editor/App.xaml.cs +++ b/src/Symptum.Editor/App.xaml.cs @@ -81,6 +81,9 @@ private async Task LoadAllBookListsAsync() file = await StorageFile.GetFileFromApplicationUriAsync(new Uri("ms-appx:///Assets/Books/Third Year Books.csv")); content = await FileIO.ReadTextAsync(file); BookStore.LoadBooks(content); + file = await StorageFile.GetFileFromApplicationUriAsync(new Uri("ms-appx:///Assets/Books/Final Year Books.csv")); + content = await FileIO.ReadTextAsync(file); + BookStore.LoadBooks(content); } catch { } } diff --git a/src/Symptum.Editor/Controls/AddNewItemDialog.xaml.cs b/src/Symptum.Editor/Controls/AddNewItemDialog.xaml.cs index fcd281a..07c49a4 100644 --- a/src/Symptum.Editor/Controls/AddNewItemDialog.xaml.cs +++ b/src/Symptum.Editor/Controls/AddNewItemDialog.xaml.cs @@ -140,22 +140,3 @@ private void FilterItems(IResource? parentResource) availItemTypes = items; } } - -public class NewItemType -{ - public string? DisplayName { get; set; } - - public Type? Type { get; set; } - - public string? GroupName { get; set; } - - public NewItemType() - { } - - public NewItemType(string displayName, Type type, string? groupName = null) - { - DisplayName = displayName; - Type = type; - GroupName = groupName; - } -} diff --git a/src/Symptum.Editor/Controls/BookReferencePicker.xaml b/src/Symptum.Editor/Controls/BookReferencePicker.xaml index d64f594..732c75f 100644 --- a/src/Symptum.Editor/Controls/BookReferencePicker.xaml +++ b/src/Symptum.Editor/Controls/BookReferencePicker.xaml @@ -68,7 +68,7 @@ Header="Volume" Minimum="0" SpinButtonPlacementMode="Inline" /> + Header="Pages" />