Skip to content

limbo-works/Limbo.Umbraco.Signatur

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

29 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Limbo Signatur

GitHub license NuGet NuGet

Limbo.Umbraco.Signatur is a package that integrates with Signatur RSS job feeds, and allows importing jobs as content in Umbraco.

License: MIT License
Umbraco: Umbraco 13
Target Framework: .NET 8



Installation

Umbraco 13

Version 13 of this package supports Umbraco version 13. The package is only available via NuGet.

To install the package, you can use either the .NET CLI:

dotnet add package Limbo.Umbraco.Signatur --version 13.0.0-alpha001

or the NuGet Package Manager:

Install-Package Limbo.Umbraco.Signatur -Version 13.0.0-alpha001




Configuration

The package can be configured via appsettings and the Limbo:Signatur section. This primarily let's you set up the Signatur RSS feeds to be imported, but there is also a few other settings as well:

{
  "Limbo": {
    "Signatur": {
      "ImportUserId": -1,
      "LogResults": true,
      "Feeds": [
        {
          "Url": "https://portal.signatur.dk/ExtJobs/Rss.aspx?ClientId=0000",
          "ParentContentKey": "a8c8f679-63bb-4b5b-a52a-19f6117344c7",
          "ContentTypeAlias": "mySignaturJobPage"
        }
      ],
      "Scheduling": {
        "Delay": 7,
        "Interval": "PT1H30M"
      }
    }
  }
}

The available configuration options are as following:

  • ImportUserId (int)
    By the default, actions (save, publish and delete) made by the import will be attributed to the default super user in Umbraco (ID: -1). If you wish to attribute these actions to another user, you can specify it's numeric ID via this setting.

  • LogResults (bool)
    Currently not used.

  • Feeds (array)
    An array of the feeds to be imported.

    • Url (string)
      The URL of the Signatur RSS feed.

    • ParentContentKey (guid)
      The GUID key of the parent code node under which new jobs should be created.

    • ContentTypeAlias (string)
      The alias of the content type which should be used for new jobs.

  • Scheduling (object)
    The package adds a background task for running the import. That task may be configured through this object.

    • Delay (duration)
      An initial delay after startup the task should wait before beginning the import. Default is five minutes.

    • Interval (duration)
      The interval between each time the task is running the import. Default is one hour.

Durations may be specified as an integer, in which case the value is treated as minutes - or as a string using the ISO 8601 duration format such as PT1H30M (one and a half hour).




Property Editors

  • Limbo Signatur Job ID (alias: Limbo.Umbraco.Signatur.JobId) Dedeicated property editor for storing the ID of each job. This is used by the import to keep track of which jobs to add, update or delete, so your job content type must have a property using this property editor. Returns an int value.

  • Limbo Signatur Job Data (alias: Limbo.Umbraco.Signatur.JobData) Dedicated property editor for storing the job data as received from Signatur. Your job content type must have a property using this property editor. Returns an ISignaturItem value by default.

  • Limbo Signatur Last Updated (alias: Limbo.Umbraco.Signatur.LastUpdated) Property editor for storing when the import last updated a job in Umbraco. The property editor is optional for the job content type. Returns an EssentialsTime value.




Extending

The package contains several extension points that let's you extend and control how the package and the import is working.

Custom Properties

Jobs in the Signatur RSS feeds contain a number of default fields, and then typically also some client/feed specific. The parsing of the RSS feed is handled by our underlying Limbo.Integrations.Signatur package, which features ISignaturFeedParser service that you may replace with your own parser.

By default each RSS item is parsed and returned as ISignaturItem, which contains properties for the default fields. If you wish to support custom fields, you can create your own class that implements the ISignaturItem interface (or the SignaturItem concrete class):

public class MySignaturItem : SignaturItem {

    public string? Location { get; }

    public string? Teaser { get; }

    public MySignaturItem(SyndicationItem item, Dictionary<string, string> fields) : base(item, fields) {
        Location = GetString("companyInformation");
        Teaser = GetString("teaser");
    }

}

