Skip to content

Commit

Permalink
feat: experiments with editor.js
Browse files Browse the repository at this point in the history
  • Loading branch information
SonicGD committed Apr 3, 2024
1 parent 4b48bae commit 752df09
Show file tree
Hide file tree
Showing 13 changed files with 483 additions and 65 deletions.
15 changes: 15 additions & 0 deletions Sitko.Blockly.sln
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sitko.Blockly.Demo.Client",
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sitko.Blockly.Data", "apps\Sitko.Blockly.Data\Sitko.Blockly.Data.csproj", "{88B081A7-F838-4E90-BB2E-581BAFAECEA6}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sitko.EditorJS", "src\Sitko.EditorJS\Sitko.EditorJS.csproj", "{8103ED8B-B508-438F-8180-B2EF88ED20F2}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -203,6 +205,18 @@ Global
{88B081A7-F838-4E90-BB2E-581BAFAECEA6}.Release|x64.Build.0 = Release|Any CPU
{88B081A7-F838-4E90-BB2E-581BAFAECEA6}.Release|x86.ActiveCfg = Release|Any CPU
{88B081A7-F838-4E90-BB2E-581BAFAECEA6}.Release|x86.Build.0 = Release|Any CPU
{8103ED8B-B508-438F-8180-B2EF88ED20F2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{8103ED8B-B508-438F-8180-B2EF88ED20F2}.Debug|Any CPU.Build.0 = Debug|Any CPU
{8103ED8B-B508-438F-8180-B2EF88ED20F2}.Debug|x64.ActiveCfg = Debug|Any CPU
{8103ED8B-B508-438F-8180-B2EF88ED20F2}.Debug|x64.Build.0 = Debug|Any CPU
{8103ED8B-B508-438F-8180-B2EF88ED20F2}.Debug|x86.ActiveCfg = Debug|Any CPU
{8103ED8B-B508-438F-8180-B2EF88ED20F2}.Debug|x86.Build.0 = Debug|Any CPU
{8103ED8B-B508-438F-8180-B2EF88ED20F2}.Release|Any CPU.ActiveCfg = Release|Any CPU
{8103ED8B-B508-438F-8180-B2EF88ED20F2}.Release|Any CPU.Build.0 = Release|Any CPU
{8103ED8B-B508-438F-8180-B2EF88ED20F2}.Release|x64.ActiveCfg = Release|Any CPU
{8103ED8B-B508-438F-8180-B2EF88ED20F2}.Release|x64.Build.0 = Release|Any CPU
{8103ED8B-B508-438F-8180-B2EF88ED20F2}.Release|x86.ActiveCfg = Release|Any CPU
{8103ED8B-B508-438F-8180-B2EF88ED20F2}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{0367FAD9-C3FD-4E07-9CBE-103A17666A1D} = {DA312F56-FDB4-4853-A7A1-A8B2527399FC}
Expand All @@ -217,5 +231,6 @@ Global
{4B682521-01D4-4A3E-9F15-16DBA1FB91C9} = {DA312F56-FDB4-4853-A7A1-A8B2527399FC}
{4C374AF7-0748-4915-988D-0338996B6AF9} = {32D6C989-DF2C-4C06-BD48-C322E72888B9}
{88B081A7-F838-4E90-BB2E-581BAFAECEA6} = {32D6C989-DF2C-4C06-BD48-C322E72888B9}
{8103ED8B-B508-438F-8180-B2EF88ED20F2} = {DA312F56-FDB4-4853-A7A1-A8B2527399FC}
EndGlobalSection
EndGlobal
119 changes: 57 additions & 62 deletions apps/Sitko.Blockly.Demo.Client/Pages/PostFormComponent.razor
Original file line number Diff line number Diff line change
@@ -1,18 +1,13 @@
@using Sitko.Blockly.Blocks
@using Sitko.Blockly.Blazor
@using Sitko.Blockly.Blazor.Forms
@using Sitko.Core.Storage
@using Sitko.Blazor.CKEditor.Bundle
@using Sitko.Blockly.Data
@using Sitko.Blockly.Data.Entities
@using Sitko.Blockly.Data.Entities

@inherits BaseComponent
<PostForm EntityId="PostId" OnAfterCreate="post => GoToPost(post)" Debug="true">
<MudItem>
<MudTextField Label="Title" @bind-Value="context.Entity.Title" For="() => context.Entity.Title"/>
</MudItem>
<MudBlocklyForm @bind-Value="context.Entity.Blocks" Options="blocksOptions"></MudBlocklyForm>
<MudBlocklyForm Label="Secondary blocks" @bind-Value="context.Entity.SecondaryBlocks" Options="secondaryBlocksOptions"></MudBlocklyForm>
@* <MudBlocklyForm @bind-Value="context.Entity.Blocks" Options="blocksOptions"></MudBlocklyForm> *@
@* <MudBlocklyForm Label="Secondary blocks" @bind-Value="context.Entity.SecondaryBlocks" Options="secondaryBlocksOptions"></MudBlocklyForm> *@
<EditorJS />
<MudButton Variant="Variant.Filled" Color="Color.Primary" Disabled="@(!context.Form.CanSave())" OnClick="@context.Form.SaveEntityAsync">Save</MudButton>
<MudButton Variant="Variant.Outlined" Color="Color.Secondary" Disabled="@(!context.Form.HasChanges)" OnClick="@context.Form.ResetAsync">Reset</MudButton>
</PostForm>
Expand All @@ -28,59 +23,59 @@
return Task.CompletedTask;
}

