Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

OSOE-751: Upgrade to Orchard Core 1.8 #124

Merged
merged 23 commits into from
Feb 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions Controllers/DatabaseStorageController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ public async Task<IActionResult> CreateBooksPost()
foreach (var book in CreateDemoBooks())
{
// So now you understand what will happen in the background when this service is being called.
_session.Save(book);
await _session.SaveAsync(book);
}

await _notifier.InformationAsync(H["Books have been created in the database."]);
Expand Down Expand Up @@ -102,7 +102,7 @@ public async Task<IActionResult> JKRosenzweigBooks()

// NEXT STATION: Models/PersonPart.cs

private static IEnumerable<Book> CreateDemoBooks() =>
private static Book[] CreateDemoBooks() =>
new[]
{
new Book
Expand Down
2 changes: 1 addition & 1 deletion Controllers/FileManagementController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ public async Task<string> ReadFileFromMediaFolder()
// If you want to extract the content of the file use a StreamReader to read the stream.
using var stream = await _mediaFileStore.GetFileStreamAsync(TestFileRelativePath);
using var streamReader = new StreamReader(stream);
var content = await streamReader.ReadToEndAsync();
var content = await streamReader.ReadToEndAsync(HttpContext.RequestAborted);

return $"File content: {content}";
}
Expand Down
5 changes: 1 addition & 4 deletions Controllers/PersonListController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -110,11 +110,8 @@ public async Task<string> FountainOfEternalYouth()
{
part.BirthDateUtc = eighteenYearOld;

// False alarm, this is not a loop.
#pragma warning disable S1643 // Strings should not be concatenated using '+' in a loop
// You can also edit content fields:
part.Biography.Text += " I'm young again!";
#pragma warning restore S1643 // Strings should not be concatenated using '+' in a loop
});

// If you happen to use reusable/named parts like BagPart (see the docs on it here:
Expand All @@ -138,7 +135,7 @@ public async Task<string> FountainOfEternalYouth()
// IContentManager.GetAsync() instead.