and then a matching feed class:

public class MySignaturFeed : SignaturFeed<MySignaturItem> {

    public MySignaturFeed(SyndicationFeed feed, IReadOnlyList<MySignaturItem> items) : base(feed, items) { }

}

This ensures a strongly typed approach to working with the feed and it's items - also supporting the custom fields handled by the MySignaturItem class.

With these to classes in place, you can now set up the custom feed parser, could look like:

public class MySignaturFeedParser : SignaturFeedParser<MySignaturFeed, MySignaturItem> {

    public override MySignaturFeed ParseFeed(SyndicationFeed feed) {
        return new MySignaturFeed(feed, ParseItems(feed));
    }

    protected override MySignaturItem ParseItem(SyndicationItem item, Dictionary<string, string> fields) {
        return new MySignaturItem(item, fields);
    }

}

and then add a composer to replace the default implementation of ISignaturFeedParser:

[ComposeAfter(typeof(SignaturComposer))]
public class MySignaturComposer : IComposer {

    public void Compose(IUmbracoBuilder builder) {
        builder.Services.AddSingleton<ISignaturFeedParser, RaSignaturFeedParser>();
    }

}

Notice that your MySignaturComposer should run after the package's SignaturComposer to ensure that things are set up in the correct order.



SignaturJobsService

The package contains the SignaturJobsService class, which is responsible for the import. The class contains a number of virtual methods than can be overridden by creating a custom class extending SignaturJobsService. Eg. if the RSS items contain a custom teaser field, the package doesn't know what to do with this out of the box. But by overriding the UpdateProperties method, you can set the corresponding `teaser´ property in Umbraco:

using Limbo.Integrations.Signatur;
using Limbo.Umbraco.Signatur.Models.Import;
using Limbo.Umbraco.Signatur.Models.Settings;
using Limbo.Umbraco.Signatur.Services;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Options;
using Umbraco.Cms.Core.Models;
using Umbraco.Cms.Core.Services;

namespace UmbracoTen.Packages.Signatur;

public class MySignaturJobsService : SignaturJobsService {

    public MySignaturJobsService(IOptions<SignaturSettings> settings, IWebHostEnvironment webHostEnvironment, IContentTypeService contentTypeService, IContentService contentService, ISignaturFeedParser signaturFeedParser) : base(settings, webHostEnvironment, contentTypeService, contentService, signaturFeedParser) { }

    protected override bool UpdateProperties(ISignaturItem item, IContent content, ImportTask task, SignaturImportJobsSettings settings, bool isNew) {

        // Call the base method so the package does what it should by default
        bool modified = base.UpdateProperties(item, content, task, settings, isNew);

        // Get the old and new teaser values
        string? oldTeaser = isNew ? null : content.GetValue<string>("teaser");
        string? newTeaser = item is MySignaturItem my ? my.Teaser : null;
        SetValueIfModified(content, "teaser", oldTeaser, newTeaser, ref modified);

        // Return whether the content item properties were modified
        return modified;

    }

}



SignaturModelFactory

By default properties using the Limbo Signatur Job Data property editor will return a ISignaturItem value. If you want it to return something else, you can replace the SignaturModelFactory factory with your own implementation - eg. if you've implemented a custom feed converter, you may wan't to return your concrete type instead:

public class MySignaturModelFactory : SignaturModelFactory {

    public MySignaturModelFactory(ISignaturFeedParser signaturFeedParser) : base(signaturFeedParser) { }

    public override Type GetJobDataValueType(IPublishedPropertyType propertyType) {
        return typeof(MySignaturItem);
    }

    public override object ConvertJobData(IPublishedElement owner, IPublishedPropertyType propertyType, ISignaturItem item) {
        if (item is not MySignaturItem my) throw new ComputerSaysNoException("This shouldn't happen!!!");
        return my;
    }

}

In this case, MySignaturItem implements the ISignaturItem interface, but you could also return your own type that is based on ISignaturItem or MySignaturItem instead.