Skip to content

Commit

Permalink
Merged in issue/OCORE-1 (pull request #6)
Browse files Browse the repository at this point in the history
OCORE-1: Training Demo átírása - Alapvető .NET Core és OrchardCore elemek bemutatása

--HG--
branch : orchard-core
  • Loading branch information
Piedone committed Jan 17, 2019
2 parents c5dbcf3 + 73f5064 commit 778505c
Show file tree
Hide file tree
Showing 64 changed files with 7,796 additions and 48 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
obj/
bin/
*.user
wwwroot
node_modules
2 changes: 2 additions & 0 deletions .hgignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,5 @@ syntax: glob
obj/
bin/
*.user
wwwroot
node_modules
Binary file added Assets/Images/HarryPotter.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
5 changes: 5 additions & 0 deletions Assets/Styles/trainingdemo-colorpicker.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
.colorField {
.pickr {
margin-top: 12px;
}
}
129 changes: 129 additions & 0 deletions Controllers/DatabaseStorageController.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
/*
* Now it's time to save something to the database. Orchard Core uses YesSql to store data in database which is
* document database interface for relational databases. Simply put, you need to design your database as a document
* database but it will be stored in your favorite SQL database. If you want to learn more go to
* https://github.com/sebastienros/yessql and read the documentation.
*
* Here you will see how to store simple data in the database and then query it without actually using Orchard Core
* content management features and practices (i.e. you can store non-Orchard Core content items).
*
* This demonstration will be really simple because more features will be shown later and you can also learn more from
* the YesSql documentation.
*/

using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Lombiq.TrainingDemo.Indexes;
using Lombiq.TrainingDemo.Models;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Localization;
using OrchardCore.DisplayManagement;
using OrchardCore.DisplayManagement.ModelBinding;
using OrchardCore.DisplayManagement.Notify;
using YesSql;

namespace Lombiq.TrainingDemo.Controllers
{
public class DatabaseStorageController : Controller, IUpdateModel
{
private readonly ISession _session;
private readonly IDisplayManager<Book> _bookDisplayManager;
private readonly INotifier _notifier;
private readonly IHtmlLocalizer H;


public DatabaseStorageController(
ISession session,
IDisplayManager<Book> bookDisplayManager,
INotifier notifier,
IHtmlLocalizer<DatabaseStorageController> htmlLocalizer)
{
_session = session;
_bookDisplayManager = bookDisplayManager;
_notifier = notifier;
H = htmlLocalizer;
}


// A page with a button that will call the CreateBooks POST action.
// See it under /Lombiq.TrainingDemo/Store/CreateBooks.
[HttpGet]
public ActionResult CreateBooks() => View();

[HttpPost, ActionName(nameof(CreateBooks))]
public ActionResult CreateBooksPost()
{
// For demonstration purposes this will create 3 books and store them in the database one-by-one using the
// ISession service. Note that you can even go to the database directly, circumventing YesSql too, by
// injecting the IDbConnectionAccessor service and access the underlying connection.

// Since storing them in the documents is not enough we need to index them to be able to
// filter them in a query.
// NEXT STATION: Indexes/BookIndex.cs
foreach (var book in CreateDemoBooks())
{
// So now you understand what will happen in the background when this service is being called.
_session.Save(book);
}

_notifier.Information(H["Books have been created in the database."]);

return RedirectToAction(nameof(CreateBooks));
}

// This page will display the books written by J.K. Rowling.
// See it under /Lombiq.TrainingDemo/Store/JKRowlingBooks.
public async Task<ActionResult> JKRowlingBooks()
{
// ISession service is used for querying items.
var jkRowlingBooks = await _session
// First, we define what object (document) we want to query and what index should be used for
// filtering.
.Query<Book, BookIndex>()
// In the .Where() method you can describe a lambda where the object will be the index object.
.Where(index => index.Author == "J.K. (Joanne) Rowling")
// When the query is built up you can call ListAsync() to execute it. This will return a list of books.
.ListAsync();

// Now this is what we possibly understand now, we will create a list of display shapes from the previously
// fetched books.
var bookShapes = await Task.WhenAll(jkRowlingBooks.Select(async book =>
await _bookDisplayManager.BuildDisplayAsync(book, this)));

// You can check out Views/Store/JKRowlingBooks.cshtml and come back here.
return View(bookShapes);
}

// NEXT STATION: Models/PersonPart.cs


private IEnumerable<Book> CreateDemoBooks() =>
new Book[]
{
new Book
{
CoverPhotoUrl = "/Lombiq.TrainingDemo/Images/HarryPotter.jpg",
Title = "Harry Potter and The Sorcerer's Stone",
Author = "J.K. (Joanne) Rowling",
Description = "Harry hasn't had a birthday party in eleven years - but all that is about to " +
"change when a mysterious letter arrives with an invitation to an incredible place."
},
new Book
{
Title = "Fantastic Beasts and Where To Find Them",
Author = "J.K. (Joanne) Rowling",
Description = "With his magical suitcase in hand, Magizoologist Newt Scamander arrives in New " +
"York in 1926 for a brief stopover. However, when the suitcase is misplaced and some of his " +
"fantastic beasts escape, there will be trouble for everyone."
},
new Book
{
Title = "The Hunger Games",
Author = "Suzanne Collins",
Description = "The nation of Panem, formed from a post-apocalyptic North America, is a country " +
"that consists of a wealthy Capitol region surrounded by 12 poorer districts."
}
};
}
}
90 changes: 90 additions & 0 deletions Controllers/DisplayManagementController.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
/*
* In this section you will learn how Orchard Core deals with displaying various information on the UI using reusable
* components called shapes (see:
* https://orchardcore.readthedocs.io/en/latest/OrchardCore/OrchardCore.DisplayManagement/README/#shapes). This is a
* very huge and powerful part of Orchard Core, here you will learn the basics of Display Management.
*
* To demonstrate this basic functionality, we will create two slightly different pages for displaying information
* about a book.
*/

using System.Threading.Tasks;
using Lombiq.TrainingDemo.Models;
using Microsoft.AspNetCore.Mvc;
using OrchardCore.DisplayManagement;
using OrchardCore.DisplayManagement.ModelBinding;

namespace Lombiq.TrainingDemo.Controllers
{
// Notice that the controller implements the IUpdateModel interface. This interface encapsulates the properties and
// methods related to ASP.NET Core MVC model binding. Orchard Core needs this model binding functionality outside
// the controllers (you will see it later).
public class DisplayManagementController : Controller, IUpdateModel
{
// The core display management features can be used via the IDisplayManager service. The generic parameter will
// be the object that needs to be displayed on the UI somehow. Don't forget to register this generic class with
// the service provider (see: Startup.cs).
private readonly IDisplayManager<Book> _bookDisplayManager;


public DisplayManagementController(IDisplayManager<Book> bookDisplayManager)
{
_bookDisplayManager = bookDisplayManager;
}


// Before we learn how shapes are generated using the display manager let's see what are these shapes actually.
// Ad-hoc shapes can be created anywhere without the display manager. In this example we'll see how to create
// an ad-hoc shape inside a view (or could be another shape).
public ActionResult AdHocShape() => View();

// NEXT STATION: Views/DisplayManagement/AdHocShape.cshtml

// First, create a page that will display a summary and some additional data of the book.
// See it under /Lombiq.TrainingDemo/DisplayManagement/DisplayBook.
public async Task<ActionResult> DisplayBook()
{
// For demonstration purposes create a dummy book object.
var book = CreateDemoBook();

// This method will generate a shape primarily for displaying information about the given object.
var shape = await _bookDisplayManager.BuildDisplayAsync(book, this);

// We will see how this display shape is generated and what will contain but first let's see how is this
// rendered in the MVC view.
// NEXT STATION: Go to Views/DisplayManagement/DisplayBook.cshtml.

return View(shape);
}

// Let's generate another Book display shape, but now with a display type.
// See it under /Lombiq.TrainingDemo/DisplayManagement/DisplayBookDescription.
public async Task<ActionResult> DisplayBookDescription()
{
// Generate another book object to be used for demonstration purposes.
var book = CreateDemoBook();

// This time give an additional parameter which is the display type. If display type is given then Orchard
// Core will search a cshtml file with a name [ClassName].[DisplayType].cshtml.
var shape = await _bookDisplayManager.BuildDisplayAsync(book, this, "Description");

// NEXT STATION: Go to Views/Book.Description.cshtml

return View(shape);
}


private Book CreateDemoBook() =>
new Book
{
CoverPhotoUrl = "/Lombiq.TrainingDemo/Images/HarryPotter.jpg",
Title = "Harry Potter and The Sorcerer's Stone",
Author = "J.K. (Joanne) Rowling",
Description = "Harry hasn't had a birthday party in eleven years - but all that is about to change " +
"when a mysterious letter arrives with an invitation to an incredible place.",
};
}
}

// If you've finished with both actions (and their .cshtml files as well), then
// NEXT STATION: Controllers/DatabaseStorageController is what's next.
17 changes: 0 additions & 17 deletions Controllers/HomeController.cs

This file was deleted.

68 changes: 68 additions & 0 deletions Controllers/PersonListController.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
/*
* In this controller you will see again how to query items but this time items will be of the newly created Person
* content type. It doesn't make too much difference but you need to keep in mind that the ContentItems are stored in
* the documents (which contain the parts and fields serialized) and can have multiple index records referencing a
* content item (e.g. the previously created PersonPartIndex that indexes data in from PersonPart).
*
* Note that there is no custom controller or action demonstrated for displaying the editor for the Person. Go to the
* administration page (/Admin) and create a few Person content items, including ones with ages above 30.
*/

using System.Linq;
using System.Threading.Tasks;
using Lombiq.TrainingDemo.Indexes;
using Microsoft.AspNetCore.Mvc;
using OrchardCore.ContentManagement;
using OrchardCore.ContentManagement.Display;
using OrchardCore.DisplayManagement.ModelBinding;
using OrchardCore.Modules;
using YesSql;

namespace Lombiq.TrainingDemo.Controllers
{
public class PersonListController : Controller, IUpdateModel
{
private readonly ISession _session;
private readonly IClock _clock;
private readonly IContentItemDisplayManager _contentItemDisplayManager;


public PersonListController(
ISession session,
IClock clock,
IContentItemDisplayManager contentItemDisplayManager)
{
_session = session;
_clock = clock;
_contentItemDisplayManager = contentItemDisplayManager;
}


// See it under /Lombiq.TrainingDemo/PersonList/OlderThan30.
public async Task<ActionResult> OlderThan30()
{
var thresholdDate = _clock.UtcNow.AddYears(-30);
var people = await _session
// This will query for content items where the related PersonPartIndex.BirthDateUtc is lower than the
// threshold date. Notice that there is no Where method. The Query method has an overload for that
// which can be useful if you don't want to filter in multiple indexes.
.Query<ContentItem, PersonPartIndex>(index => index.BirthDateUtc < thresholdDate)
.ListAsync();

// Now let's build the display shape for a content item! Notice that this is not the IDisplayManager
// service. The IContentItemDisplayManager is an abstraction over that and it's specifically for content
// items. The reason we need that is that a ContentItem doesn't have a DisplayDriver but the ContentParts
// and ContentFields attached to the ContentItem have. This service will handle generating all the drivers
// created for these parts and fields.
// NEXT STATION: Drivers/PersonPartDisplayDriver
var shapes = await Task.WhenAll(people.Select(async person =>
await _contentItemDisplayManager.BuildDisplayAsync(person, this, "Summary")));

// Now assuming that you've already created a few Person content items on the dashboard and some of
// these persons are more than 30 years old then this query will contain items to display.
// NEXT STATION: Views/PersonList/OlderThan30.cshtml

return View(shapes);
}
}
}
Loading

0 comments on commit 778505c

Please sign in to comment.