private MudBlazorBlocklyFormOptions? blocksOptions;
private MudBlazorBlocklyFormOptions? secondaryBlocksOptions;
// private MudBlazorBlocklyFormOptions? blocksOptions;
// private MudBlazorBlocklyFormOptions? secondaryBlocksOptions;
protected override void Initialize()
{
base.Initialize();
var imagesStorageOptions = new BlockFormStorageOptions
{
UploadPath = "posts/images",
MaxAllowedFiles = 10,
MaxFileSize = 2 * 1024 * 1024, // 2Mb
GenerateMetadata = (_, _) =>
{
var metadata = new TestMetadata(Guid.NewGuid(), "Image");
return Task.FromResult<object>(metadata);
}
};
var filesStorageOptions = new BlockFormStorageOptions
{
UploadPath = "posts/images",
MaxAllowedFiles = 10,
MaxFileSize = 100 * 1024 * 1024, // 100Mb
GenerateMetadata = (_, _) =>
{
var metadata = new TestMetadata(Guid.NewGuid(), "File");
return Task.FromResult<object>(metadata);
}
};
var ckEditorConfig = CKEditorBundleOptions.DefaultConfig.WithHtmlEditing();
ckEditorConfig.Language = "ru";
blocksOptions = new MudBlazorBlocklyFormOptions
{
Storage = GetService<IStorage>(),
ImagesOptions = imagesStorageOptions,
FilesOptions = filesStorageOptions, CKEditorConfig = ckEditorConfig
};
blocksOptions.DisableBlocksDelete(new[] { typeof(TextBlock), typeof(CutBlock), typeof(GalleryBlock), typeof(YoutubeBlock) });
blocksOptions.DisableBlocksMove(new[] { typeof(CutBlock), typeof(GalleryBlock) });

secondaryBlocksOptions = new MudBlazorBlocklyFormOptions
{
MaxBlocks = 5, Storage = GetService<IStorage>(),
ImagesOptions = imagesStorageOptions,
FilesOptions = filesStorageOptions
};
secondaryBlocksOptions.AddAllowedBlock<TextBlock>();
secondaryBlocksOptions.AddAllowedBlock<GalleryBlock>();
secondaryBlocksOptions.AddAllowedBlock<YoutubeBlock>();
secondaryBlocksOptions.ConfigureBlockPriority<YoutubeBlock>(1);
secondaryBlocksOptions.ConfigureBlockPriority<TextBlock>(2);
secondaryBlocksOptions.ConfigureBlockPriority<GalleryBlock>(3);
secondaryBlocksOptions.ConfigureBlockMaxCount<GalleryBlock>(1);
secondaryBlocksOptions.ConfigureBlockMaxCount<YoutubeBlock>(1);
}
// protected override void Initialize()
// {
// base.Initialize();
// var imagesStorageOptions = new BlockFormStorageOptions
// {
// UploadPath = "posts/images",
// MaxAllowedFiles = 10,
// MaxFileSize = 2 * 1024 * 1024, // 2Mb
// GenerateMetadata = (_, _) =>
// {
// var metadata = new TestMetadata(Guid.NewGuid(), "Image");
// return Task.FromResult<object>(metadata);
// }
// };
// var filesStorageOptions = new BlockFormStorageOptions
// {
// UploadPath = "posts/images",
// MaxAllowedFiles = 10,
// MaxFileSize = 100 * 1024 * 1024, // 100Mb
// GenerateMetadata = (_, _) =>
// {
// var metadata = new TestMetadata(Guid.NewGuid(), "File");
// return Task.FromResult<object>(metadata);
// }
// };
// var ckEditorConfig = CKEditorBundleOptions.DefaultConfig.WithHtmlEditing();
// ckEditorConfig.Language = "ru";
// blocksOptions = new MudBlazorBlocklyFormOptions
// {
// Storage = GetService<IStorage>(),
// ImagesOptions = imagesStorageOptions,
// FilesOptions = filesStorageOptions, CKEditorConfig = ckEditorConfig
// };
// blocksOptions.DisableBlocksDelete(new[] { typeof(TextBlock), typeof(CutBlock), typeof(GalleryBlock), typeof(YoutubeBlock) });
// blocksOptions.DisableBlocksMove(new[] { typeof(CutBlock), typeof(GalleryBlock) });
//
// secondaryBlocksOptions = new MudBlazorBlocklyFormOptions
// {
// MaxBlocks = 5, Storage = GetService<IStorage>(),
// ImagesOptions = imagesStorageOptions,
// FilesOptions = filesStorageOptions
// };
// secondaryBlocksOptions.AddAllowedBlock<TextBlock>();
// secondaryBlocksOptions.AddAllowedBlock<GalleryBlock>();
// secondaryBlocksOptions.AddAllowedBlock<YoutubeBlock>();
// secondaryBlocksOptions.ConfigureBlockPriority<YoutubeBlock>(1);
// secondaryBlocksOptions.ConfigureBlockPriority<TextBlock>(2);
// secondaryBlocksOptions.ConfigureBlockPriority<GalleryBlock>(3);
// secondaryBlocksOptions.ConfigureBlockMaxCount<GalleryBlock>(1);
// secondaryBlocksOptions.ConfigureBlockMaxCount<YoutubeBlock>(1);
// }
}
4 changes: 4 additions & 0 deletions apps/Sitko.Blockly.Demo.Client/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
using Sitko.Core.Repository.Remote;
using Sitko.Core.Repository.Remote.Wasm;
using Sitko.Core.Storage.Remote;
using Sitko.EditorJS;