return "People modified: " +
(oldPeople.Any() ?
(oldPeople.Count != 0 ?
string.Join(", ", oldPeople.Select(person => person.As<PersonPart>().Name)) :
"Nobody. Did you create people older than 90?");

Expand Down
2 changes: 0 additions & 2 deletions Controllers/SiteSettingsController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,6 @@
using Lombiq.TrainingDemo.Models;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Options;
using OrchardCore.ContentManagement;
using OrchardCore.Entities;
using OrchardCore.Settings;
using System.Threading.Tasks;

Expand Down
12 changes: 5 additions & 7 deletions Drivers/ColorFieldDisplayDriver.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,14 @@
using OrchardCore.ContentManagement.Metadata.Models;
using OrchardCore.DisplayManagement.ModelBinding;
using OrchardCore.DisplayManagement.Views;
using System;
using System.Text.RegularExpressions;
using System.Threading.Tasks;

namespace Lombiq.TrainingDemo.Drivers;

// You shouldn't be surprised - content fields also have display drivers. ContentFieldDisplayDriver is specifically for
// content fields. Don't forget to register this class with the service provider (see: Startup.cs).
public class ColorFieldDisplayDriver : ContentFieldDisplayDriver<ColorField>
public partial class ColorFieldDisplayDriver : ContentFieldDisplayDriver<ColorField>
{
private readonly IStringLocalizer T;

Expand Down Expand Up @@ -75,11 +74,7 @@ public override async Task<IDisplayResult> UpdateAsync(ColorField field, IUpdate

// Also some custom validation for our ColorField hex value.
var isInvalidHexColor = !string.IsNullOrWhiteSpace(viewModel.Value) &&
!Regex.IsMatch(
viewModel.Value,
"^#([A-Fa-f0-9]{8}|[A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$",
RegexOptions.ExplicitCapture,
TimeSpan.FromSeconds(1));
!RegexExpression().IsMatch(viewModel.Value);

if (isInvalidHexColor) updater.ModelState.AddModelError(Prefix, T["The given color is invalid."]);

Expand All @@ -89,6 +84,9 @@ public override async Task<IDisplayResult> UpdateAsync(ColorField field, IUpdate

return await EditAsync(field, context);
}

[GeneratedRegex("^#([A-Fa-f0-9]{8}|[A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$", RegexOptions.ExplicitCapture, matchTimeoutMilliseconds: 1000)]
private static partial Regex RegexExpression();
}

// END OF TRAINING SECTION: Content Field development
Expand Down
36 changes: 18 additions & 18 deletions Lombiq.TrainingDemo.csproj
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
<Project Sdk="Microsoft.NET.Sdk.Razor">
<Project Sdk="Microsoft.NET.Sdk.Razor">

<Import Project="..\..\Utilities\Lombiq.NodeJs.Extensions\Lombiq.NodeJs.Extensions\Lombiq.NodeJs.Extensions.props" />

<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<TargetFramework>net8.0</TargetFramework>
<AddRazorSupportForMvc>true</AddRazorSupportForMvc>
<Title>Lombiq Training Demo for Orchard Core</Title>
<Description>Orchard Core training demo module for teaching Orchard Core fundamentals primarily by going through its source code.</Description>
Expand All @@ -23,29 +23,29 @@
</ItemGroup>

<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="7.0.0" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="7.0.0" />
<PackageReference Include="OrchardCore.Users.Abstractions" Version="1.7.0" />
<PackageReference Include="OrchardCore.Workflows.Abstractions" Version="1.7.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="8.0.0" />
Piedone marked this conversation as resolved.
Show resolved Hide resolved
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="8.0.0" />
<PackageReference Include="OrchardCore.Users.Abstractions" Version="1.8.2" />
<PackageReference Include="OrchardCore.Workflows.Abstractions" Version="1.8.2" />
</ItemGroup>

<ItemGroup>
<PackageReference Include="OrchardCore.BackgroundTasks" Version="1.7.0" />
<PackageReference Include="OrchardCore.ContentFields" Version="1.7.0" />
<PackageReference Include="OrchardCore.ContentManagement" Version="1.7.0" />
<PackageReference Include="OrchardCore.ContentTypes.Abstractions" Version="1.7.0" />
<PackageReference Include="OrchardCore.Data.Abstractions" Version="1.7.0" />
<PackageReference Include="OrchardCore.DynamicCache" Version="1.7.0" />
<PackageReference Include="OrchardCore.FileStorage.FileSystem" Version="1.7.0" />
<PackageReference Include="OrchardCore.Indexing.Abstractions" Version="1.7.0" />
<PackageReference Include="OrchardCore.Media.Abstractions" Version="1.7.0" />
<PackageReference Include="OrchardCore.Module.Targets" Version="1.7.0" />
<PackageReference Include="OrchardCore.BackgroundTasks" Version="1.8.2" />
<PackageReference Include="OrchardCore.ContentFields" Version="1.8.2" />
<PackageReference Include="OrchardCore.ContentManagement" Version="1.8.2" />
<PackageReference Include="OrchardCore.ContentTypes.Abstractions" Version="1.8.2" />
<PackageReference Include="OrchardCore.Data.Abstractions" Version="1.8.2" />
<PackageReference Include="OrchardCore.DynamicCache" Version="1.8.2" />
<PackageReference Include="OrchardCore.FileStorage.FileSystem" Version="1.8.2" />
<PackageReference Include="OrchardCore.Indexing.Abstractions" Version="1.8.2" />
<PackageReference Include="OrchardCore.Media.Abstractions" Version="1.8.2" />
<PackageReference Include="OrchardCore.Module.Targets" Version="1.8.2" />
<!-- Note that you need to add a reference to OrchardCore.ResourceManagement for the basic tag helpers like <style>
and <script> to properly work when the app is built for production (and thus Razor Runtime Compilation is turned
off. OrchardCore.DisplayManagement is needed for a variety of things but also for the <shape> tag helper for the
same reason. -->
<PackageReference Include="OrchardCore.ResourceManagement" Version="1.7.0" />
<PackageReference Include="OrchardCore.DisplayManagement" Version="1.7.0" />
<PackageReference Include="OrchardCore.ResourceManagement" Version="1.8.2" />
<PackageReference Include="OrchardCore.DisplayManagement" Version="1.8.2" />
</ItemGroup>

<ItemGroup>
Expand Down
12 changes: 6 additions & 6 deletions Manifest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,8 @@
// feature then you need to include them in this list. Orchard Core will make sure to enable all dependent features
// when you enable a feature that has dependencies. Without this some features would not work even if the assembly
// is referenced in the project.
Dependencies = new[]
{
Dependencies =
[
"OrchardCore.Admin",
"OrchardCore.Apis.GraphQL",
"OrchardCore.BackgroundTasks",
Expand All @@ -64,7 +64,7 @@
"OrchardCore.Themes",
"OrchardCore.Users",
"OrchardCore.Workflows",
}
]
)]

// And we also have a second feature!
Expand All @@ -77,10 +77,10 @@
Category = "Training",
Description = "Demonstrates how to write middlewares in a separate feature.",
// It's usual for sub-features to depend on the base feature but this is not mandatory.
Dependencies = new[]
{
Dependencies =
[
"Lombiq.TrainingDemo",
}
]
)]

