Skip to content

Commit

Permalink
Merge pull request #55 from leekelleher/dev/v1.1
Browse files Browse the repository at this point in the history
Preparing v1.1.0 release
  • Loading branch information
leekelleher authored Dec 3, 2020
2 parents 8e3312a + c1fe50c commit 5b50a5c
Show file tree
Hide file tree
Showing 87 changed files with 3,642 additions and 230 deletions.
12 changes: 6 additions & 6 deletions .github/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,22 +24,22 @@ Let's take a look inside...
##### Property Editors

- [Bytes](../docs/editors/bytes.md) - a read-only label to display file sizes in relative bytes.
- [Content Blocks](../docs/editors/content-blocks.md) - a block editor, configurable using element types.
- [Data List](../docs/editors/data-list.md) - an editor that combines a custom data source with a custom list editor.
- [Icon Picker](../docs/editors/icon-picker.md) - an editor to select an icon (from the Umbraco icon library).
- [Notes](../docs/editors/notes.md) - a read-only label to display rich-text instructional messages for content editors.
- [Render Macro](../docs/editors/render-macro.md) - a read-only label dynamically generated from an Umbraco Macro.


#### Release status
#### Releases

My aim to have a v1.0 release by end of Q2 (June) 2020.

Downloads will be made available, (in due course), on the [releases page](https://github.com/leekelleher/umbraco-contentment/releases).
Downloads are available on the [releases page](https://github.com/leekelleher/umbraco-contentment/releases).


#### Known issues

_There are currently no known issues with the Contentment package._
- **Data List**
- When using the Umbraco Content data source with an XPath query, inside a Nested Content editor, it will not be able to identify the contextual containing node ID. e.g. your XPath query will not work. See #30 for details.


### Documentation
Expand Down Expand Up @@ -101,7 +101,7 @@ For more information about the Mozilla Public License, please visit: <https://ww
- [Lee Kelleher](https://leekelleher.com) - ([GitHub](https://github.com/leekelleher), [Twitter](https://twitter.com/leekelleher))

<details>
<summary>Current development effort: <b>746+ hours</b> (between 2019-03-13 to 2020-06-11)</summary>
<summary>Current development effort: <b>810+ hours</b> (between 2019-03-13 to 2020-08-28)</summary>

_To give you an idea of how much human developer time/effort has been put into making this package._

Expand Down
2 changes: 1 addition & 1 deletion .github/ROADMAP.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ Initial release. Property Editors are:

### v1.1

- Content Blocks _(a StackedContent-esque editor)_
- [Content Blocks](../docs/editors/content-blocks.md)
- Data List: Umbraco Content _(a data source for selecting nodes)_

### v1.2
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,4 @@ src/packages/*/**
/tools/*.exe
/build/__umb/*
/build/__nuget/*
/build/build-push.ps1
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
1.0.1
1.1.0
9 changes: 8 additions & 1 deletion build/build-assets.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,14 @@ $htmlFiles = Get-ChildItem -Path "${ProjectDir}DataEditors" -Recurse -Force -Inc
foreach($htmlFile in $htmlFiles){
$contents = Get-Content -Path $htmlFile.FullName;
$minifiedHtml = [Regex]::Replace($contents, "^<!--.*?-->", "");
Set-Content -Path "${pluginFolder}\editors\$($htmlFile.Name)" -Value $minifiedHtml;
[IO.File]::WriteAllLines("${pluginFolder}\editors\$($htmlFile.Name)", $minifiedHtml);
}

# Razor Templates - Copy
$razorFiles = Get-ChildItem -Path "${ProjectDir}DataEditors" -Recurse -Force -Include *.cshtml;
foreach($razorFile in $razorFiles){
$contents = Get-Content -Path $razorFile.FullName;
[IO.File]::WriteAllLines("${pluginFolder}\render\$($razorFile.Name)", $contents);
}

# CSS - Bundle & Minify
Expand Down
5 changes: 5 additions & 0 deletions docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,16 @@

### Documentation

> If there are any parts of the documentation that are unclear, [please do let me know](https://github.com/leekelleher/umbraco-contentment/issues/new/choose).
>
> Sometimes I can be too close to the code to understand how others (e.g. you) will use it. :v::heart::dove:
#### Property-Editors

Here is the documentation for the Contentment property-editors...

- [Bytes](../docs/editors/bytes.md) - a read-only label to display file sizes in relative bytes.
- [Content Blocks](../docs/editors/content-blocks.md) - a block editor, configurable using element types.
- [Data List](../docs/editors/data-list.md) - an editor that combines a custom data source with a custom list editor.
- [Icon Picker](../docs/editors/icon-picker.md) - an editor to select an icon (from the Umbraco icon library).
- [Notes](../docs/editors/notes.md) - a read-only label to display rich-text instructional messages for content editors.
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
166 changes: 166 additions & 0 deletions docs/editors/content-blocks.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
<img src="../assets/img/logo.png" alt="Contentment for Umbraco logo" title="A state of Umbraco happiness." height="130" align="right">

## Contentment for Umbraco

### Content Blocks

Content Blocks is a property-editor used for creating a list of structured content, with each block configurable using an element type.

> If you are using Umbraco 8.7 (or above), this may sound familiar to the [Block List Editor](https://our.umbraco.com/Documentation/Getting-Started/Backoffice/Property-Editors/Built-in-Property-Editors/Block-List-Editor/), and you may be asking yourself why should you use Content Blocks over the built-in Block List Editor? It's a good question, and you'll find no marketing spin from me. So if you have any doubts, then I'd recommend that you stick with Umbraco's built-in editors. Content Blocks has subtle differences, it's entirely your choice.
> For long time fans of Umbraco v7.x, if you recall the [Stacked Content](https://our.umbraco.com/packages/backoffice-extensions/stacked-content) editor, then Content Blocks could be considered its spiritual successor.

### How to configure the editor?

In your new Data Type, selected the "[Contentment] Content Blocks" option. You will see the following configuration fields.

The two main fields are "**Display mode**" and "**Block types**", the rest are for further configuration.

![Configuration Editor for Content Blocks - empty state](content-blocks--configuration-editor-01.png)

The **Display mode** is pre-configured to use the **Stack** mode, this enables a richer editing experience. Alternatively, if you prefer to use an interface similar to Umbraco's Content Picker editor, you can remove the **Stack** configuration and use the **List** mode instead. Each display mode comes with their own configuration options, _e.g. the Stack mode has a feature to create a **Content template** from each block item._

![Configuration Editor for Content Blocks - the Stack display mode configuration](content-blocks--configuration-editor-02.png)

> **Note:** You can add your own custom display modes by implementing the [`IContentBlocksDisplayMode`](https://github.com/leekelleher/umbraco-contentment/blob/develop/src/Umbraco.Community.Contentment/DataEditors/ContentBlocks/IContentBlocksDisplayMode.cs) interface.
>
> `// TODO: Write documentation on developing custom display modes.`
Next is to select and configure the **Block types**. By pressing the **Select and configure an element type** button, you will be presented with a selection of element types.

> **Note:** If you have not created any element types. Please refer to [Umbraco's documentation on how to create an element type](https://our.umbraco.com/documentation/Getting-Started/Data/Defining-content/).
![Configuration Editor for Content Blocks - list of available element types](content-blocks--configuration-editor-03.png)

Once you have selected an element type, you will be presented with the configuration options for that block type.

![Configuration Editor for Content Blocks - block type configuration](content-blocks--configuration-editor-04.png)

The **Name template** field can be used to enter an AngularJS expression, which is evaluated against each block (of this type) to display its name. If this field is left empty, the default name template will be `"Item {{ $index }}"`.

The **Editor overlay size** option will configure the size (width) of the overlay editing panel. The options are Small, Medium and Large. The default value is "Small", this is typically ideal for concise element types, e.g. with a heading, media picker and intro blurb textarea. For element types with heavier content, e.g. Rich Text editors, then "Medium" or "Large" would be a more suitable option.

The **Enable preview?** option can be enabled to render a richer preview of the content block item. The preview mechanism uses a Razor (`.cshtml`) partial-view for rendering.

> **Note:** For details on how to render a preview, see the [Previews](#previews) section below.
Once you have configured the block type, press the **Done** button at the bottom of the overlay.

The rest of the configuration options can give finer control over the editing experience.

The **Enable filter?** option can enable a search filer at the top of the overlay selection panel. This can be useful if you have configured many block types.

The **Maximum items** field is used to limit the number of content blocks that the editor can have. Once the maximum is reached, the **Add** button will not be available.

The **Disable sorting?** option will prevent the Content Blocks from being sorted.

Lastly, the **Developer mode?** option is a special feature for those who would like to have access to the raw JSON value of the Content Block editor. Enabling this option will add a [property action](https://our.umbraco.com/Documentation/Extending/Property-Editors/Property-Actions/) called **Edit raw value**.

![Property action for Content Blocks - edit raw value](content-blocks--configuration-editor-05.png)

Once you have configured the Data Type, press the **Save** button and add it to your Document Type.


### How to use the editor?

Once you have added the configured Data Type on your Document Type, the Content Blocks editor will be displayed on the content page's property panel.

![Content Blocks property-editor - displaying the empty state, with an Add button](content-blocks--property-editor-01.png)

By pressing the **Add content** button, an overlay with the available content blocks will appear.

![Content Blocks property-editor - displaying the available content blocks overlay](content-blocks--property-editor-02.png)

Selecting one of the available content blocks, you will be presented with the editing panel, (with the properties from the corresponding Element Type).

![Content Blocks property-editor - displaying the content blocks editing panel](content-blocks--property-editor-03.png)

Once you have finished editing the properties, press the **Done** button at the bottom of the overlay. This will close the overlay, with the content block being added to the stack/list.

![Content Blocks property-editor - new content block has been added](content-blocks--property-editor-04.png)

For further options, each content block has its own action menu, initially for sorting and removing content, but additional features for **Copy content block**, and **Create content template...** actions.

![Content Blocks property-editor - content block action menu](content-blocks--property-editor-05.png)

> **Did you know...** you can copy items from Nested Content and paste them into Content Blocks, (and vice-versa)! :dizzy_face:

#### Previews

An advanced feature of Content Blocks is the ability to have a richer preview for each block item. To do this, make sure that you enable the **Enable preview?** option when you configure the content block.

> **Note:** The preview feature will only work with the **Stack** display mode.
Once the preview feature is enabled, the content block item will render the preview using a Razor partial-view template.

The default preview partial-view (that ships with Contentment), will be used. This can be found at [`"~/App_Plugins/Contentment/render/ContentBlockPreview.cshtml"`](https://github.com/leekelleher/umbraco-contentment/blob/develop/src/Umbraco.Community.Contentment/DataEditors/ContentBlocks/ContentBlockPreview.cshtml). This will render similar to the default (plain) block style, with the exception that the **Name template** value is not available, the content block item's GUID (key) will be displayed instead.

To use your own custom preview partial-views, you must use the following convention; name the partial-view the same as the Element Type alias, and place it in **the `"~/Views/Partials/Blocks/"` folder.** If you would like to re-use the same preview partial-view for multiple content block items, you can create a `"~/Views/Partials/Blocks/Default.cshtml"` template.

When developing your own preview partial-view template, the declaration can be one of the following...

- `@inherits Umbraco.Web.Mvc.ContentBlockPreviewView`
This is the default declaration. This will give you access to `@Model.Content` (the current page as `IPublishedContent`), and `@Model.Element` (the content block item as `IPublishedElement`).

- `@inherits ContentBlockPreviewModel<TPublishedContent, TPublishedElement>`
This is advanced syntax, _(note, may require some trial-and-error, and sense of play)._ This can be used if you are using Umbraco's ModelsBuilder feature, where you know the object-type of the current Content Type page and Element Type item. As above, you can have strongly-typed access to the current page with `@Model.Content`, and the content block item with `@Model.Element`.

To aid the preview, there are a number of additional properties available in the partial-view's `ViewData` dictionary.

- `ViewData["elementIndex"]` - This is the index (`int`) of the content block item's position in the list.
- `ViewData["elementIcon"]` - This is the Element Type's icon, _(since the icon is not available on `Model.Element.ContentType`)._
- `ViewData["contentIcon"]` - This is the Content Type's icon, _(since the icon is not available on `Model.Content.ContentType`)._

> **Note:** The preview feature **does not work** on a freshly created new unsaved page. This is because the preview has no context of the page itself.

### How to get the value?

The value for the Content Blocks will be as `IEnumerable<IPublishedElement>` object-type.

If you are using Umbraco's ModelsBuilder feature, then each content block item will be castable as the intended Element Type model.

In terms of rendering the items, you can do so however you desire. As an example here, I would recommend having a separate partial-view template for each of the Element Types, (using the Element Type's alias as the filename), that way you are able to encapsulate the logic for that particular Element Type.

Using Umbraco's Models Builder...

```cshtml
<div>
@foreach (var item in Model.ContentBlocks)
{
@Html.Partial(item.ContentType.Alias, item)
}
</div>
```

Without ModelsBuilder...

The weakly-typed API may give you some headaches, we suggest using strongly-typed, (or preferably Models Builder).

Here's an example of strongly-typed...

```cshtml
<div>
@foreach (var item in @(Model.Value<IEnumerable<IPublishedElement>>("contentBlocks")))
{
@Html.Partial(item.ContentType.Alias, item)
}
</ul>
```


### Similar editors and further reading

There are several alternative block-based editors that you could use with Umbraco v8, here are a selection...

- [Umbraco's **Block List** editor](https://our.umbraco.com/documentation/getting-started/backoffice/property-editors/built-in-property-editors/Block-List-Editor/) - available since Umbraco v8.7.0.
- [Umbraco's **Nested Content** editor](https://our.umbraco.com/documentation/getting-started/backoffice/property-editors/built-in-property-editors/Nested-Content/) - available since Umbraco v7.7.0, _(since superseded by the Block List editor)._
- [**Bento** editor by KOBEN Digital](https://our.umbraco.com/packages/backoffice-extensions/bento-editor/) - compatible with Umbraco v8.6.0 (and above).
- [**Perplex.ContentBlocks** by Perplex](https://our.umbraco.com/packages/backoffice-extensions/perplexcontentblocks/) - _(ignore my naming clash with Content Blocks, naming things is hard),_ compatible with Umbraco v8.1.0 (and above).

For further reading, here are a selection of insights...

- [Paul Marden's **Landing Page article** on Skrift](https://skrift.io/issues/part-1-landing-pages/) - part of a wider series on exploring common practices.
- [Cogworks' post on **How to Pick a Block Style Editor**](https://www.wearecogworks.com/blog/umbraco-v8-how-to-pick-a-block-style-editor/)
Binary file modified docs/editors/data-list--configuration-editor-01.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/editors/data-list--configuration-editor-02.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 2 additions & 2 deletions docs/editors/data-list.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ The two main fields are "**Data source**" and "**List editor**".

![Configuration Editor for Data List - empty state](data-list--configuration-editor-01.png)

Selecting the **Data source**, you will be presented with a selection of data sources, including .NET enumeration, file system, SQL, CSV, JSON and XML data.
Selecting the **Data source**, you will be presented with a selection of data sources, including .NET enumeration, file system, Umbraco content, SQL, CSV, JSON and XML data.

![Configuration Editor for Data List - available data sources](data-list--configuration-editor-02.png)

Expand All @@ -43,7 +43,7 @@ Once you have configured both the **Data source** and **List editor** you can **

### How to use the editor?

Once you have added the configured Data Type on your Document Type, the Data List will be displayed.
Once you have added the configured Data Type on your Document Type, the Data List will be displayed on the content page's property panel.

![Data List property-editor - displaying the data source with a Checkbox List](data-list--property-editor-01.png)

Expand Down
1 change: 1 addition & 0 deletions src/Umbraco.Community.Contentment.sln
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Editors", "Editors", "{A5294B30-2ED5-4BBA-A2DE-A07103DAE78F}"
ProjectSection(SolutionItems) = preProject
..\docs\editors\bytes.md = ..\docs\editors\bytes.md
..\docs\editors\content-blocks.md = ..\docs\editors\content-blocks.md
..\docs\editors\data-list.md = ..\docs\editors\data-list.md
..\docs\editors\icon-picker.md = ..\docs\editors\icon-picker.md
..\docs\editors\notes.md = ..\docs\editors\notes.md
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,9 @@ public void Terminate()

private void ServerVariablesParser_Parsing(object sender, Dictionary<string, object> e)
{
if (e.ContainsKey(Constants.Internals.ProjectAlias) == false)
if (e.TryGetValueAs("umbracoPlugins", out Dictionary<string, object> umbracoPlugins) == true && umbracoPlugins.ContainsKey(Constants.Internals.ProjectAlias) == false)
{
e.Add(Constants.Internals.ProjectAlias, new
umbracoPlugins.Add(Constants.Internals.ProjectAlias, new
{
name = Constants.Internals.ProjectName,
version = Configuration.ContentmentVersion.SemanticVersion.ToSemanticString()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ public void Compose(Composition composition)
.Append<ContentmentComponent>()
;
}

}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/* Copyright © 2020 Lee Kelleher.
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */

using System;
using System.Collections.Generic;
using System.Reflection;

namespace Umbraco.Core.Xml
{
// NOTE: Bah! `UmbracoXPathPathSyntaxParser` is marked as internal! It's either copy code, or reflection - here we go!
// https://github.com/umbraco/Umbraco-CMS/blob/release-8.6.1/src/Umbraco.Core/Xml/UmbracoXPathPathSyntaxParser.cs#L11
internal class UmbracoXPathPathSyntaxParser
{
public static string ParseXPathQuery(
string xpathExpression,
int? nodeContextId,
Func<int, IEnumerable<string>> getPath,
Func<int, bool> publishedContentExists)
{
try
{
var assembly = typeof(XPathVariable).Assembly;
var type = assembly.GetType("Umbraco.Core.Xml.UmbracoXPathPathSyntaxParser");
var method = type.GetMethod(nameof(ParseXPathQuery), BindingFlags.Static | BindingFlags.Public);
return method.Invoke(null, new object[] { xpathExpression, nodeContextId, getPath, publishedContentExists }) as string;
}
catch { /* ಠ_ಠ */ }

return xpathExpression;
}
}
}
Loading

0 comments on commit 5b50a5c

Please sign in to comment.