var builder = WebAssemblyHostBuilder.CreateDefault(args);

Expand All @@ -32,6 +33,9 @@
context.Configuration.Bind(context.IsDevelopment() ? "HttpRoutes:Development" : "HttpRoutes:Production");
});

builder.Services.AddEditorJS()
.AddBlock<ParagraphBlock, ParagraphBlockOptions>((configuration, options) => { })
.AddBlock<SimpleImageBlock, SimpleImageBlockOptions>((configuration, options) => { });

builder.ConfigureLocalization("ru-RU");

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

<ItemGroup>
<ProjectReference Include="..\..\src\Sitko.Blockly.MudBlazor\Sitko.Blockly.MudBlazor.csproj"/>
<ProjectReference Include="..\..\src\Sitko.EditorJS\Sitko.EditorJS.csproj" />
<ProjectReference Include="..\Sitko.Blockly.Data\Sitko.Blockly.Data.csproj"/>
</ItemGroup>
<ItemGroup>
Expand Down
6 changes: 3 additions & 3 deletions apps/Sitko.Blockly.Demo.Client/_Imports.razor
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@
@using Sitko.Blockly.Demo.Client
@using Sitko.Blockly.Demo.Client.Layout
@using MudBlazor
@using Sitko.Blockly.MudBlazorComponents.Forms
@using Sitko.Blockly.MudBlazorComponents.Display
@* @using Sitko.Blockly.MudBlazorComponents.Forms *@
@* @using Sitko.Blockly.MudBlazorComponents.Display *@
@using Sitko.Core.Blazor.Components
@using Sitko.Core.Blazor.MudBlazorComponents

@using Sitko.EditorJS
5 changes: 5 additions & 0 deletions apps/Sitko.Blockly.Demo/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
using Sitko.Core.Repository.EntityFrameworkCore;
using Sitko.Core.Storage.FileSystem;
using Sitko.Core.Storage.Metadata.Postgres;
using Sitko.EditorJS;

var builder = WebApplication.CreateBuilder(args);
builder
Expand All @@ -30,6 +31,10 @@
.AddFileSystemStorage<BlocklyStorageOptions>()
.AddPostgresStorageMetadata<BlocklyStorageOptions>();

builder.Services.AddEditorJS()
.AddBlock<ParagraphBlock, ParagraphBlockOptions>((configuration, options) => { })
.AddBlock<SimpleImageBlock, SimpleImageBlockOptions>((configuration, options) => { });

var app = builder.Build();

