Skip to content

Latest commit

 

History

History

README.md

OnTopic Editor

The OnTopic.Editor.AspNetCore project provides a web-based interface for the OnTopic Library. The editor is distributed as a Razor Class Library via NuGet so it can easily be added to a website that implements the OnTopic.AspNetCore.Mvc library.

OnTopic.Editor.AspNetCore package in Internal feed in Azure Artifacts Build Status NuGet Deployment Status

Contents

Attribute Type Plugins

When a topic is edited in the OnTopic Editor, every attribute is exposed as a particular attribute type—such as a text box, dropdown menu, etc. Those attribute types are implemented as plugins, which can be developed by third-party developers as a means of customizing or extending the editor. The OnTopic.Editor.AspNetCore.Attributes provides a standard set of attribute types for the editor. The following summarizes the structure of plugins.

View Component

The {Type}ViewComponent) (e.g., BooleanViewComponent) is responsible for evaluating contextual information against services to return view models for each attribute type.

Attribute Descriptor

The {Type}AttributeDescriptor (e.g., BooleanAttributeDescriptor) derives from AttributeDescriptor and is primarily responsible for customizing the ModelType for cases where the attribute should not be stored in Topic.Attributes.

public class FooAttributeDescriptor: AttributeDescriptor {
  public FooAttributeDescriptor(string key, string contentType, Topic parent, int id = -1): base(key, contentType, parent, id) {
    ModelType = ModelType.Reference
  }
}
Notes
  • The signature of the constructor should match Topic, which this derives from. That allows the TopicFactory to create new instances of it.
  • Generally, the only customization required is to modify the ModelType, if it shouldn't be set to the default of ModelType.ScalarValue.

Attribute Descriptor (View Model)

The {Type}AttributeDescriptorViewModel (e.g., BooleanAttributeDescriptorViewModel) exposes the configuration of the AttributeDescriptor to the view. It will typically have a property for each attribute associated with the AttributeDescriptor in the Editor. For exxample,

public record FooAttributeDescriptorViewModel: AttributeDescriptorViewModel {
  public string Height { get; init; }
}

In this example, the FooAttributeDescriptorViewModel has a single configuration value, which specifies the Height of the view component.

Client Resources

In addition to exposing configurable properties for the attribute, the attribute descriptor view model is also responsble for registering client-side resources that should be injected into the header or footer of the layout. This can be done in the constructor using the following calls:

public record FooAttributeDescriptorViewModel: AttributeDescriptorViewModel {
  public FooAttributeDescriptorViewModel() {
    StyleSheets.Register(GetNamespacedUri("%/Shared/Styles/Foo.css"));
    Scripts.Register(GetNamespacedUri("%/Shared/Scripts/Foo.js"));
  }
}

Note that the GetNameSpaceUri() helper will automatically replace the %/ with the Razor Class Library namespace for the plugin's assembly—e.g., /_Content/FooAttribute/.

View Model (Optional)

Typically, view components will return an instance of the AttributeViewModel<T> view model, where T is the AttributeDescriptorViewModel. On occassion, however, there is additional non-configuration data that needs to be returned to the view. For example, an attribute type which displays a dropdown list may include a Collection<SelectListItem> to include the data for that dropdown list:

public record FooViewModel {
  public Collection<SelectListItem> Values { get; } = new();
}

Binding Model

The {Type}AttributeBindingModel (e.g., BooleanAttributeBindingModel) is assembled by the AttributeBindingModelBinder to bind attribute data posted to the EditorController to an EditorBindingModel. Typically, there's no need to customize this unless there's a need to translate how the value is read. If there's a need to translate the value submitted from the editor prior to it being set on the Topic, implementers can override the GetValue() method:

public record FooBindingModel {
  public string GetValue() => Value.ToLower();
}

View

Per ASP.NET Core conventions, views must be stored in /Views/Editor/Components/{Type}/Default.cshtml. To ensure they are consistently rendered in the OnTopic Editor, and property bound to the EditorBindingModel, they should have their layout set to:

@{
  Layout = "~/Areas/Editor/Views/Editor/Components/_Layout.cshtml";
}

This will automatically add the header, tooltip, as well as hidden metada needed to correctly bind to the appropriate AttributeBindingModel.

Infrastructure

Typically, consumers of the OnTopic Editor shouldn't need to know much about the architecture of the code. The following overview of types used by the OnTopic Editor may, however, be of use to those looking to extend the functionality of the editor.

Controllers

  • EditorController: The primary controller fo the OnTopic Editor, with actions for /Edit, /Import, /Export, /Move, /Delete, /Rollback, and /Json.

Components

  • ContentTypeListViewComponent: A view component for displaying a list of content types that can be created in the current context. Used for opening the new topic form.
    • ContentTypeListAttributeDescriptorViewModel: The attribute descriptor for the ContentTypeList view component; includes an EnableModal property for optinally opening the new topic form in a popup window.
    • ContentTypeListViewModel: The view model for the ContentType view component includes, critically, a TopicList of SelectListItems for binding to the dropdown list.

Services

Internal

Models

  • EditorViewModel: The core view model used to represent each page in the OnTopic Editor.
    • EditingTopicViewModel: The current topic being edited; exposed via the Topic property on the EditorViewModel.
  • ContenTypeDescriptorViewModel: Provides metadata associated with a given ContentTypeDescriptor; exposed via the ContentType property on the EditorViewModel.
    • AttributeDescriptorViewModel: Provides metadata associated with a specific AttributeTypeDescriptor; exposed via the AttributeDescriptors property of the ContentTypeDescriptorViewModel.
  • AttributeViewModel: Contains the serialized metadata for an attribute, with a link to the associated AttributeDescriptorViewModel and EditingTopicViewModel; constructed by Edit.cshtml for each attribute type view component.
    • ClientResourceCollection: Provides a base class for registering client-side resources associated with a given attribute.
      • ClientResource<T>: Provides a base class for representing an individual client-side resources.
      • ScriptCollection: A concrete implementation of the ClientResourceColletion for registering client-side scripts.
        • ScriptResource: A concrete implementation of the ClientResource for representing a client-side script.
      • StyleSheetCollection: A concrete implementation of the ClientResourceColletion for registering client-side style sheets.
        • StyleSheetResource: A concrete implementation of the ClientResource for representing a client-side script.
  • EditorBindingModel: The core binding model used to respond to POST requests in the OnTopic Editor.
    • EditorAttributeCollection: A collection of AttributeBindingModel instance, exposed by the Attributes property of the EditorBindingModel.
      • AttributeBindingModel: Binds the metadata and submitted value for an individual attribute control, as submitted via a POST request.