// How do you distinguish what's activated when turning on a feature? With the same Feature attribute! Check out the
Expand Down
11 changes: 6 additions & 5 deletions Migrations/BookMigrations.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

using Lombiq.TrainingDemo.Indexes;
using OrchardCore.Data.Migration;
using System.Threading.Tasks;
using YesSql.Sql;

namespace Lombiq.TrainingDemo.Migrations;
Expand All @@ -17,9 +18,9 @@ public class BookMigrations : DataMigration
{
// Migrations have Create() and UpdateFromX methods. When the module is first enabled the Create() is called so it
// can set up DB tables.
public int Create()
public async Task<int> CreateAsync()
{
SchemaBuilder.CreateMapIndexTable<BookIndex>(table => table
await SchemaBuilder.CreateMapIndexTableAsync<BookIndex>(table => table
.Column<string>(nameof(BookIndex.Author))
// Titles of books can be really long sometimes (even as long as 26000 characters:
// https://www.guinnessworldrecords.com/world-records/358711-longest-title-of-a-book) so we have to make
Expand All @@ -31,7 +32,7 @@ public int Create()
// Let's suppose that we'll store many books, tens of thousands in the database. In this case, it's also advised
// to add SQL indices to columns that are frequently queried on. In our case, Author is like this so we add an
// index below. Note that you can only add indices in AlterTable().
SchemaBuilder.AlterTable(nameof(BookIndex), table => table
await SchemaBuilder.AlterTableAsync(nameof(BookIndex), table => table
.CreateIndex($"IDX_{nameof(BookIndex)}_{nameof(BookIndex.Author)}", nameof(BookIndex.Author))
);

Expand All @@ -44,13 +45,13 @@ public int Create()
// already enabled before and the create method was run (like when you update a module already running on an Orchard
// site). The X in UpdateFromX is the version number of the update (the method's name is conventional). It means:
// "run this update if the module's current migration version is X". This method will run if it's 1.
public int UpdateFrom1()
public async Task<int> UpdateFrom1Async()
{
// The initial version of our module did not store the book's title. We quickly fix the issue by pushing out an
// update that modifies the schema to add the Name. Remember, we've returned 2 in the Create method so this
// update method won't be executed in a fresh setup. This is why you need to include all these changes in the
// Create method as well.
SchemaBuilder.AlterTable(nameof(BookIndex), table => table
await SchemaBuilder.AlterTableAsync(nameof(BookIndex), table => table
.AddColumn<string>(nameof(BookIndex.Title))
);

Expand Down
11 changes: 6 additions & 5 deletions Migrations/PersonMigrations.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
using OrchardCore.ContentManagement.Metadata.Settings;
using OrchardCore.Data.Migration;
using System;
using System.Threading.Tasks;
using YesSql.Sql;
using static Lombiq.HelpfulLibraries.OrchardCore.Contents.ContentFieldEditorEnums;

Expand All @@ -22,10 +23,10 @@ public class PersonMigrations : DataMigration

public PersonMigrations(IContentDefinitionManager contentDefinitionManager) => _contentDefinitionManager = contentDefinitionManager;

public int Create()
public async Task<int> CreateAsync()
{
// Now you can configure PersonPart. For example you can add content fields (as mentioned earlier) here.
_contentDefinitionManager.AlterPartDefinition(nameof(PersonPart), part => part
await _contentDefinitionManager.AlterPartDefinitionAsync(nameof(PersonPart), part => part
// Each field has its own configuration. Here you will give a display name for it and add some additional
// settings like a hint to be displayed in the editor.
.WithField(nameof(PersonPart.Biography), field => field
Expand All @@ -39,7 +40,7 @@ public int Create()
);

// This one will create an index table for the PersonPartIndex as explained in the BookMigrations file.
SchemaBuilder.CreateMapIndexTable<PersonPartIndex>(table => table
await SchemaBuilder.CreateMapIndexTableAsync<PersonPartIndex>(table => table
.Column<DateTime>(nameof(PersonPartIndex.BirthDateUtc))
.Column<Handedness>(nameof(PersonPartIndex.Handedness))
// The content item ID is always 26 characters.
Expand All @@ -51,7 +52,7 @@ public int Create()
// https://docs.orchardcore.net/en/latest/docs/glossary/#content-type. The content type's name is arbitrary but
// choose a meaningful one. Notice how we use a class with constants to store the type name so we prevent risky
// copy-pasting.
_contentDefinitionManager.AlterTypeDefinition(ContentTypes.PersonPage, type => type
await _contentDefinitionManager.AlterTypeDefinitionAsync(ContentTypes.PersonPage, type => type
.Creatable()
.Listable()
// We attach parts by specifying their name. For our own parts we use nameof(): This is not mandatory but
Expand All @@ -62,7 +63,7 @@ public int Create()
// We can even create a widget with the same content part. Widgets are just content types as usual but with the
// Stereotype set as "Widget". You'll notice that our site's configuration includes three zones on the frontend
// that you can add widgets to, as well as two layers. Check them out on the admin!
_contentDefinitionManager.AlterTypeDefinition("PersonWidget", type => type
await _contentDefinitionManager.AlterTypeDefinitionAsync("PersonWidget", type => type
.Stereotype("Widget")
.WithPart(nameof(PersonPart))
);
Expand Down
1 change: 0 additions & 1 deletion Services/DemoSettingsConfiguration.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
using Lombiq.TrainingDemo.Models;
using Microsoft.Extensions.Options;
using OrchardCore.Entities;
using OrchardCore.Settings;

namespace Lombiq.TrainingDemo.Services;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<TargetFramework>net8.0</TargetFramework>
</PropertyGroup>

<ItemGroup>
Expand Down
2 changes: 1 addition & 1 deletion Views/ColorField-ColorPicker.Edit.cshtml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
<fieldset class="form-group @BlockName @(BlockName)_editor_colorPicker">
<legend class="@(BlockName)__displayName">@Model.PartFieldDefinition.DisplayName()</legend>

<label asp-for="ColorName" class="@(BlockName)__label">@T["Color name"]</label>
<label asp-for="ColorName" class="form-label @(BlockName)__label">@T["Color name"]</label>
<input asp-for="ColorName" class="form-control @(BlockName)__input" />

<div id="@pickerElementId" class="@(BlockName)__picker"></div>
Expand Down
4 changes: 2 additions & 2 deletions Views/ColorField.Edit.cshtml
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,10 @@
<fieldset class="form-group colorFieldEditor">
<legend>@Model.PartFieldDefinition.DisplayName()</legend>

<label asp-for="ColorName" class="colorFieldEditor__label">@T["Color name"]</label>
<label asp-for="ColorName" class="form-label colorFieldEditor__label">@T["Color name"]</label>
<input asp-for="ColorName" class="form-control content-preview-text colorFieldEditor__input" />

<label asp-for="Value" class="colorFieldEditor__label">@T["Hexadecimal value"]</label>
<label asp-for="Value" class="form-label colorFieldEditor__label">@T["Hexadecimal value"]</label>
<input asp-for="Value" class="form-control content-preview-text colorFieldEditor__input" />
@if (!string.IsNullOrEmpty(settings.Hint))
{
Expand Down
8 changes: 4 additions & 4 deletions Views/ColorFieldSettings.Edit.cshtml
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,22 @@
<fieldset class="form-group">
<div class="custom-control custom-checkbox">
<input asp-for="Required" type="checkbox" class="custom-control-input">
<label class="custom-control-label" asp-for="Required">@T["Check if the field is required."]</label>
<label class="form-label custom-control-label" asp-for="Required">@T["Check if the field is required."]</label>
</div>
</fieldset>

<fieldset class="form-group">
<div class="row col-md">
<label asp-for="Hint">@T["Hint"]</label>
<label class="form-label" asp-for="Hint">@T["Hint"]</label>
<textarea asp-for="Hint" rows="2" class="form-control"></textarea>
<span class="hint">@T["The hint text to display for this field on the editor."]</span>
</div>
</fieldset>

<fieldset class="form-group">
<div class="row col-sm">
<label asp-for="Label">@T["Label"]</label>
<input asp-for="Label" class="form-control" />
<label class="form-label" asp-for="Label">@T["Label"]</label>
<input class="form-label" asp-for="Label" class="form-control" />
<span class="hint">@T["The text associated to the checkbox."]</span>
</div>
</fieldset>
2 changes: 1 addition & 1 deletion Views/DemoSettings.Edit.cshtml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
@using OrchardCore.Mvc.Core.Utilities

<fieldset class="form-group" asp-validation-class-for="Message">
<label asp-for="Message">@T["Message"]</label>
<label class="form-label" asp-for="Message">@T["Message"]</label>
<input asp-for="Message" class="form-control" type="text" />
<span asp-validation-for="Message"></span>
<span class="hint">
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
@model ManagePersonsPermissionCheckerTaskViewModel

<div class="mb-3" asp-validation-class-for="UserName">
<label asp-for="UserName">@T["Username"]</label>
<label class="form-label" asp-for="UserName">@T["Username"]</label>
<input type="text" asp-for="UserName" class="form-control code" />
<span asp-validation-for="UserName"></span>
<span class="hint">@T["The user's name to be checked for ManagePersons permission."]</span>
Expand Down
6 changes: 3 additions & 3 deletions Views/PersonPart.Edit.cshtml
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,18 @@
here, because (as mentioned) it has its own editor and display shape so no need to worry about that. *@

<fieldset class="form-group" asp-validation-class-for="Name">
<label asp-for="Name">@T["Name"] <span asp-validation-for="Name"></span></label>
<label class="form-label" asp-for="Name">@T["Name"] <span asp-validation-for="Name"></span></label>
<input asp-for="Name" class="form-control" />
<span class="hint">@T["Person's name"]</span>
</fieldset>

<fieldset class="form-group" asp-validation-class-for="BirthDateUtc">
<label asp-for="BirthDateUtc">@T["Birth date"] <span asp-validation-for="BirthDateUtc"></span></label>
<label class="form-label" asp-for="BirthDateUtc">@T["Birth date"] <span asp-validation-for="BirthDateUtc"></span></label>
<input asp-for="BirthDateUtc" type="date" class="form-control" />
</fieldset>

<fieldset class="form-group" asp-validation-class-for="Handedness">
<label asp-for="Handedness">@T["Handedness"] <span asp-validation-for="Handedness"></span></label>
<label class="form-label" asp-for="Handedness">@T["Handedness"] <span asp-validation-for="Handedness"></span></label>
<select asp-for="Handedness" asp-items="Html.GetEnumSelectList<Handedness>()" class="form-control"></select>
</fieldset>

Expand Down