// Configure the HTTP request pipeline.
Expand Down
9 changes: 9 additions & 0 deletions src/Sitko.EditorJS/EditorJS.razor
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<div style="margin-top: 10px; margin-bottom: 10px;" id="@Id"></div>

<pre>
@Data
</pre>

@code {

}
110 changes: 110 additions & 0 deletions src/Sitko.EditorJS/EditorJS.razor.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
using System.Text.Json;
using System.Text.Json.Serialization;
using Microsoft.AspNetCore.Components;
using Microsoft.Extensions.Options;
using Microsoft.JSInterop;
using Sitko.Blazor.ScriptInjector;

namespace Sitko.EditorJS;

public partial class EditorJS : ComponentBase, IAsyncDisposable
{
private static readonly JsonSerializerOptions JsonOptions = new()
{
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull
};

private DotNetObjectReference<EditorJS>? instance;
private bool rendered;
[Inject] protected IScriptInjector ScriptInjector { get; set; } = null!;
[Inject] protected IBlocksAccessor BlocksAccessor { get; set; } = null!;
[Inject] protected IOptions<EditorJSOptions> EditorJSOptions { get; set; } = null!;
[Inject] protected IJSRuntime JsRuntime { get; set; } = null!;
protected ElementReference EditorRef { get; set; }
[Parameter] public EditorJSConfig? Config { get; set; }
private string Data { get; set; } = "";

public Guid Id { get; } = Guid.NewGuid();

public ValueTask DisposeAsync()
{
GC.SuppressFinalize(this);
instance?.Dispose();
return DestroyEditor();
}

protected override async Task OnAfterRenderAsync(bool firstRender)
{
await base.OnAfterRenderAsync(firstRender);
if (firstRender)
{
instance = DotNetObjectReference.Create(this);

var config = GetConfig();
var injectRequests = new List<InjectRequest>
{
ScriptInjectRequest.FromUrl("SitkoEditorJS", "_content/Sitko.EditorJS/EditorJS.razor.js",
InjectScope.Scoped),
ScriptInjectRequest.FromUrl("editorjs", EditorJSOptions.Value.EditorJSScriptUrl, InjectScope.Scoped)
};
foreach (var (key, script) in BlocksAccessor.GetScripts())
{
injectRequests.Add(ScriptInjectRequest.FromUrl($"editorjs-{key}", script, InjectScope.Scoped));
}
// if (!string.IsNullOrEmpty(OptionsProvider.Options.StylePath))
// {
// injectRequests.Add(CssInjectRequest.FromUrl($"{OptionsProvider.Options.EditorClassName}Css",
// OptionsProvider.Options.StylePath));
// }

// foreach (var (key, path) in OptionsProvider.Options.GetAdditionalScripts(config))
// {
// injectRequests.Add(ScriptInjectRequest.FromUrl(key, path));
// }

await ScriptInjector.InjectAsync(injectRequests, InitializeEditorAsync);
}
}

private async Task InitializeEditorAsync(CancellationToken cancellationToken)
{
await JsRuntime.InvokeVoidAsync("window.SitkoEditorJS.init", cancellationToken, Id.ToString(),
JsonSerializer.Serialize(GetConfig(), JsonOptions), instance);
rendered = true;
}

private EditorJSConfig? GetConfig() => Config ?? BlocksAccessor.GetConfig(Id.ToString());


protected ValueTask DestroyEditor()
{
rendered = false;
return JsRuntime.InvokeVoidAsync("window.SitkoEditorJS.destroy", Id);
}

[JSInvokable]
public Task OnSave(string data)
{
using var jDoc = JsonDocument.Parse(data);
Data = JsonSerializer.Serialize(jDoc, new JsonSerializerOptions { WriteIndented = true });
StateHasChanged();
return Task.CompletedTask;
}

// private async ValueTask UpdateEditorAsync() =>
// await JsRuntime.InvokeVoidAsync("window.SitkoBlazorCKEditor.update", Id, EditorValue);
}

public record EditorJSConfig
{
[JsonPropertyName("holder")] public required string Holder { get; init; }

[JsonPropertyName("tools")] public Dictionary<string, EditorJSToolConfig> Tools { get; } = new();
}

public record EditorJSToolConfig
{
[JsonPropertyName("className")] public required string ClassName { get; init; }
[JsonPropertyName("config")] public required ContentBlockConfig Config { get; init; }
}
1 change: 1 addition & 0 deletions src/Sitko.EditorJS/EditorJS.razor.css
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@

Loading

0 comments on commit 752df09

Please sign in to comment.