So when I say I work with Umbraco, people kind of always go, "ahh Umbongo Umbongo, they drink it in the Congo" referencing the TV advert jingle for sugar and fruit flavoured drink 'Umbongo' from the mid-nineteen eighties; which I can't deny is a particulary catchy jingle, but one I've always felt slightly self-concious singing along to. On the other hand, the Kia-Ora jingle of the same vintage and ouvre is as catchy as a rash, and I'm much more comfortable with it in the sing-a-long stakes. So when I had to name my blog which would largely concern Umbraco subject matter and I HAD to pick an eighties fruit based tv advert to reference, I chose the Kia-Ora one. Now I could have gone with the ad strapline 'We all adore a Umbraco' but somehow 'Umbraco, too orangey for crows' made more sense (nonsense). So sorry for wasting your time with this explaination, but I think it gives a fairly good indication about whether it's worth reading any of the blog posts...

Editing some Tabular Data in Umbraco V8

Written by @marcemarc on Sunday, 14 March 2021

So this is just another modern, standard back-to-basics, blog post about a thing, no puns, no ultra-clever subtle sideshow, no allegories, nothing to read between the lines, no insights into the well of humanity on this one, oh no, not this time.

I make this clear in order to avoid regular customers from reading on and becoming disillusioned with the text - don’t worry, dear dear reader, another flight of fancy will be along soon.

But in the meantime, Tables, we’re talking tables and tabular data - and editing this data in Umbraco V8.

Editing tabular data is awkward because as we’ve discussed many times before on this blog, we’re always trying to design an editing experience that feels in harmony with how the content is eventually presented. We say ‘in harmony’ because the act of editing content IS different from that of viewing content and there are nuances involved: the source of the data, and how people feel when trying to complete the task of editing (or creating) the content, this means that a WYSIWYG or live preview accompaniment isn't always the 'best' or only way.

With tabular data and HTML tables, and Umbraco there are, it seems, lots of options...

TinyMce RichTextEditor Tables 

undefined

One option is to enable the ability to insert a table in a TinyMce Rich Text Editor, it’s not too bad, it’s a bit fiddly right? And how often do you end up just switching to the raw HTML to, you know, ‘colspan’ that cell… and is its outcome responsive?

Well, If you are ploughing this furrow then take a glance at these custom TinyMCE configurations, that are in my ‘goto’ things to add to the tinyMCE.config file:

<!-- Use percentages instead of pixels for table cell widths-->
  <config key="table_responsive_width">true</config>
<!-- default table attributes eg ensure a styleable css class is on every inserted table--> <config key="table_default_attributes">{ "border" : "0", "class": "table"}</config>
<!-- provide some default 'styles' for the table (if you are not using the css class to control this)--> <config key="table_default_styles">{ 'border-collapsed': 'collapse', 'width': '100%'}</config>
<!-- provide some styling choices for the editor to select when inserting the table. --> <config key="table_class_list"> [ {"title": "Responsive", "value": "table"},{"title": "None", "value": ""},{"title": "Hover", "value": "table table-hover"},{"title": "Striped", "value": "table table-striped"},{"title": "Condensed", "value": "table table-condensed"},{"title": "Bordered", "value": "table table-bordered"} ] </config>  

So, it's a rudimentary way for an editor to add a simple Table, but as an implementer, in a template view you’ve lost a little control of the HTML markup, the storage of the data is wrapped ‘a little’ in its presentation.

There are of course external tools that can help generate ‘good’ HTML table markup: https://ianrmedia.unl.edu/responsive-table-generator-tool (from spreadsheets, or by manually entering data) - and the output of these editors can be pasted into TinyMce or a Macro, but there is a cognitive shift for editors when they need to move outside of Umbraco, and you start to need to know a little about HTML, which is always a good thing! - but one of the things a CMS is trying to abstract. 

So how about something a bit more whizzy? 

Well Anthony Dang and The Radley Yeldar Devs (which should be a band name right?) put together, last year, a specific table editing custom property editor.

undefined

https://github.com/rydigital/Our.Umbraco.Tables

Again, it’s kind of, for building ad-hoc tables, the editor can add new rows and columns, but what’s lovely is the data entered into the table is stored and retrieved in a strongly typed way, so you can then custom build the actual table markup when displaying the table, allowing you to take into consideration responsiveness, accessibility etc - you have full implementation control.

And you could probably achieve something similar with the Grid and using a custom Grid Renderer file.

What if the table is not that ad-hoc?

These approaches though are aimed at editors adding a generic one-off flexible ‘table’, but what if you have to use the same structure table on different pages? In the context where the table has the same columns, every time it is created there is an unnecessary overhead to ask editors to recreate the same column headers each time...

And this is the scenario I encountered this week - I'm building a kind of global Product Repository in Umbraco V8, and each product, it turns out, can have a table with multiple rows of technical data - ‘the corrosivity of the product in different circumstances’. The columns and headers are the same each time it is displayed on each product - and the editor can add as many rows of data as they want, but it will probably only be about 3-4 rows per product.

The text in the table needs to be translatable, and I’m using variants for other properties that need to be translated, but it’s a bit much to reproduce the table in 20 different languages when the 'data' is the same and asking the translators to translate the same table headings on every product...it’s not the same as an ad-hoc table situation. We want the editors to focus here on the data, not the markup of the table.

Also, we'll need full control over the markup when it’s displayed, for accessibility and responsiveness, but also because the data will feed into different devices, and not necessarily a webpage - perhaps a table won't be appropriate to display the data, and we also need to query against the data - find me all the products that have x data in their technical data table.

(Aside: The products are being pushed to an Azure Search index, so as long as the data can be described in a strongly typed fashion, that level of complex querying and faceting is actually taken care of by Azure Search).

So essentially, in old money, this is probably 'just' a Nested Content repeating item, where the Document Type Element describes the ‘columns’ of the table, and the editor can keep adding new repeating content items, one for each row…

... that would be functional, but the result doesn’t feel very tabular…

We really want the editor to get a sense they are editing a table, surfacing the visibility of each row of data in the backoffice, in well, table row form… in V7 maybe we would have been creative with the use of the | character and the Nested Content name template or Stacked Content but…

We don’t do Nested Content anymore, do we?

Not in V8, it’s virtually obsoletish, and we have been politely introduced to the BlockList Editor, which can do anything…

The BlockList Editor can do anything

… but can I make the experience a bit like a table editor?

(*Spoiler*, I don’t want anybody to get tense here about whether it will or will not be possible to do this, we live in anxious times, and there is only so much jeopardy we should be expected to experience when reading a back-to-basics blog post like this - so yes, it kind of is possible, read on to find out how).

So first we’ll define our Element Type:

undefined

(notice the lovely menu for choosing an Element - coming soon to Umbraco V8.12… you didn't create this as a Doc Type first, and then swear, and go back in to find and tick the IsElement box... you just chose to create an Element from the menu!)

On the Element Type we set up the structure for our Table Columns, some of the column data will be links to other Products, which would all be different in different language variations - but we can make this a content picker, and calculate the links automatically, the editor doesn't need to think and make the link manually. One of the columns will be a ‘total’ of the DFT column values, so we don't need to ask the editor to calculate this - we can do the math, no you do the math, no it’s ok we’ll do the math for you...

undefined

Now in our BlockList Editor we can set this Document Type Element to be the only available block…

If we set Inline editing mode to true, it will just behave like Nested Content, which we’ve already established isn’t what we necessarily want, but without that it’s just going to be ‘blocks’, not showing any data, opening up a panel to add the data like Stacked Content…

… but we can specify a custom HTML view to use when displaying each block in the backoffice, and if we set Live Editing Mode to true, we’ll see any updates in the panel, updated in real-time in the custom view, and we can associate an AngularJS controller with the view, ‘and also do the Math’...

undefined

undefined

The custom HTML view

Our custom view can be a table!

<div>
    <table class="corrosion-table" border="1">
        <tr><th>Zinc Rich Primer</th><th>DFT (µm) </th><th>Primer</th><th>DFT (µm) </th><th>Topcoat</th><th>DFT (µm) </th><th>Total DFT (µm) </th><th>Corrosivity Category</th><th>Edit</th></tr>

        <tr>
            <td> <span ng-bind="block.data.zincPrimerProductCode"></span></td>
            <td><span ng-bind="block.data.zincPrimerDFT"></span></td>
            <td><span ng-bind="block.data.primerProductCode"></span></td>
            <td><span ng-bind="block.data.primerDFT"></span></td>
            <td><span ng-bind="block.data.topcoatProductCode"></span></td>
            <td><span ng-bind="block.data.topcoatDFT"></span></td>
            <td><span ng-bind="block.data.corrosivityCategory"></span></td>
            <td style="text-align:center">
                <a class="btn btn-secondary" ng-click="block.edit()">
                    <span class="icon icon-edit"></span>
                </a>
            </td>
        </tr>
    </table>
</div>

And there, the data is displayed inside a table!

undefined

But it's a mess!

1) we’re seeing the Umbraco Udi of the picked product and we haven’t added stuff together

and

2) we’ve got multiple Tables for each block row, with a table header repeated above each row of data…

Let’s address the Picked Product problem first by adding an angularJS controller to the view

the AngularJS controller

angular.module("umbraco").controller("corrisionTablesController", function ($scope, entityResource) {

    //this method takes the values stored for the block and retrieves the 'Name' of the picked entity + does the maths
    function init() {
        var zincPrimerUdi = $scope.block.data.zincRichPrimer;
        var primerUdi = $scope.block.data.primer;
        var topcoatUdi = $scope.block.data.topcoat;

        $scope.zincPrimerDFT = parseInt($scope.block.data.zincRichPrimerDFT) || 0;
        $scope.primerDFT = parseInt($scope.block.data.primerDFT) || 0;
        $scope.topcoatDFT = parseInt($scope.block.data.topcoatDFT) || 0;
        $scope.totalDFT = $scope.zincPrimerDFT + $scope.primerDFT + $scope.topcoatDFT;

        //the mediaResource has a getById method:
        if (zincPrimerUdi.length > 0) {
            entityResource.getById(zincPrimerUdi, "Document")
                .then(function (entity) {
                    console.log(entity);
                    $scope.zincPrimerProductCode = entity.name;
                });
        }
        else {
            $scope.zincPrimerProductCode = '-';
        }
        if (primerUdi.length > 0) {
            entityResource.getById(primerUdi, "Document")
                .then(function (entity) {
                    console.log(entity);
                    $scope.primerProductCode = entity.name;
                });
        }
        else {
            $scope.primerProductCode = '-';
        }

        if (topcoatUdi.length > 0) {
            entityResource.getById(topcoatUdi, "Document")
                .then(function (entity) {
                    console.log(entity);
                    $scope.topcoatProductCode = entity.name;
                });
        }
        else {
            $scope.topcoatProductCode = '-';
        }
    }
// watch for changes and update the view when changes are made $scope.$watch("block.data.zincRichPrimer", function (newValue, oldValue) { if (newValue != oldValue) { init(); } }); $scope.$watch("block.data.primer", function (newValue, oldValue) { if (newValue != oldValue) { init(); } }); $scope.$watch("block.data.topcoat", function (newValue, oldValue) { if (newValue != oldValue) { init(); } }); $scope.$watch("block.data.zincRichPrimerDFT", function (newValue, oldValue) { if (newValue != oldValue) { init(); } }); $scope.$watch("block.data.primerDFT", function (newValue, oldValue) { if (newValue != oldValue) { init(); } }); $scope.$watch("block.data.topcoatDFT", function (newValue, oldValue) { if (newValue != oldValue) { init(); } }); init(); });

In our controller, we have an updateRowData() function, that will read in the Udis from the $scope.block.data property, and use the entityResource.getById method to get the picked entity, and read the value of the product code to display instead of the Udi.

We’ll want this to update whenever the $scope.block.data property is updated - so we’ll set a 'watch' on that value and call updateRowData() whenever this changes, the same with the other three fields.

And we’ll do the adding up here too, “no, you do the math, we’ll do the math” etc

Updated Html View

<div ng-controller="corrisionTablesController">

    <table class="corrosion-table" border="1">
        <tr><th>Zinc Rich Primer</th><th>DFT (µm) </th><th>Primer</th><th>DFT (µm) </th><th>Topcoat</th><th>DFT (µm) </th><th>Total DFT (µm) </th><th>Corrosivity Category</th><th>Edit</th></tr>

        <tr>
            <td> <span ng-bind="zincPrimerProductCode"></span></td>
            <td><span ng-bind="zincPrimerDFT"></span></td>
            <td><span ng-bind="primerProductCode"></span></td>
            <td><span ng-bind="primerDFT"></span></td>
            <td><span ng-bind="topcoatProductCode"></span></td>
            <td><span ng-bind="topcoatDFT"></span></td>
            <td><span ng-bind="totalDFT"></span></td>
            <td><span ng-bind="block.data.corrosivityCategory"></span></td>
            <td style="text-align:center">
                <a class="btn btn-secondary" ng-click="block.edit()">
                    <span class="icon icon-edit"></span>
                </a>
            </td>
        </tr>
    </table>

</div>

Now we have nicely updated data, and we're correctly showing the picked product code.

undefined

But we have a Table for 'each row'... really we want one table, and each row to be a row within it... which we can't really do, but we can fake it!

Faking a single table

Each block has an index property that lets you know where in the order of picked block properties it is, and we can use that to set a CSS class on each table’s header row.

<tr ng-class="{firstheaderrow : block.index == 0, additionalheaderrow : block.index > 0}">

So the first block will have a CSS class of ‘firstheaderrow’ and subsequent blocks will have the CSS class ‘additionalheaderrow’.

We can specify a stylesheet for the editor, and use these CSS classes to ‘hide’ the subsequent header rows - but we still want the ‘width’ of the headers to remain the same for each column, in order to fake the lining up of these columns, we'll use visibility: hidden rather than display:none and set the height to be 0 to make them disappear but retain their width;

table.corrosion-table .additionalheaderrow {
visibility: hidden;
height: 0;
padding: 0;
border-top: 0;
overflow: hidden;
line-height: 0;
}

undefined

Looking more like a table! the columns are lined up but the rows have uneven gaps, this is because the BlockList Editor itself has a wrapping div for each block, with a min-height of 48px, and the rows look unevenly spaced when they are lacking their header, and there's not much we can do about that without affecting other Block List implementation, so let's work with the gap - and set the min-height on each of our custom tables to match:

table.corrosion-table {width:85%; min-height:48px}

undefined

the 'gap' is still there, but because it's consistent, the eye doesn't notice and we perceive it as one whole table - and it almost looks a little like the gap is on purpose.

Now we could have gone further, and placed text boxes in the table cells of the custom view and use those to allow the editor to edit the data inside the table, but I've preferred instead, to have the Edit link in the final column of the row, to open the pull out panel.

I agonised over this, but it comes back to being in harmony with the editing experience, and I think it’s because the editor is ‘picking’ products, which involves the slide-out panel anyway, that, it works out well that they are already focussed inside the infinite editing paradigm. If it was purely numbers that were being entered I might have tried using text boxes inside the columns for a spreadsheet-like ‘live editing’ dalliance.

Finally

I can then populate my AzureSearchIndex with a strongly typed IEnumerable of Corrosion Data Rows which are queryable.

       [SimpleField(IsFilterable = true, IsSortable = false)]
        public IEnumerable<CorrosionTableDataRow> CorrosionTableData { get; set; }

And then on the front end of the site, I have full control over the table markup to display this data, (or even maybe not display it as a table, the data is separate from the presentation) 

undefined

I can follow good practice for accessibility using a <caption, and setting scope=”col” etc which are normally additional 'difficult to achieve tasks' for Editors inside a CMS table editor, and inevitable get left out, remind yourself here:

https://www.w3.org/WAI/tutorials/tables/

Also, check out the new accessibility course for Umbraco:

https://umbraco.com/training/course-details/accessibility/

So that's it, no clever joke at the end to tie it all together, sorry - but if you enjoyed this back-to-basics article don’t forget to drop a like, leave a comment, and subscribe using the link below. 

 


Umbraco V8, Variants and limiting editor access by language - an adventure story

Written by @marcemarc on Wednesday, 27 January 2021

The ‘new’ version of Umbraco V8 trumpeted the arrival of language variants into the core of Umbraco.

Previously on Umbraco

Previously on Umbraco, for large multilingual content managed offerings you would implement multiple content tree structures, one for each language and ‘relate’ alternate translations of pages together using relations OR you would use the ‘Vorto package’ to enable you to edit variations of language on a single node. 

undefined

The decision on which approach to use depended largely on two factors: 

1) how the editors would update the content, eg one multi-lingual editor handling multiple-translations of a site - Vorto would win hands down - if different editors in different countries, editing only one language: the multi-tree approach had more going for it. 

2) Whether the sites would be translated 1-1, same images, same layout, same pages, just 'translated text' OR whether actually the flexibility would be needed to have different pages in different territories to bend and shape the content to suit the culture it was being published too.

The desire for a mechanism to ‘vary’ content in Umbraco for different audiences, but managed 'on the same content item', had been on a lot of people’s wish lists and regularly Codegarden talks would focus on how a solution had cleverly worked around these deficiencies to deliver personalisation of some kind or a multi-lingual setup to draw deep impressed breaths from the Umbraco developer brethren.

To implement this 'properly' in the Umbraco core would mean changes to the underlying database tables, which meant it was an ideal candidate for the next major version at the time (V8) - and implementing a‘Vorto-like’ language variants experience was seen as a way to validate the underlying structural changes that would deliver the future exciting prospects of variants and deliver a ‘new feature’ at the same time.

The reason why I give this vague take on the history, (and this may not be exactly what happened!) - is that I think the aim of language variants in V8 wasn’t to necessarily implement a completely nuanced, feature-complete language editing experience in Umbraco that would work in all scenarios, (even if it may have felt to have been marketed in this way) - but more to introduce the concept of ‘variants’, that would enable language variant functionality to be iterated and improved upon over time and pave the way for ‘other things’ to 'vary' - the fruits of which people are now harvesting in the uMarketingSuite package.

I think the context helps understand some of the anomalies, and really, to be fair, it turns out that ‘language variants’ probably aren’t a ‘simple’ first variant implementation, because language editing ‘is different’ to a single editor just varying content for a different audience, language and translations and cultures is hard the whole world over - but what initially exists in V8, with the side-by-side editing is pretty cool.

[Aside - But also,  I should declare I AM bitter about variants, as I suspect it’s the reason why we’ve lost the ‘Change Document Type’ functionality from the right-click menu in the content tree - because the changes in the database structure + complexity of the UI to explain you are changing the doctype for each different language variation... well 'would be quite hard to do' - and what if the new doctype ‘doesn’t vary’? etc. I miss 'Change Document Type' as a thing.]

undefined

Anyway, Anyway, this far in and I'm already using double Anyways... 

The adventure starts here

Anyway, nearly two years on from V8’s release I’m implementing a repository of global products - it isn’t a website in itself but rather a central location for Products and their technical details to be updated/translated. The products will be available to display in multiple 'other Umbraco sites' in multiple territories and multiple languages - via an API layer (in this case driven rather robustly and scalably by Azure Search).

This makes V8 Variants a good candidate for the solution, it will provide the side-by-side translating of content experience (which I have to say, demo’d very well...) and there will be a single point of truth for a product, and it's language variations. Some properties for a product will be ‘fixed’, eg 'Product Code', and some can be varied by language, eg the 'Product Summary'.

However, one thing to be aware of, is that in Umbraco, permissions for backoffice Users' content managing actions are ‘node’ based, so if you give somebody permission to publish a product, they can choose to edit and publish that product in each of its language variations. 

undefined

There is an issue on the tracker, https://github.com/umbraco/Umbraco-CMS/issues/3830 where the super genius Kjac identifies the problem and proposes a nice solution.

In our scenario this isn’t too much of a problem, as the products will likely be translated once, and not be updated too often, the ‘marketing information’ will be supplied in the Umbraco sites that ultimately display the products, this is only really for the technical information, so the chances of new territory editors logging in, and accidentally updating and publishing the wrong language variant is unlikely. We trust them to tick the right box.

undefined

That said, having seen the demo, the client assumed ‘it would be possible’ to set which languages a backoffice User had access to edit and publish and were surprised it was not possible.

I guess if you are building a language variant editing scenario that IS one of the User journeys that you would reasonably expect to have been catered for, but in the slightly differently focussed scenario of validating the concept of variants, you can see how that journey might not have been included!

Yet! - nobody disputes it isn't a good idea, it will undoubtedly be implemented at some point in the future.

Setting Sail

Our client wanted to know what would be involved if they did REALLY need this functionality, so I carried out a quick development spike to see what could be achieved by utilising the existing extension points of Umbraco… 

… this is how I got on.

Assigning Permissions

First, we need a way of saying ‘Can the current backoffice user manage a particular language?’ - it’s possible to set a default language for a User, but only 'one language', what if a user needs to be able to manage multiple languages? Well, Umbraco has the functionality of ‘User Groups’ so this seems the natural way to manage who can see what, without any additional extension of Umbraco

We created some new User Groups, and as there aren't really any ways to extend User Groups with metadata and because I love a good convention... we followed one:

  • LanguageEditors_de-DE
  • LanguageEditors_es-ES
  • LanguageEditors_en-GB

By following this naming convention it allows us to neatly map a User Group to a culture code - ok it’s a hack! By tacking on the culture code of the group though - it means new groups can be created in the future, without having to change the implementation code. It's easy to understand. 

undefined

The thinking here is: ‘any user’ in a User Group starting with ‘LanguageEditors’ is someone who needs to have their language variant options restricted. If you are not in one of these groups, Umbraco will operate in the standard way for you... seeing all variants…

(if you are unhappy with this convention approach, I suggest you stop reading now, as there is a much more outrageous hack later on)

Applying the convention

Our old friend the EditorModelEventManager.SendingContentModel event to the rescue. - https://our.umbraco.com/documentation/reference/events/EditorModel-Events/

Normally you’d use this event to set default values for properties, it’s fired ‘just before’ a backoffice node is displayed in Umbraco for editing, and it exposes the complete Model of the editable content, including all variants (e.Model.Variants)  and basically, it enables you to tweak things at the last moment! 

So if we check that the page being loaded for editing ‘has variants’ - we can get a reference to the Current User and check their User Group membership to see if they are in a ‘LanguageEditors’ group, and if they are - use this list of groups to filter the variants they are allowed to see. 

private void EditorModelEventManager_SendingContentModel(System.Web.Http.Filters.HttpActionExecutedContext sender, EditorModelEventArgs<Umbraco.Web.Models.ContentEditing.ContentItemDisplay> e)
      {
          bool hasVariants = e.Model.Variants.Count() > 1;
          // remove variants from users in Language Restricted User Groups
          if (hasVariants) {
              using (UmbracoContextReference umbracoContextReference = _umbracoContextFactory.EnsureUmbracoContext()) {
                  var umbracoContext = umbracoContextReference.UmbracoContext;
                  IUser currentUser = umbracoContext.Security.CurrentUser;
                  var languageGroups = currentUser.GetCurrentUserLanguageGroups();
                  bool hasLanguageGroupRestrictions = languageGroups.Any();
                  if (hasLanguageGroupRestrictions) {              
                          e.Model.Variants = e.Model.Variants.Where(f => f.Language != null && (languageGroups.Contains(f.Language.IsoCode.ToLower())));
                  }                  
              }
          }              
      }

and the custom extension method on IUser, that retrieves the groups looks like this:


public static class UserLanguageGroupExtensions  {
      public static IEnumerable<string> GetCurrentUserLanguageGroups(this IUser currentUser) {
          List<string> languageGroups = new List<string>();
          foreach (var group in currentUser.Groups) {
              // check for 'special LanguageEditors group membership
              if (group.Name.StartsWith("LanguageEditors_")) {
                  //strip of the culture from the end of the language User Group name...
                  languageGroups.Add(group.Name.Split(new char[] { '_' }, StringSplitOptions.RemoveEmptyEntries)[1].ToLower());
              }
          }
          return languageGroups;
      }
    }

Now, when the user creates or edits a page in Umbraco, only the language variants matching the User Groups, are displayed for 'switching to' and 'side-by-side' comparison…

undefined

and if a user saves or publishes the page, the checkbox options only match the languages they are allowed to manage. Neat!

undefined

This is great, but if you want the editor to see the fallback default language, perhaps English, for side by side comparison, but you don't want the editor to be able to change the content of the fallbacck default language, then it gets a bit messy...

Populating default values for variants

One option is to again use the EditorModelEventManager_SendingContentModel event - and  ‘read’ all the existing fallback language property values - and use these as ‘default values’ for the variants that haven’t been set yet… 

The trick here is to realise that all variants have a 'State' and those that haven't been created yet have the ContentSavedState.NotCreated state - so any new variants get the default language values as umm defaults:


if (hasVariants) {
var defaultEnglishVariant = e.Model.Variants.FirstOrDefault(f => f.State != Umbraco.Web.Models.ContentEditing.ContentSavedState.NotCreated && f.Language.IsoCode == "en-GB");
if (defaultEnglishVariant != null) {
// we have english variant
// get existing English variant values
var defaultEnglishVariantProperties = defaultEnglishVariant.Tabs.SelectMany(f => f.Properties);
// now set the name to be the English name for all uncreated variants
foreach (var variant in e.Model.Variants.Where(f => f.State == Umbraco.Web.Models.ContentEditing.ContentSavedState.NotCreated && f.Language.IsoCode != "en-GB")) {                      
variant.Name = defaultEnglishVariant.Name;
foreach (var property in variant.Tabs.SelectMany(f=>f.Properties)) {
property.Value = defaultEnglishVariantProperties.FirstOrDefault(f=>f.Alias.InvariantEquals(property.Alias))?.Value;
}  
}
}
}

This provides No side-by-side comparison - but the translator can see the default values they are aiming to translate…

Beside-by-side ourselves

But we want the lovely side-by-side comparison that we demo to everyone…

So I thought a bit more…

Could we allow the editor to see the fall back English version?, for side-by-side translation, but then put a ‘hard stop’ on saving ‘anything’ if the English version was accidentally updated...

For this, I looked at the Content Saving event of the Content Service, and the IsSavingCulture extension method of the ContentSavingEventArgs, which allows you to check if a particular language culture is being saved during the event, eg if the English Version was being saved, I could cancel the save operation:


private void ContentService_Saving(IContentService sender, Events.ContentSavingEventArgs e) {
     IUser currentUser = default;
     List<string> languageGroups = new List<string>();
     bool isSavingAVariantWithoutPermission = false;
     bool checkLanguageGroups = false;

     using (UmbracoContextReference umbracoContextReference = _umbracoContextFactory.EnsureUmbracoContext())  {
          var umbracoContext = umbracoContextReference.UmbracoContext;
          currentUser = umbracoContext.Security.CurrentUser;
          languageGroups = currentUser.GetCurrentUserLanguageGroups().ToList();
          checkLanguageGroups = languageGroups.Any();
     }

     foreach (var entity in e.SavedEntities) {
          if (checkLanguageGroups && !isSavingAVariantWithoutPermission) {
               //cultures being saved
               var savingCultures = entity.AvailableCultures.Where(f => e.IsSavingCulture(entity, f)).ToList();
               isSavingAVariantWithoutPermission = CheckCurrentUserIsSavingAVariantWithoutPermission(languageGroups, savingCultures);
          }      }
     if ( isSavingAVariantWithoutPermission) {
          e.Cancel = true;
          e.Messages.Add(new Events.EventMessage("Saving Cancelled", "You do not have permissions to save all these language variations", Events.EventMessageType.Error));
     } }

undefined

This enables us to update the logic in the EditorModelEventManager_SendingContentModel to ALWAYS allow the default language, en-GB, in this case to be displayed for people who have these restricted LanguageEditors permissions:


     if (hasLanguageGroupRestrictions) { 
          e.Model.Variants = e.Model.Variants.Where(f => f.Language != null && (languageGroups.Contains(f.Language.IsoCode.ToLower()) || f.Language.IsoCode == "en-GB"));
    }

We've cracked it... side-by-side comparison and restricted editors can't save or update the default language, it's not a perfect UX, getting the error message, but default content is safe... we are there... 

... but not quite ... if the editor switches to view the default language, and clicks in one of the fields in the default language accidentally, even if they don't update a value - and seemingly sometimes even if they only open it for side-by-side comparison - it's likely the angularJS will mark the default language variant as 'dirty' - and even though nothing has changed, the IsSavingCulture method will return true for the default language variant and our code above will stop the editor saving anything!

... a few idle click tests shows this will happen quite a lot... grrr

What we really really want is the properties on the fallback English culture to be ‘visible’ but not editable - like a ‘read only’ state…

Read Only

Wait a minute, didn’t we see a ‘Read Only’ option for each variant property when we were trying the option of ‘just’ copying the English values across - hang on, this is it, we just need to set that to true in the EditorModelEventManager_SendingContentModel event for each property of the default language variant and I bet we won’t even need the ContentSaving event to ‘stop the save’, ‘stop the save’...


if (!languageGroups.Contains("en-gb")) {
// set default entries to be readonly
foreach (var variant in e.Model.Variants) {
if (variant.Language != null && variant.Language.IsoCode == "en-GB") {                        
foreach (var tab in variant.Tabs) {
foreach (var property in tab.Properties) {                                    
property.Readonly = true;
}
}
}
}
}

Et voila…

zut alors!

(still not sure I can use French phrases in a post-Brexit world) 

undefined

The property is still ‘editable’ how come? I'm fairly sure I know what should happen when I set a property to be Read Only! 

Sadly, it turns out the ‘Read Only’ property doesn’t change the UI !!- the angularJS property editors aren’t looking for this value, even though it is set to true on their 'model', and I 'bet wrong' - the property editors don’t all magically become ‘read-only’ when this is set - they operate normally… (though any changes aren’t saved!) 

It’s been raised as an issue here, but there is a need to identify a use case:

https://github.com/umbraco/Umbraco-CMS/issues/7906

Thwarted - read-only another way?

Thwarted once more, but hang on let's not give up - looking at the property editor model again - I can also change the ‘view’ that the property editor is using for each property to become the  ‘readonlyvalue’ (this is the view used for the non-editable label property editor):


   foreach (var tab in variant.Tabs) {
        foreach (var property in tab.Properties) {
             property.View = "readonlyvalue";
             property.Readonly = true;
         }
    }

This works reasonably well for the rich text editor or textbox properties, the text values of the properties are displayed, and can be used for side by side editing - but pickers or the grid only render their ugly data eg just display the Guids of the picked items or the JSON. This just makes it look like the page hasn't loaded properly, but would I suppose be viable if you only had textboxes and rich text areas to compare between variants.

undefined

It also breaks the display of non-varying property content when you switch to the non-default language variants view - normally these non-editable properties display their editor and the content but appear greyed out and looks really odd if this is the raw data instead… and gives off the scent that something is broken.

The 'readonlyvalue' view is only really for the 'label' editor - but in theory you could create a custom read-only version of each property editor view and use this trick to switch each type to a nice rendering of the way the editor stores its content in a read-only fashion... sigh... which would feel like a lot of work! and I just want it 'to work'.

What I want is the properties to look like they normally do, but just be greyed out and non-editable - in fact EXACTLY like those non-varying properties when they are displayed on a language variant doc-type, you still see it, but it’s greyed out…

undefined

I wondered how is that done?

So I had a look at the source code and I found an angularJS helper: propertyEditorDisabled(property) that is called for each property, what’s the logic here? 

https://github.com/umbraco/Umbraco-CMS/blob/34e80d86e8c0b754f6b7a02e307f53cb32806bbe/src/Umbraco.Web.UI.Client/src/common/directives/components/content/umbtabbedcontent.directive.js#L142


var canEditCulture = !contentLanguage ||
// If the property culture equals the content culture it can be edited
property.culture === contentLanguage.culture ||
// A culture-invariant property can only be edited by the default language variant
(property.culture == null && contentLanguage.isDefault);

So basically a property becomes 'read-only' if the 'culture of the property' doesn’t match the 'culture of the page' being edited (eg for a non-varying by culture property)...

(hmm, might have a look at this later, would it be a good place to implement the ‘readonly’ setting?) 

Outrageous Hack

So now I give you our 'outrageous hack' - all we need to do, to trigger the core to make the property editor disabled and read-only and still show it’s content but greyed out… is to set the language culture of the property to be different to the language culture of the page… 

… lets go with en-CX - which of course is the language culture of Christmas Island: https://en.wikipedia.org/wiki/Christmas_Island 

(yes, no need to tweet me - I know this hack won’t work for websites that are built with the Christmas Island culture in mind… but I felt it was obscure enough for most sites… and unlikely to cause a clash!)


  foreach (var tab in variant.Tabs) {
       foreach (var property in tab.Properties) {
              property.Culture = "en-CX";
              property.Readonly = true;
}
  }

Which is exactly how we want it to behave! - the fallback language properties are visible to the editor for the side-by-side comparison, but aren’t editable, and are greyed out to indicate as such, this prevents the fallback language from becoming ‘dirty’ or accidentally updated.

undefined

We almost don’t need the Content Service in place with it’s 'hard stop': but even in this setup it’s still possible for an editor to change the ‘Name’ of the default fallback language content - so if total lockdown is your aim, you can keep the contentservice saving event, and with this 'Christmas Island hack' in place, the IsSavingCulture method performs reliably.

Blimey, we got there in the end!

But also, we probably don't want editors to be able to 'publish' pages of different language/cultures either, if they are not in those groups - and on the ListView they can pick multiple items, and choose to publish multiple items - a dialog appears with checkboxes for each variant, and they can tick all of them, and potentially publish something that shouldn’t be published yet. 

undefined

Sigh, and there is also the main language switching navigation dropdown too - you can still see all the language dropdown options there, even if you can’t edit them…

undefined

There are multiple places this happens, where all the languages are made visible to the editor, so somehow the hack still feels incomplete…

Bonus Hack

But one thing I noticed with all these situations - they all call the languageResource.getAll() method to get a list of all languages to display the options to the editor - which calls the api endpoint:

/umbraco/backoffice/UmbracoApi/Language/GetAllLanguages 

Now if you are not familiar with intercepting AngularJS requests - have a read of this excellent (5yr old article - still very relevant today in this context) from 24 days in Umbraco and the wunderkind Matt Brailsford: 

https://24days.in/umbraco-cms/2015/umbraco-7-back-office-tweaks/

And you’ll see there’s something further we can do - we can intercept all requests that are made to this get all languages endpoint - check the current user’s user groups, if they are in a language editor user group, we can use the convention again to filter out the ‘GetAllLanguages’ response, so it effectively becomes GetAllLanguagesForThisUser… (if User isn’t in a LanguageEditor group it will work as standard)

 Yes it’s the same hack - this time in javascript: 


angular.module('umbraco.services').config([
  '$httpProvider',
  function ($httpProvider) { 
      $httpProvider.interceptors.push(function ($q, $injector) {
          return {
              'response': function (response) { 
                  // Intercept requests content editor data responses
                  if (response.config.url.indexOf("/umbraco/backoffice/UmbracoApi/Language/GetAllLanguages") === 0) {
                        var userLanguageGroups = [];
                      var hasLanguageGroups = false;
                      var userService = $injector.get('userService');
                       // get Current User
                      userService.getCurrentUser().then(function (currentUser) {
                          if (currentUser !== null && currentUser.userGroups.length > 0) {
                              // loop for all groups and see if any are special 'language groups' ones to determine whether any filtering should take place
                              var i;
                              for (i = 0; i < currentUser.userGroups.length; i++) {
                                  console.log(currentUser.userGroups[i]);
                                  var userGroupName = currentUser.userGroups[i];
                                  // check group name starts with languageEditors
                                  if (userGroupName.startsWith("languageEditors")) {
                                      hasLanguageGroups = true;
                                        // split language group name on _ and add language code to userLanguageGroups array
                                      var languageGroupCultureCode = userGroupName.split("_")[1];
                                        userLanguageGroups.push(languageGroupCultureCode)
                                  }
                              }
                          }
                          // check if hasLanguageGroups is true
                            if (hasLanguageGroups) {
                              // if so loop through response.data and filter out any cultures not in the list of user languagesGroups
                              var i = response.data.length;
                              while (i--) {
                                  var availableCulture = response.data[i].culture.replace("-", "");
                                 // remove the culture from the response
                                    if (userLanguageGroups.indexOf(availableCulture) === -1) {
                                      response.data.splice(i, 1);
                                  } 
                              }
                          }
                      });
                  }
                  return response;
              }
          };
      });
  }]);

And now in the language navigation dropdown, you only get the languages that match the language editor groups people are in…

undefined

and when dialogs are shown to ask you to tick which variant for publishing purposes, only checkboxes are shown for those the editor is allowed to check.

undefined

There is of course a potential issue if GetAllLanguages changes in a later version of Umbraco, or is used in a piece of functionality that it’s not ok to filter by the current user groups… but hey we’ve just hacked the properties to all have the culture of the Christmas Islands - so I think this is worth the risk.. and also it's a good chance this will be implemented 'properly' one day in the core.

The end

Anyway, that’s the gist, the output of this 'deep dive' - to enable some editor restriction of the languages that they can view/edit in the Umbraco backoffice when using V8 and variants and using only existing extension points, a naming convention, and ermm some ‘hacks’. 

Hope this helps someone, or you could just trust the editors to tick the right box, I'm sure it will be ok if you do.


The legend of the phoenix, all ends with beginnings

Written by @marcemarc on Monday, 05 October 2020

It was National Poetry Day in the UK last week, and I’m reminded of my Umbraco poem of a few years ago, and how that earned me the semi-official title of ‘Umbraco Poet Laureate’ or I think we decided on ‘Umbraco Artist in Residence’ - because it’s more than just the poetry isn't it?, remember: the watercolour package-icon paintings, the #umbracostreetbingo / #iseeumbracologos photos, the panini sticker album, hack the merchandise, the puppet shows, umbanksy, Umbraco Man, the performance art of festival non-attendance… and ‘Codegarden: The Musical’ that sadly lies unperformed due to Covid.. etc etc

I say semi-official as it was a joke in a conversation, but it came from the mouth of Niels Hartvig, so how much more official can it be? (although, he also has described me as the ‘Mario Balotelli** of the Umbraco community’… and I’m not diving about the place and un-fulfilling my obvious potential on the world stage in response). But hey I got the business cards printed all the same.

Anyway, with any kind of ‘official artist position’ in an institution, you get to well, have a very loose and undefined job description - do ‘artistic things’ whenever you fancy (hey, where’s my bursary?) - but every now and then because of a momentous event, you get coerced to write something commemorative… a birth, a wedding, a sad parting of the ways...  for the official record...

… and it’s really hard …

And I don’t have the words for THIS poem, fortunately, however, somebody else did…

So this is 'Niels Hartvig Festival Keynotes Opening Lines Refactored', a rudimentary cut-up poem in the style of the Fluxus art movement, taking lines from the first 3 minutes of any Umbraco Festival keynote that Niels has delivered***, and reordering, repeating etc, to try to capture well 'something'... to commemorate his hiatus:

You should try to be up here

clumsy, ok thank you for waiting
Let's see if we can get this up and running
umm we gotta a lot to cover over the next one and a half hour
so errr, Say cheese, ahh awesome, what a wonderful day

Thank you very much for coming errr
welcome to the biggest Codegarden ever
without a doubt our biggest ever
the biggest err ever Codegarden
we are more than 380 people err today,
which is err about a little more than twenty times the people at the first Codegarden
err this year there is more than 700 people,
which makes it more than 30 times bigger than the very first one
err so awesome to be back at the err the err Umbraco festival

Hey, before we start I just want to be the first one to use the 'hi-five I suck' tag
the only thing that makes this very different from my normal Christmas Eve
is that I don't get sweaters like these from my inlaws which makes it even better...
so the book will be a little delayed, and that's my fault

ahhh it's amazing to be back
umm I've really been looking forward to this
I love Codegarden is because we're all together
all the people you talk to on the forums, maillist people suddenly you see them in real life
this is fantastic
but we just have so much to share

You should try to be up here
it's scary and awesome at the same time

so let's err let's start
perhaps always people say
Doug has this weird thing on my machine, I can't see anything
aha he has notes, he's been preparing
which I have of course...

You should try to be up here
I was here I think as the slide says quite a number of years ago
We have slides and we have demos and there is so much that can go wrong
err which is awesome

So back in the day Per and I did demos and they failed
and then we were told you can't fail in a keynote
so then we made boring slideshow demos
and pre-recorded videos
and almost no dangerous demos
and we are so bored
we need stress
we need panic
we need to smell bad afterwards
and then Pete Duncanson isn't here
so we are going to have a buffet of Yellow Screens of Death

You should try to be up here

umm
those hats are still in use, err at the HQ you have to wear the hat
if you forgot to log out of the computer
and someone gets to post in Slack that you are giving out free beer,
you have to wear the hat.

I am really excited that so many people have come here
it's pretty wild to just stand up here
one of the reasons I love Codegarden is because we're all together
all the people you talk to on the forums, maillist people
suddenly you see them in real life and for me, that's kinda like Christmas Eve

just think about it for a second
people gathered here
all passionate about Umbraco
travelled across the world to share our ideas, our thoughts and maybe even umm... some code
I really think it's crazy

you should try to be up here
it's the most awesome sight ever

Are you ready?

I don't know if you can see the slides now?

Community and Infinity
Are you ready?
don't worry it's not as abstract as it sounds

there is a long break after this one so err

and now I have transitions




* He didn't want a song...

** Strangely, this wasn’t the first time I’ve been compared to a footballer. When working with Kevin Jump at Liverpool City Council, he once described me as ‘The Eric Cantona of the team,  he reckoned all the work of the team on a particular project seemed to pass through and be linked by me.... And previously when I worked in the comedy industry at Avalon Management, the comedian Frank Skinner described me as ‘The Roy Keane of Avalon’ always busy, popping up to fix things and organise different parts of the business, keeping things going when it was least expected, and it seemed like all was lost. Anyway, I’d just like to say that with these three particular talented footballer comparisons, flattering though they are, that, well - I DON’T HAVE AN UNDERLYING PROBLEM WITH ANGER MANAGEMENT OK?

*** Since, all these words are all available in keynotes videos, somebody, with a lot of time on their hands could stitch together a video for this poem - editing all the bits together from the source videos :-P sorry if I've made you inspired to do that...


I used to get mad at my school

Written by @marcemarc on Friday, 25 September 2020

I'm doing the best that I can... 

What now? and is this going to be another long nonsense post?

This week, I updated one of my much heralded/niche/obscure Umbraco packages to V8:

uDictionaryItemSearch

This allows editors to locate 'Dictionary Item Keys' in the Umbraco Dictionary - if they know the key but it's 'nested' or crucially they only know the value that 'appears' on the site - if you are looking at the front end of Umbraco and seeing a word that isn't translated it's impossible to work out what the dictionary key is, without looking in the template or asking someone. Many years ago we inherited an Umbraco 4 site with a super huge and crazy dictionary section and I kind of got fed up with being 'asked'.

It has a great icon.

undefined

 

(Yes, this package exists, I'm not making it up, this isn't the kind of 'parody' that wearily you've come to expect from me.)

V4/V6

undefined

So originally this was a .net UserControl dashboard that you could add to the content or translation section, to work in tandem with another package 'Dictionary Dashboard' - that would allow editors to edit dictionary terms - back in v4\V6 you couldn't move the dictionary tree out of 'Settings' section and so the 'Dictionary Dashboard' was invaluable - all my package did was to help editors search by key or by value, the Dictionary Dashboard did the hard work. (http://tooorangey.co.uk/posts/yes-i-see-how-it-works-but-what-is-the-dictionary-item-called-that-i-need-to-edit/)

V7

undefined

When we upgraded this site to V7 - the first cry (well second one, after the mourning of CropUp) was "help, where is our Dictionary Key Item Search and tangentially related Dictionary Dashboard?" and as there wasn't a version of the Dictionary Dashboard for V7 - I cobbled together an AngularJS version, which would, yes, do the searching like before but also allow the editing too, so for a brief period of time it became the "coolkids" way of allowing editors to edit dictionary items, without giving them access to the Settings section.(http://tooorangey.co.uk/posts/its-not-that-simple-this-dictionary-never-has-a-word-for-the-way-im-feeling/)

This is the version of the package that we all know and grew to love and has nearly 8690 downloads on Nuget, 443 on Our - hitting the perfect sweet spot of seeming like a good clever idea and perhaps helping somebody with a similar crazy dictionary structure, but without the burden of it becoming a successful Umbraco package, accompanied with all the pressure and maintenance that comes along with such 'package hits' (I imagine).

Anyway, it didn't last long... evil Dan Diplo came along and released the 'Diplo Dictionary Editor For Umbraco' https://www.diplo.co.uk/blog/web-development/diplo-dictionary-editor-for-umbraco/ and stole the coolkids' 'editing dictionary items outside of settings' hearts market from underneath tooorangey.uDictionaryItemSearch's feet, what with his consistent styling and fancy 'Download to CSV file' export option, the game was up.

But wait, in his eagerness to please those coolkids he neglected the whole niche 'searching thing' - I asked him about it, he said:

"Never thought it would be something someone would want to do, to be honest. And I guess it could easily match multiple keys. Seems like a niche requirement :)"

Anyway I'm getting off track, to vent and pursue petty vendettas, and dinosaurs are underrepresented in our community and the tech industry generally, and he is a lovely man.

... in later versions of 7, the Dictionary tree got rewritten anyway and you could relocate the Dictionary tree to another section, and it broke uDictionaryItemSearch (and all our hearts) and it felt like this was the extinction event for the innovative community-driven dictionary dashboard interventions...

... hmm, but 'the search thing' ...

There IS a version of uDictionaryItemSearch for the latest version of 7 (1.0.11), because Gordon Saxby fixed it because he needed the search thing... thanks, Gordon!

V8?

Roll on V8, another large site, plenty of dictionary items, and I'm being asked again... what is the Dictionary key for the Search Button? (well, it's the SearchButtonText key actually etc) and so I think 'if only the world had evolved a uDictionaryItemSearch dashboard for V8'...

... and here's the thing ...

it hasn't, you don't need a dashboard for this kind of interaction now, in later versions of V7 and in V8 we have ISearchableTree.

ISearchableWhat?

It's a way to provide your own custom implementation of the 'backoffice search' for items in a particular 'backoffice tree' - it's documented here: https://our.umbraco.com/documentation/extending/section-trees/Searchable-Trees/

So now uDictionaryItemSearch is 'just' (the magic word) an implementation of ISearchableTree:

  public class DictionarySearchableTree : ISearchableTree
    {
        private IScopeProvider _scopeProvider;
        public DictionarySearchableTree(IScopeProvider scopeProvider)
        {
            _scopeProvider = scopeProvider;
        }
//tree alias this SearchableTree implementation is for public string TreeAlias => Umbraco.Core.Constants.Trees.Dictionary; public IEnumerable Search(string query, int pageSize, long pageIndex, out long totalFound, string searchFrom = null) { totalFound = 0; List searchResults = new List(); if (!string.IsNullOrEmpty(query) && query.Length > 2) { var dictionaryTerms = PerformSearch(query); totalFound = dictionaryTerms.Count(); foreach (var dicTerm in dictionaryTerms) { //is the match on the dictionaryTerm or the value if (dicTerm.Key.StartsWith(query, System.StringComparison.InvariantCultureIgnoreCase)) { searchResults.Add(new SearchResultEntity() { Name = dicTerm.Key, Id = dicTerm.PrimaryKey, Key = dicTerm.UniqueId }); } else { var languageTextMatches = new CommaDelimitedStringCollection(); foreach (var languageText in dicTerm.LanguageTextDtos) { languageTextMatches.Add(languageText.LanguageIsoCode); } searchResults.Add(new SearchResultEntity() { Name = dicTerm.Key + " (" + languageTextMatches.ToString() + ")", Id = dicTerm.PrimaryKey, Key = dicTerm.UniqueId }); } } } return searchResults; } public IEnumerable PerformSearch(string searchTerm) { using (var scope = _scopeProvider.CreateScope(autoComplete: true)) { var sql = "select cd.*, clt.*, ul.LanguageIsoCode from cmsDictionary cd INNER JOIN cmsLanguageText clt on cd.id = clt.UniqueId INNER JOIN umbracoLanguage ul on ul.[id] = clt.languageId WHERE cd.[key] like @0 OR clt.[value] like @1 order by cd.[key]"; return scope.Database.FetchOneToMany(x => x.LanguageTextDtos, sql,searchTerm + "%", "%" + searchTerm + "%"); } } }

(yeah ok, the SQL won't always be blindingly fast on every site, but you get the gist? - the earliest version of uDictionaryKeySearch loaded all the dictionary items into memory to search! - but hopefully it's still a reasonably good example of what's involved in implementing ISearchableTree - git repo is here, github.com/marcemarc/tooorangey.DictionaryItemKeySearch/tree/master/V8/solution)

Searching now looks like this:

undefined

If the search match is in the 'value' rather than the 'key', I show the culture in brackets. 

What is the point I'm trying to make?

[yes we give up, in some ways this blog post is a return to form, and we like it, but you are going to just have to tell us what you mean, stop being so nuanced about everything!]

I've released a new version of my uDictionaryItemSearch for V8?

Yes - but also what slightly overwhelmed me - that got me thinking and writing - was how things have changed and evolved with extending Umbraco for this 'same piece of functionality' over time - like some kind of 'digital evolution'...

(note possible dissertation title "The digital history of dictionary item searching in Umbraco" - actually for a dissertation more like "Planing Conscientious Culture : Digital History Of Dictionary Item Searching In Umbraco and/in the Disenfranchised". there is, as it happens, an academic essay title generator: https://besttitlegenerator.com/index.php have fun!)

... This is of course just one branch of the evolutionary tree, an isolated example - but what I think it kind of shows, is some evidence of 'digital evolution' in progress, over nearly ten years through the Umbraco versions v4->v6->v7->v8, the packages that come and go, ebb and flow in popularity - get superseded or succumbed and requisitioned into the core, the arguments, the misunderstanding... all those tents we have been encouraged to be positive in...

...maybe it shows nostalgia or charts evidence of progress over time, but, it does feel like it's getting better, a little better all the time...

Package Listing: https://our.umbraco.com/packages/backoffice-extensions/udictionaryitemsearch/

also available via Nuget: Install-Package tooorangey.uDictionaryItemSearch


Advice for first-timers not attending a tech conference

Written by @marcemarc on Sunday, 24 May 2020

Can’t attend a tech conference? Considering ‘pretending’ it instead? Is this your first time? Here are some practical things to remember.

This year’s Umbraco tech conference ‘Codegarden’ #cg20 is unfortunately cancelled due to the Covid-19 pandemic.. However quite a few people have expressed a desire to ‘do something’ to ‘virtually’ pretend to be there, and Umbraco HQ have asked yours truly, a hardened veteran of ‘pretending’ conferences to provide some handy tips and advice for the ‘first time’ pretendee.

Motivation

Firstly you have to be clear on your motivation, why would you want to be perceived to have attended the event? I’m often asked why I would tweet during a conference when I’m not actually there, and the counter answer I always give is in the form of a question - why would you tweet at a conference if you WERE there?

You might be providing support via social media noise and buzz for the event
or
Trying to feel part of the shenanigans
or
Showing off to your peer group and work colleagues that you are the type of person who goes to tech conferences...

But all of these aims can easily be achieved by ‘pretending’ the conference, AND you save on travel expenses, plus it’s good for the environment.

Your motivation is important as this shapes the evidence you gather, if your aim is to just make some work colleagues think you went to a thing, that’s a much lower bar to achieve than trying to rewrite history and make people who were actually at the conference think that you were actually there and that they had a conversation with you. My suggestion for first-timers though, is aim low, pretending a conference isn’t something you can just leap into, you can’t pretend you did the keynote, nobody would believe you!

Believability

Which brings us to believability… here on your side is the fact that it is really unlikely that anyone would ever ‘pretend’ a conference, that conferences are busy events with lots of people and lots going on - so people are much more likely to believe you ‘were there’ and they happened to miss seeing you, with only scant attendance evidence, than assume the opposite which would be frankly bizarre (*wink*)... anyway the key thing here is believability - don’t overdo it! - one ridiculous claim can puncture the illusion of your attendance, keep things simple… luckily a lot of tweets from conferences are mind-numbingly banal… so it’s easy to slide a tweet into this humdrum noise to begin establishing 'credibility of presence', without giving things away, particularly early on…
… this applies even if the conference is completely cancelled - and you are group ‘pretending it’ - the pretence won’t be sustained if we all arrive on the back of elephants etc - although if the surrealism scales over the conference days, we can certainly all leave on one...

Early on

The start of the conference is ripe for the early establishment of pretendance… nothing really has happened yet… so it’s hard to be caught out - everyone is excited, all social media output is around ‘seeing people’ or remarking how ‘everybody is lovely’ or ‘the venue is great’... great possibilities to join in BUT WAIT A GOD DAMN MINUTE! - and this is a key first-timer mistake… you haven’t provided any evidence for how you got there!!! You need to get some ‘journey’ evidence in there to really establish credibility… you can start with a picture of a bus or train or anything transport-related in your vicinity… (remember believability - no camels) tweet this out with the conference #hashtag and the golden mantra for any festival/conference attendee/pretendee:

“And so it begins... “

Bang you are in the game!

It’s up to you if you want to provide some evidence of ‘jeopardy’ to the journey - but if you do, remember people will want to see a picture of you on a plane ready for take-off, having conquered that jeopardy… so again, keep it simple.

If travelling to a foreign country, you’ll probably want to remark about something culturally different around the time your virtual plane was due to land… there will be plenty of images on the internet you can pinch about that country or its airport - but if out of inspiration just announcing enigmatically

“Country, I am in you…!”

Will be enough.

Bumping into someone on your journey who is also attending the conference, is a tempting credibility establishing step - but remember those people will immediately know that didn’t happen, and your followers will expect a selfie with those people… however, if you know someone else who is also planning to ‘pretend’ the same conference, this could be a perfect mutual credibility establishing strategy - but do realise if the other pretendee is an idiot they could completely undermine your pretendance, if at a later date they are caught out pretending the wrong lunch menu…

Photographic Evidence

Now the conference has started, there is pressure on any attendee/pretendee to tweet some sort of image from the venue - it establishes that they truly are there (remember we are trying to sync in with what normal ‘attendees’ do!)... this is a key moment… after the conference starts you can always cop out and say it was sooo busy you didn't really have time to take photos and tweet… you’ll have a successful conference pretendance but it will be boring! But, come on, if you WERE ‘there’, and experiencing the initial level of ‘giddy excitement’, you know, you need to get something real ‘out there’ fast.

In normal circumstances, you can ‘surf off’ other attendees photographs… and really you are looking out for anything that features ‘this year’s’ festival logo and colours… you can usually ‘fake’ your own image by then quickly cropping that logo contained in someone else’s image and then ‘remark’ how cool the conference ident is ‘this year’...

Another ‘classic fake’ is to look for people taking a photo and sharing the conference ‘lanyard’ with their name printed on... Again a quick photoshop later (matching font is important) you’ll be sharing a photo of YOUR lanyard, with YOUR name on it… sweet! (in later years reflecting on your timeline with your kids, you won’t remember whether this conference is one you attended or pretended)

Any tweet praising 'the organisation of the first day' has a high chance of being retweeted by conference organising account, just don’t do this if there is general chaos as it will seem really really sarcastic.

Sometimes the organisers will release a teasing shot of the festival ident or t-shirt design months in advance on Twitter, it might be possible to construe your own piece of merchandising based on this sneak preview, for example before Codegarden 17, the whole ‘FRIENDLY’ hoodie was teased in a tweet, and there was enough time to produce the ‘FIENDLY’ pastiche, which was so convincing, people just assumed it was the FRIENDLY one available in the merchandise area in a different colour:

undefined

undefined

 This year at Codegarden 2020, although it’s not happening we know from early teaser tweets that there will be Umbraco socks with the slogan ‘High Five your Socks’... Warren shared an image on twitter...

undefined

So I’d get in quick with any sock references or sock based puns… perhaps referencing the Matt and Lee sock puppets from cg18 etc

If photoshopping isn’t your thing, then as it’s the tech community and nobody really knows what people look like in real life, try commenting on somebody ‘known’ in the tech community’s relative height - but do of course make sure that person is there, and that their relative height is vaguely known by people eg. in the Umbraco community it would be a dead give away if you said

“Wow, just seen Per Ploug… he’s so actually tiny in real life”
Or
“Just accidentally bumped into Shannon, my god, sooo much taller than you would expect”

Mole

The use of a mole to take generic venue photographs can be a real handy boost to the first-time pretendee - but don’t ruin that attendees experience, for your own self-aggrandisement by constantly messaging them to try and get a shot of the merchandise stand, or an empty stage or the inside of a caravan etc etc, having multiple moles is much better, and if people try to ‘call you out’ for pretending - as they are ‘on to you… ‘ then inviting them into the pretence and recruiting them as a mole, is a great way to continue playing the game, without upsetting people.

When the conference isn’t happening moles are of no importance but having similarly pretending co-conspirators can also help boost the quality of the authenticity of your tweets.

Putting yourself in the picture

It might be really tempting to take an image shared on social media from the conference and add yourself into it using Photoshop, but again STOP! - classic rookie mistake!! You only really share pictures on social media from YOUR camera - so think think think - how would you be taking a picture of yourself? It’s subtle, but you’d really only share an image of yourself if you were taking a ‘selfie’ or you asked someone else to take a photo of you with your camera because it made sense…'composition' is important for believability.

For example, in this picture from #cg19 you can see there was a wall of MVPs names and a ‘gold guy’ living statue… it would be ‘weird’ not to have a photo of yourself with the gold guy…

undefined

In this scenario, because it’s totally expected that an MVP would have their photo taken here, and social media will be ‘awash’ with similar photos, the quality of the photoshopping isn’t really questioned, you’d be surprised about how slapdash you can actually be during the daytime… remember people will mainly be following things on tiny mobile screens and be rushing, whereas in the evening, people have more time to look…

... at the end of the ‘same day’ this was taken, I pretended to be on umbraCoffee (a bold move since it is a show recorded on YouTube.. But fortunately most people who would normally watch it were at the conference...), but the unique nature of this image means the photoshoppery needed to be of a higher degree to be convincing: (check out the reversed version of me on the screen above the sofa, respect to Helen's photoshop skills)

undefined

So the tip really is to see what photos other people are sharing and whether that sparks any opportunity for you to do the same… it’s all about telling a shared story.

With a conference not taking place, this is still true, to some degree you’ll have to ‘go with’ other people’s flights of fancy to ‘keep up’.

The final tip on adding yourself to photos, is to ‘be on point with your clothing’… last year's conference t-shirt, you’d think would be a dead giveaway but actually lots of people do wear previous years t-shirts throughout a conference, to show their ‘long term’ investment in the thing… (I liked it before you)... the older the T the better… if it’s a one day conference, try not to be changing outfits in your images that would be weird, similarly for a three-day conference make sure that each day you have clean different clothes on in your images… don’t want to successfully pretend but be considered a ‘bit smelly’ by your audience.

High stakes

Don’t forget to have fun! But remember whilst photoshopping feels the most creative and can establish the greatest amount of attendance credibility in a single tweet - it is by far the riskiest thing you can do for giving the game away… poor photoshopping or just getting something wrong it can quickly make it game over… of course, the high risk brings a lot of the excitement of pretending, but always remember, don’t get carried away - realistical banal photos are dull but they aren’t scrutinised in the same fashion, and they are much more establishing. You are only aiming to pretend the conference, not be the most exciting delegate there/not there. Think photos of ‘the amazing food’ rather than ‘look at me on stage’.

Key Events

Things will happen during the conference, that’s I guess why people go, you’ll need to have the schedule handy and follow closely any social media outpourings from the festival #hashtags or Instagram accounts… to pick up on them… it could be an amazing talk… or an incident involving notorious community members or a shock award announcement. The key thing here is ‘speed of response’ - if you can blend your social media message of ‘YOUR’ thoughts on the thing just as the story is breaking... Then everybody is focusing on the ‘event’ and the unfolding story, and nobody is questioning whether you are actually there or not.

Making up your own key event would be audacious at an existing conference, but I don’t think impossible, (so much happens at a conference that not everybody can really know what is happening everywhere to everyone at any one time... And people can repeat things they see on twitter, even though they are there, it can be an echo chamber - I’d aim for that chaotic bubble of when talks are finishing just before lunch for the best chance). When the conference is cancelled though - you are going to have to invent something… so pick a talk or get creative, plan with co-conspirators - but there is no pointing pretending a cancelled conference if nothing of all of any interest happens, - bearing in mind within the laws of Physics pretty much anything can be allowed to happen… But you know not on Day 1… don’t get cocky!

A quick win at an existing conference is Interacting with somebody on social media who gave a talk, you can perhaps ask them if they are going to share their slides? And they are in such an elated mood from having given their talk that they will definitely reply, which gives great credibility, if you are complimentary about their talk, their ego may even retweet you!

You’ll need to find out if somebody is pretending a talk during the cancelled conference to make this work and be in their mutual interests.

Guilt

A surprising thing that can occur for the first-time pretendee is a feeling of ‘guilt’, you are sort of deceiving all these nice people, and this can be compounded if these people reach out to you on twitter, to express disappointment at not being able to see you, and trying to arrange to meet you… this happens to me quite a lot.. And you can either try and fake it and say, yeah, let's meet up after the ‘next’ xxx talk and then hope the person forgets or you can follow my preference, which is to completely confess to your absence, express your disappointment at not being able to meet them and beg that they help continue the charade… if you're lucky you’ll get a new enthusiastic photo mole!

undefined

At a completely cancelled conference, you can be guilt-free, you know anyone contacting you in this manner, is also playing along too, and you are safe to arrange to ‘meet them’ later in the day.

Wrapping it all up.

Well done! You’ve nearly made it… as the conference draws to a close it’s customary and polite to express in your final set of social media outpourings some sort of wise closing emotional expression on the event.

Do say how sad it is to say goodbye to people,
Mention hugs etc (describing physical interactions gives a real sense you are physically there…)

also don’t forget to pronounce:

“Wow, can’t believe #xxxconf is over - best one ever”

And to thank all the organisers, and wish people ‘safe journeys home’

Another great way to end it, with a guaranteed retweet from the festival organising account is:

“Early bird ticket purchased for next year!!! Can’t wait to do this all over again in 2021”!

WAIT! - But you are not completely done, are you? You thought you’d done it… you’ve still got to get back home and get depressed about being at work, and missing the conference vibe.

So there needs to be a photo of you at home (easier to organise this one), perhaps with a beloved pet, and perhaps with a variation on the message:
“Shattered, happy to be back home, but xxx conference was everything I dreamed of”

Followed up a few days later with

“Anyone else missing being at xxx conference”

Lying

If it’s important to you not to be telling fibs, you can always give no context to your images, it is other people assuming you are there, not you telling them that you went! - and consider wording your tweets ambiguously: “It’s always great to be at xxx conference…” (whether you are there or not) - “I wish I’d seen XX’s talk, why do I always manage to miss the best talks?” (again always true) or “Day 2 has started, feeling overwhelmed, feel like I’m not really taking part” (very honest right?)

The Blog Post

Finally, to totally nail the pretendance you need to conjure that ‘conference attending blog post’ - Now you might be panicking thinking how are you going to put together a detailed blog post of a conference that you didn’t actually attend? You didn’t see those talks? How can you possibly comment???

Well, the good news if you read those ‘xxxx went to xxx conf’ type blog posts, they are all written like a high school book report, we did this, we did that, we saw this talk, then this one, then it ended, it was good. They tend to list talks they attended, but not talk content and repeat 3 key points from the keynote, all in all, it’s very easy to fake… but of course, being a creative pretender you’ll want to establish more credible attendance than the actual attendees!

At least one of the talks of the conference will probably have been done before, at another conference, and filmed… you can watch that and pick up on some nuance, to feature as your favourite bit. Failing that speakers will share their slide decks, just a case of finding something poignant - no point picking the speakers’ slide with their twitter handle and place of work as your highlight of the festival…
the main trick is to take an established key event from the festival and relate to how that ‘made you feel or think’... this way your blog post seems much more real than the ‘attendees’ attempts and it should be the icing on your pretendance experience!

When no conference has taken place you’ve got free reign here to establish a really creative narrative piece… but remember, remember believability! - you didn’t administer CPR during the keynote!

Tech Conference Pretendance Checklist

As this is also a parody of the ‘pre-conference’ blogposts for first-timers, I’ve noticed these always end with some sort of checklist of things for first-timers to help them prepare:

  • Photograph yourself in various standing/sitting positions, smiling - holding a drink and in various outfits.
  • Cut yourself out in photoshop, so you are ready to go with some transparent background pngs of yourself if you need to make some quick images during the festival
  • Look at Flickr feeds of previous conference years, to see what goes on, usually, it’s the same venue etc
  • Find out who is going/not going
  • Wear sunscreen (these sort of blog posts always end with wear sunscreen).

Anyway, I don’t have time to pretend #cg20 this year, so I won’t be taking part myself in the festivities, but I do hope these tips really help you have a fun pretendance this year, and at future tech conferences that you ‘need’ to be seen to have attended.

Do take a moment to add yourself to the #cg20 group picture that Lars and Lotte are organising here: https://github.com/lars-erik/codegarden-2020-group-image and check out Candid Contribution's code patch hackathon and virtual celebration.

And Happy pretending everyone! Until next time…. Keep it real! I mean Keep it unreal!, ok I just don’t know what’s real or unreal anymore...

Inspiration

@marcemarc 'at' #cg19

@marcemarc 'at' Umbraco UK Festival 2018

 


Karma Suit Ya! - Part 1

Written by @marcemarc on Wednesday, 15 January 2020

I’ve always thought it funny that Umbraco put a number on Karma…

the sum of a person's actions in this and previous states of existence viewed as deciding their fate in future existences.

When I started developing with Umbraco I was fascinated and repelled by this idea that all tracked interactions with the Umbraco community would somehow ‘attract a score’ and it seemed to have been a real driver and measure of interactiveness in the history of the community….

A lot of what I say here is ‘before my time’ in the Umbraco community and based on hearsay but:

...references to Karma / Karmageddon / the Karma Wars, all seemed to be part of Umbraco folklore, and I was drawn to the stories like future digital archaeologists will be... but also a little bit scornful ... there was a man, (I heard whispered in awe), called ‘The Karmanator’**… and what an absolute dick he must be I thought… I was repelled and I vowed never to be arsed with Karma nor ever post in the Umbraco Forums… to this day I have never actually posed a question in the Our Umbraco Forum…which is odd, although I have of course often found the answer there…

Your Karma score, for a while, determined whether you would be entered into an ‘end of season’ community vote, to be awarded the status of MVP around the time of Codegarden… which, although the accumulation of Karma was anonymous, this kind of final ballot meant ‘nice and popular’ people won the MVP status ahead of the particular score anyways… but this was ok, as they were nice and popular people and ‘being nominated’ was a thing in itself to be cherished.

… so it wasn’t meaningless... gaining ‘karma points’ wasn’t just throwing shapes at the Universe for the joy of it - there was an identifiable reward for the actions… and so this encouraged:

Gamification!

 Essentially people trying to get as much Karma as possible for the sake of having a higher Karma score than somebody else... and given that ‘any reply’ in the forum gave you a Karma point… in the competitive spirit of Karma hunting… you’d see quite a lot of  “great you got it working”, follow up replies, and well, it would be harsh to say ‘blatant comments’ just for karma sake… but people were rushing to get their answers in… but there was a sense of fun to this competitive edge, and since the people were nice and knowingly almost ironically taking part in the game, was it all bad? All the time? And did this earn the community its coveted friendly reputation in the first place?, ... after all ... few questions went unanswered… and the gamification meant lots of questions were resolved properly because a resolved question delivered 10 karma points!, ...so there was an increased incentive to find an acceptable answer… like a free market economy… but also important to acknowledge the people did genuinely want to help others, and in fact ‘each other’...  it was a smaller community, so you would likely meet the people you’d helped in person. And in true ‘Karma terms' -  people would buy someone a drink, or a gift… or just say thanks in real life.

 … but the competitive nature seemed to get silly, and cross a line and I'm not actually sure what that was but it probably became a little bit unsustainable and so changes were made …

Karma Police

The public league ladder of Karma points disappeared from Our.Umbraco, the MVP nominations were no longer based on karma numbers alone, quality of answers was also considered, although the calculation of this was not necessarily transparent… it took the edge off of the gamification, balance restored to the forum...

...But shsssh secretly karma still seemed an important factor… and some folk would take to the forums a month or so before MVP announcements were due… in the hope of being noticed, and become anointed as an MVP. And anyone who said they didn't is lying.

Umbraco Training

About this time I had begun teaching the popular and comprehensive Umbraco Level 2 official training course (this is a different story of how this came to pass), and I spent a lot of my time talking to and helping developers that were new to the Umbraco community and along with Umbracoman! Doug (L1) introduced the existence of Our Umbraco and some of the stories behind Karma to new Umbracians… encouraging people to go answer questions themselves and build and spread Karma…but also pointing out it’s a really good way to learn Umbraco, as solving ‘real life’ problems is often the point at which we understand something clearly… rather than stepping through idealised situations on a training course (I’d say that at the end of the course obviously...)

 During this time a student asked, “why have you only got 150 Karma on the forum then?”

And I realised I probably ought to practice a little about what I preached and have a Karma score higher than that… and actually even if you weren’t ‘going for it for MVP purposes’ - that your Karma score ‘did’ say something about you…

 But I didn’t want to become an uber-competitive Karma whore -  At the time a score of around 3,000 seemed completely ‘unbelievable’... (Karma like in real life doesn’t reset or rundown over time), I would never catch up, nor would I want to, or more importantly ‘be perceived to be trying to’ and I wouldn’t want to take Karma out of the mouths of those still battling out to somehow win… but I thought if I could get to 1,000 Karma then I wouldn’t seem such a big hypocrite…

 Around this time a new option was added to the forum, the ability to filter by ‘only topics with no replies’

 undefined

 I figured if I concentrated on this list, and looked at questions that hadn’t been answered in over a week, I wasn’t going to tread on anyone's toes, and well imposter wise, if my answers weren’t very helpful… people would less likely be annoyed…

There are currently 13700 unanswered questions on the forum (that doesn’t seem very friendly!) but the number of unanswered questions also probably made it ok for me to answer some.

This was around the end of the summer 2015, and my first few replies didn’t solve the problems or if they did the person didn’t reply, but then suddenly...

Here is my first ever reply with an accepted answer:

https://our.umbraco.com/forum/umbraco-7/using-umbraco-7/71096-changing-valuetype-in-custom-propertyeditor-not-working

 undefined

And Cesar’s reply:

 undefined

Yey, I’d helped someone, and it felt good!

An hour on Our

I decided to dedicate an hour on ‘our’ a week (snappy slogan right?) and because I was trying to justify to myself that I wasn’t buying into the whole karminator thing I invented lots of rules to follow to keep myself ‘real’… I’d..

never answer a question I didn’t already know the answer to,

never follow up with a ‘great you got it working’ message,

and certainly under no circumstances ‘would you like to mark my answer as the answer, because it will help others, but I want 10 karma points!!!’ kinda messages…

Owzat!

I pondered a lot about gamification and how bad it could be, but also saw people answering questions too and helping people, and my increase in score made me happy - and I thought what if you could actually make the forum into a game? One that was ‘against’ yourself rather than a leaderboard against others… when I was a kid  I was obsessed with the ‘dice cylinder’ version of Cricket called ‘Owzat!’ and would spend many hours playing Test Matches against myself (and I wasn’t an only child!)

undefined

...there being no real skill to the outcome of those games… struck a chord with me when answering forum questions… as there seemed to be no real correlation between an answer being accepted and ‘turning green’ and boosting your score with a yield of 10 karma points, or just remaining as a ‘might be right, might be wrong’ general 1 karma point reply… in the same way that rolling the cylinder could be a ‘6’ or ‘out’….

During a long hot summer in the midlands, probably in the early eighties following on from the heady delights of the 1981 ashes series, I remember I was playing a game of Owzat against my friend Ian Foster, and in order to win, the game, and go home for my tea it turned out  I needed six ‘sixes’ off of the last over, … now I am no Sir Garfield Sobers… but my first 3 rolls were all sixes… prompting accusations of cheating, and a meltdown in the game… and being told if we couldn’t play nicely we couldn’t play at all… and well I never found out if I would have rolled a further three sixes, ‘mums stopped play’…

And this came into my head when noticing a pattern answering forum posts, (my email has never worked with Our Umbraco, I do not get updates if anyone replies to one of my replies, so I have to search ‘Marc Goodson’ in order to see my latest posts, and see if there is a reply), and in doing so, the pattern I saw in the search results was when questions that were previously were white, got accepted, they turned green, and you could easily see three in a row… which got me thinking… could I get six in a row? And after 35yrs could I still beat Ian Foster?  And well… I don’t know what that says about me but that became ‘my game’… I’d answer six questions each week, with the hope, when searching my name, of turning all six listed posts in a row ‘green’ (so for a time ‘Marc Goodson’ was probably the most searched forum phrase)

So you can see what I’ve done here right? I’ve made ‘forum answering’ into a fun non-competitive version of Cricket... Or have I?

 I can stop at anytime

This has the markings of obsessive behaviour doesn’t it?, well we are developers… and for most of the year, I passed the time innocently playing this game, when I was on a train, or in hotel rooms, whilst away from home to deliver a training course... I’d fit in another 'karma kricket' over…

This trivial pursuit was working! In so many ways, I celebrated a century, waving my mouse in the air.. And my Karma score soon passed ‘Brian Lara’ proportions 500, what a knock this was and nudged up towards a credible 750...but I hit a snag, at best I was getting 2 maybe 3 accepted answers in a row - like doing the lottery the odds are a lot longer than you’d hope - I was carefully picking six from long list of previously unanswered questions but I wasn’t always finding six I knew the answer to (remember the arbitrary rules), and I needed six in order to try and get six in a row, otherwise what was the point?

So I started breaking my rules.

I ventured into answering questions I wasn’t quite sure of the answer…

... but I was so frightened about giving the wrong answer in public, that I would completely verify the answer first, by recreating the questioners’ problem in code, building the event system they were talking about, adding the custom menu item etc etc - I’d always have a version of Umbraco v-latest on my machine, ready to spin up and double double check my hunch of an answer.

These answers took ages to put together but had a correspondingly high acceptance rate due to the appreciation of the effort.

…but this triggered a further escalation…

I started answering questions that I had no idea of the answer nor really knew anything about..., sometimes I’d just replicate the issue, not find a solution, and not reply at all… or I'd dive into the Umbraco source and work it out - but the upshot of this was I was forcing myself into learning an awful lot about Umbraco, and because my learning was focussed on newish forum questions, and real-world problems - well just by reading those questions, I was finding out about bugs and problems with new releases, in real-time - which meant in my job at a popular Umbraco Gold Partner, I knew about issues well before our clients development teams raised them… like some sort of AI driven learning program… I gained insights into what people actually struggled with when developing with Umbraco and I fed these back into the training materials… and ideas for packages and plugins to solve these real-world pain points…

 Enough Karma already

.. but then I noticed something… I’d pushed past 1,000 Karma now, breezed past, without noticing, objective achieved… but I carried on… telling myself it would be worth seeing if I could just get that six in a row , win the Test Match… defeat Ian Foster,  then I could stop… but I knew the odds of that were huge.

It had never been about a high score, and other people had many thousands of Karma points, but an odd thought struck me, in Cricket you score a 100 runs... it’s a century, you raise your bat to acknowledge the crowd... A milestone has been passed in the match but what really really matters in a cricket career is your ‘average’ number of runs per innings...

… so I started calculating my Karma average, essentially I was playing a game of Cricket against myself.. Therefore the average number of Karma points per reply… was a way I could measure whether my Umbraco game was improving… if my average went up from one month to the next, then I could suppose on average - I was supplying better answers… 

and also my earlier rule of 'not answering a question if I didn’t really know the answer' meant that actually ‘my average’, wasn’t too shoddy either, around 4.1… when actually between 2 and 3 was a typical score (yes I calculated lots of peoples averages) … but again for some mysterious arbitrary reason, I felt a ‘really’ good average you could be proud of, drop casually into conversations... would be around 6… this felt much more achievable than getting 6 in a row…

Ironically from a leaderboard perspective, this seems like a really good way to nullify accusations of gamification, because you can’t add hundreds of gamified  ‘friendly’ replies to gain an extra point of karma... it would destroy your overall average…

MVP

My average began to creep up, I was awarded an MVP for ‘work in the forum’, it was the first year ‘without a public vote’, and where it wasn’t directly attributable to the total Karma score in the year… so as a number of people said at the time, “they’ve just given it to people they like”... it was nice to be liked - it wasn’t the aim to become an MVP, the aim was to sound legit when talking about the forum in the training… and of course to get six in a row or a Karma average of 6 points per reply...

… so great to pick up a trophy... but the important thing, my average was hovering at only 5.21 …

And I carried on...

… why couldn’t I stop?

… why didn’t people always mark answers as correct, when they were correct?

… I got 5 in a row on two occasions, including one run where it would have been six if the person hadn’t accepted their reply to say thanks instead of my reply with the correct answer

… why is it even possible to accept your own an swer as the answer :-)?

… why couldn’t I stop?

I’d created this arbitrary target to aim for, but why?, I remember having a conversation with Tim (@munkimagik) about addiction and negative reinforcement and read a bit about addiction on line.

If you think about it, the act of answering a question, and hoping that it helps… is a bit like putting a coin in a Fruit Machine… you have no control over the outcome… will it stay white or turn green? Who knows… woot, it’s turned green! That response felt good, you solved the problem for someone and it produces a little bit of dopamine reward in the brain… and you are one step closer to the unlikely jackpot of six in a row, if I keep answering questions… it will pay out…  and oh god I realised I’m not playing Our Umbraco Owzat Cricket… I’m actually playing Our Umbraco Fruit Machine… and it’s bloody addictive!

Don't stop me now

So I stopped…my average was 6.02, I bloody should have had six in a row… I had nobody I could really celebrate this with… though I did tell Kevin Jump (who’s average was 4, but has now shot up to 6.4 over the last two years… almost like he’d really like to have a higher average than me, although I’d argue that it’s cheating to build popular packages that everybody uses, and then willfully name the config settings slightly oddly, just to try and generate low hanging forum fruit, that only you can answer - just to boost your Karma average… anyway as you can see from the above it's much more a battle with yourself!)

I stopped for a year

I still won MVP status, although this time for ‘Core contributions’…

 ...There is a part 2 to this… but I am running out of train journey...I have been writing this post on and off for the last three or four months... it was nearly the basis of a talk... but since Kevin Jump has posted his average online today on Twitter, and revealed there ‘is a game’ - I thought I’d publish what I have so far to at least explain what it is we are going on about… a ‘Karma average' origin story if you like.

But do let me know if you'd like me to continue 'next time'...Will Ian Foster be defeated? will there be a point to this? is Karma dead? will I make a song AND dance about it...

** turns out the karmanator is a lovely man, how wrong an impression you can possibly get out of context!


Go Figure 8

Written by @marcemarc on Sunday, 12 May 2019

"If you can grab a circle in your hands and twist it, that's an eight..."

... Well it feels a lot like that's what has happened to Umbraco 7.. twisted into an 8!... everything is familiar, but whereas before you knew you would be always going 'left' or always going 'right'... now you've got going 'left' for a bit, followed by a 'straight on', and whoa, now we're going 'right'... 'straight on' again (aaaaag what's happening!) ... ahh ok back to going 'left' again. If you are old enough to have played Scalextric** in your youth then a figure 8 track was much much more fun than an oval, but well, your car would fall off the track more often...as you tended to misjudge the bends...

sorry, what we talking about?

I'm not sure it can be described as a surprise, but the 'ready when it's ready' new major version of Umbraco: v8; has been released, after, is it 3 years? and seemingly...caught everyone by surprise... well maybe not surprise exactly but maybe off-guard. I've heard a lot of people not using V8 and speculating that it 'isn't ready'... 'there is no documentation', 'nucache isn't stable', 'I don't need variants, - that's so niche', 'I thought there was going to be a phase of community engagement', 'I thought there was going to be a database migration script', 'I've just got a bad feeling about this', 'let's wait until it's proven more stable'...

... I sort of think these statements, whilst some possibly true, share the same undertow of fear, fear of change, and stems perhaps (although I'm not qualified to say) from a feeling, which I'll openly admit I kind of subscribe to, that personally, I was not really ready for this - despite the huge run-up. The narrative is convenient therefore if V8 isn't ready then I don't have to admit that I'm not ready! - that doesn't also mean I think V8 is ready... and also ready for what? context is everything.

... the truth is we're now in a period of transition ...

The same has happened before with Umbraco V6 -> v7, there isn't going to be a definitive 'switch over' point (How about Oct 10th everyone?)... it's a transition... more people use V8, they find problems, HQ fixes them, they share their knowledge, packages emerge, more people use V8, more problems are found, HQ fixes them, etc etc... which is actually exactly what's been happening with V7 over the last five years... but you wouldn't start a new site on V6 now because of it.

So everyone just use V8 right? trust in HQ, is it that simple?

Well ok, but what do you advise a client?

"We're going to start building a new Umbraco site this week, you are the experts, should we use V8?"

If you are building a site yourself then you can afford to trust, and take any risks of any unforeseen setbacks, because, you build Umbraco sites, so the sooner we are all out of this transition period the better, and you understand the quickest way for that to happen is for more people to build with V8, but that doesn't necessarily serve the interest of the client.

All you can responsibly do is be honest...

That a project built on V7 leverages your knowledge for the last few years + a raft of community plugins and packages that solve common problems, but a V8 project has unknown risks, we hope there are none, but nobody knows 'for sure' only time will tell, but if you start on V8 you will save a migration later.

The biggest risk is probably NuCache in terms of impact and size of change... all you can point to here is the 'NuCache "Panic"' issue on github, which illustrates the type of unknown, and the speed at which Umbraco are moving to fix such issues. You can keep an eye on the issue tracker for all open issues with NuCache in the title.

The next risk, is probably death by hundreds of small issues, lots of small things that aren't quite right, that are fixed in the next release, but over the length of a project, block when you least expect it...I've done this before, it adds weeks to a development schedule and finally there is just the plain annoyance of there being a package in V7 that would just 'do this' but it's not available now in V8.

Every client, I've spoken to about this has opted for or steered towards the V8 option, some have wanted to know 'when' all the packages will be moved across (Oct 10th right?) and one was a bit annoyed, that 'maybe never' was an answer... (uCssClassNameDropdown is first in the queue ok!) but on the whole clients see the value of being on the latest major version, but perhaps don't appreciate the richness of all that is available in V7, nor the scale of the change in v8.

Working with V8

Anyway, this strange set of circumstances found me last week in a position of working with V8 for the first time on a real project - creating a wireframe of a site structure. initial doc type design, virtual content, custom IContentFinder, UrlProvider as a jumping off point for an in-house development team to run with along with some team training of how to work with Umbraco - the theme for the first iteration - 'is V8 up to the job?'. The 'working out how the site should be structured work' is easily portable back to V7, but by starting out on V8, it gives the best opportunity to assess what problems there may turn out to be or what short term compromises need to be made...

The site is not small, they will have around 8,000+ content managed Umbraco pages and experience around 70,000 page views per hour, so importing this amount of content into a V8 build and simulating a lot of traffic is part of the process to alleviate any NuCache concerns... (the workaround is presumably to tap into events and store everything in one big Xml file in memory.... :-P)

I'm sure you are much more interested in the results of this test than what I'm about to go on to talk about, but that's for another day...

First impressions

The main thing I wanted to share was a list of some random first impressions of working with V8, in quite an adhoc manner, just to get them out of my head and because once you've used a system for a while you tend not to notice stuff like this.

Documenting V8

I'd have been screwed on this project if I hadn't spent the last couple of months trying to understand and document changes in V8 - I started out just trying to answer questions in the forum (people using Umbraco for the first time, think V8, is Umbraco, they don't understand why documentation isn't 'just there' or why nobody seems to know the answers to their getting started questions - but like in the old days, you can, of course, work things out from the source!). Then based on my replies I decided to update any samples in the docs that included ApplicationEventHandler (replacing with Composition/Composing examples...) - it's taken me ages, and I'm not finished, as each update reveals something else that has subtly twisted... needs, working out, testing and explaining - but in doing this, I've learned a tremendous amount, and have been able to quickly action and wire things up in this last week, injecting all the things, composing all the things! You can see the status of the V8 docs here: https://our.umbraco.com/documentation/v8documentation and create issues here

UI

Working with the Umbraco Backoffice, designing document types, and moving things around has been great with infinite editing, it seems a notch faster than working with V7, you really feel the UI improvements.

Editing content - the 'publish' action has disappeared from the content tree, meaning you have to click on a node, find it's green publish button, and choose from the white arrow menu 'publish with descendants' to publish a section - maybe that is V7 learned behaviour, but it's absence annoyed me a lot! - along with PR of the year functionality: Change Document Type as here, I've designed categories:, different category type, different document type, different icon - I expected editors would be able to change these... but without 'Change Document Type' - I'll need to either create a custom thing here, or keep them all the same Document Type with a dropdown property to indicate type, which might turn out to be better... it's just the thing I knew wasn't there anymore.

Content Apps - so if you switch to the 'info' content app, and are looking at the published Url / History etc and want to switch back to the Content to edit further - bizarrely your eyes can't find it! - you look first to the left of the Url Name (like you are seeking to 'go back home') and the actual 'Content' content app icon, is not necessarily in predictable place on the screen, unless you are hovering over the info tab... then it's easy to switch back and forth... but I found myself clicking the item in the tree to load the Content view time and time again... weird ... I guess this will become leaned... I think from a UI perspective the content app switching is 'behaving like tabs', and with the tabs metaphor, you always have the first tab on the left... and the 'Name' field is there instead!

Tabs

There was a bit of a hoo-har over the dropping of tabs in V8 for document type design - in V7 I had been having, on average, about 5 tabs on a content item, but no more - as they'd start to wrap... moving towards an Atomic Design approach and using compositions/molecules to only apply the groups of properties a page might need (rather than inheriting everything) the average for me has come down to around 3... so I wasn't too worried about the change in paradigm for V8, I could see it would open up possibilities for preview etc, and maybe the tabs metaphor wasn't perfect anyway, maybe a 'new way' might emerge after this reset..  what I've discovered this week, is I can have more than 5 property groupings!.... with one long list it's totally ok to have as many groupings as make sense, they no longer need to be represented on a 'tab' and so there is no artificial horizontal limit! - you can use longer text for the grouping names too, and group properties together by how the Editor relates to them rather than putting them in 'similar' places to just avoid the problem of 'too many tabs...' - I'm not saying 'therefore no-tabs is good', I'm just saying it's an outcome I hadn't considered in the weighing up of their disappearance.

I still have a feeling there is a need to somehow interact differently within the UI for properties that do not have a visual page outcome as opposed to those that control metadata/routing - we used tabs for that purpose in V7, and now, in my new wireframed-out set of Doc Types I've grouped them at the bottom of the content item. It feels like it would be lovely to indicate with colour and/or icon each property grouping in the list, to make them stand out more when the editor scrolls up and down, and then you'd have the flexibility to test the theory and indicate meta property groupings slightly differently to content ones (welcome to the grey zone...)

Implementation

I can't stop myself typing Model.Content.GetPropertyValue - but that is more ingrained in me and my touch-typing fingers, I will get used to Model.Value I will... the new syntax for reading properties, @Model.Value("title", fallback: Fallback.ToDefaultValue, defaultValue: Model.Name) and <h1>@Model.Value("siteName", fallback:Fallback.ToAncestors)</h1> takes a bit of getting used to, but is much better than the stupefying range of options in Umbraco.Field, it's just working out how to do, via intellisense, what you used to know how to do - without thinking.

Configuration

I can't see the configuration!, I can't look in a config folder and see a .config file and know what's configured! I can configure things in code, that is fine, but I can't then see what's configured on a site that is running... ? Again I think this is just a learned 'first place to look' when troubleshooting, someone has moved my cheese type of problem, but it threw me trying to work out where the Examine indexes were configured to be located on the server. Deploying code to change configuration is a pain (fine if you know what you are doing I guess... :-)) 

Problems

Publishing super large amounts of content (5000) or copying a section of the tree, locked the NuCache.db (we're running 8.02 with the cache fixes in), and this stopped content trees from loading in the Backoffice - this is almost certainly because the SQL server was maxed out, I know effectively it's a DOS against the SQL db!, and more digging to be done here to try and report the issue coherently on the tracker, but in V7, if the db was maxed out, there wasn't quite such a catastrophic effect on the site... anyway in this project people won't be publishing that amount of content on a regular basis... and getting the Publication Queue in place for V8 would be worthwhile if they did.

Another issue during the import using the ContentService, calling Save and Publish on the imported item would intermittently fail - the item under which that was being published, had somehow reverted back to being unpublished in NuCache (although published in the db) - each time rebuilding the NuCache from the Backoffice enabled the import to run again for a bit - the import is just a one-off though, and we were using Chauffeur, so plenty could be rogue here in this instance.

With a ton of content imported, changing the name of the homepage and re-publishing - can time out, it's changed in the backoffice but the change is not Publlished - my guess is the name change effects all the Urls of the site, looking at the logs, it's a SQL execution timeout, so maybe we don't have something setup correctly (S2 in Sql Azure).

I did appreciate the irony of not always being able to view the logs and being told in the error message to see the log for full details!

undefined

It's strangely not clear in the Backoffice if an item is unpublished, we unpublished sections, and found underneath the items, the pages were still 'published' in the db, and were not greyed out in the tree - clicking on the item reported the item was published, but not visible due to a parent node being unpublished. weird.

Conclusion

I'm not sure I can answer the question "Will some of my content ever disappear from the site?" yet... but I do quite like the improvements in V8 and would really like to be using it here and moving forward, it's a great starting point for 'future Umbraco' - but I can't let that cloud judgement for someone else's business - really the conclusion is I'd really really like us to get out of this weird transition phase as soon as possible!

It's going to take more than HQ to do this, I don't think I'm being naive in saying this, and the recent increase in slickness and professionalism in the Umbraco outfit, might have led you to expect some different outcome but ultimately it needs people with an invested interest in Umbraco continuing to be a good platform, to engage with V8 and feedback... (I declare this the 'Community Engagement Phase') - the more people, the shorter this phase will be - and it's kinda in all our interests for this period to be as short as possible - and I don't necessarily mean blindly building with V8 on every new client project and just hoping that it'll be fine, but instead chip away at the knowledge gap, have a look at the forum - see if you can work out an answer to someone based on your V7 expertise, look at the source, get a version of v8 running locally or in the cloud for your experiments - maybe take a page of the documentation, is it valid for V8? read the issues on GitHub - read core team blog posts and slides, take the official training - is that in the docs? can I add it in? blog your experiences - tiny tiny little things, but I promise they'll make you a better developer too - if really really lots of people do so then we'll shorten this weird intermission period we find ourselves treading water in.

"that's the way you skate...when you figure eight"

Scalextric tip: replace the brushes under the car with some pure copper mesh for an older-brother-beating acceleration boost..


Any plans to update for V8 yet?

Written by @marcemarc on Friday, 12 April 2019

With Umbraco v8 fresh out of the release traps like a hungry greyhound, never can it be said that I don’t surf the bleeding edge of new things in Umbraco… as in the last few weeks, I’ve released not one, but two Umbraco Healthchecks for ummm V7, totally taking advantage of the whole V8 release thing to bury the news, …,, (sorry ok!,  I have a bit of a backlog and I’m working through it in order… clearly, I’m only about two years behind the curve…. but hey who can hardly wait for the content apps I must be gestating ready for release in 2021?)

Anyways Healthchecks…  been around for a bit ain’t they?, and although they’ve become the ‘must run’ thing for a new launch, probably because their ‘origin story’ stems back to the old ‘go live checks’ dashboard - I find there are lots of checks for specific configuration - but not so many checking the ongoing health of an Umbraco site - or if there are (I can’t find them!)...

… Paul Seal is curating a collection of community checks here https://our.umbraco.com/packages/backoffice-extensions/ourumbracohealthchecks/ and I’ve contributed a check to keep track of content versions - which I’ve blogged about here on the Moriyama site.  

undefined

Be nice if there were more checks for stuff that can go wrong over time… but that’s for another post, probably circa 2020…

You said two healthchecks - what’s the other one?

The other healthcheck is a bit of a diagnostic one… and it’s for checking Flexible Load Balancing configuration - I’m sure if you’ve ever read the documentation on Flexible Load Balancing, you’ve immediately, read it again. Slowly, line by line… and said “does that mean that the master election server needs to have an umbracoApplicationUrl… help”... 

https://our.umbraco.com/Documentation/Getting-Started/Setup/Server-Setup/Load-Balancing/flexible 

The irony of the complication of flexible load balancing is that ‘it just works’ - if you don’t put firewalls in the way or have weird Url rewriting rules in place, or multiple domains, staging environments sharing live database, it just works, Umbraco guesses everything, and it works - and out of the box that’s quite a nice achievement. 

Anyway for your weird setup scenarios there are a few advanced techniques, implementing in code IServerRegistrar2…  to enable you to have full control specifying each server’s Role, and even setting the UmbracoApplicationUrl… and I’m not blogging here about how to set this up, it’s in the documentation, (https://our.umbraco.com/Documentation/Getting-Started/Setup/Server-Setup/Load-Balancing/flexible-advanced ) you just have to read it twice, the second time a little bit more slowly. 

What I’m blogging about here is when you start down this route, testing whether you’ve got it right...it can be a pain. 

Not least because when you are making changes like this in code, you’ve usually got to push them out to your load balanced servers to test, and hey, you’ve probably only noticed it’s ‘not working’ after the 'go live', so well, you’re probably trying to frantically get this to work in a live environment, because someone in Marketing has published a page, and it was all ok, but an hour later it’s reverted back to the old version, but it’s still ok in Umbraco etc and hand-on-heart, there are sooo many contributing factors, which you don’t quite fully comprehend yet, ...even after a third read through - and you just want this to work, it’s meant to ‘just work’, why won't it 'just work'? - it seems unjust! - you are even trying again things you know you've already tried, in pure hope, that somehow the 'passage of time' will resolve the problem. 

Well, I don’t mind telling you dear reader, I’ve found myself in that frustrating situation on a number of occasions, and I HAVE remembered to recycle the app pool, before you ask...and if you find yourself agreeing, well I don't think you are in the minority…regardless of how many people you might hear saying "yeah you 'just' blah de blah de blah" etc 

On a particular occasion, last year, the situation was compounded by assisting in the troubleshooting of a Flexible Load Balancing scenario on a client’s site, without access to servers or source control, and only able to ask questions of the developer, like a Victorian parlour game and because the answers did not fit with what we were observing and my knowledge of Flexible Load balancing setup, I was not necessarily 100% sure that the answers were, well, correct - What is the UmbracoApplicationUrl set to? Right, but in /config/umbracoSettings/web.routing what is the value of the setting umbracoApplicationUrl=”” … are you there, Moriarty?

 it all should have ‘just worked’ but as we were getting nowhere, and getting frustrated, going through the multiple things over and over, I put together some code to response.write out on each server instance, what Umbraco was using as the umbracoApplicationUrl, and how it had been set - to stop us going through the ritual of asking the same questions again and again, but mainly to prove I was right. 

… but I wasn’t right … 

It wasn’t ‘just working’… but it was all configured correctly! 

Desperately looking through the source code I found this: 

//by default we'll use the db server registrar unless the developer has the legacy
// dist calls enabled, in which case we'll use the config server registrar
if (UmbracoConfig.For.UmbracoSettings().DistributedCall.Enabled)
 {
ServerRegistrarResolver.Current = new ServerRegistrarResolver(new ConfigServerRegistrar());
}
else if ("true".InvariantEquals(ConfigurationManager.AppSettings["umbracoDisableElectionForSingleServer"]))
{
ServerRegistrarResolver.Current = new ServerRegistrarResolver(new SingleServerRegistrar());
}
else
{
ServerRegistrarResolver.Current = new ServerRegistrarResolver(
 new DatabaseServerRegistrar(
new Lazy<IServerRegistrationService>(() => ApplicationContext.Services.ServerRegistrationService),
new DatabaseServerRegistrarOptions()));
}

ooh a hidden feature, I like a hidden feature, they make you seem clever if you know about them - but just what is this mysterious umbracoDisableElectionForSingleServer setting?

Well it’s used on Umbraco Cloud, as you can’t flexible load balance on Umbraco Cloud, there is no need to make an initial database request at startup to see what servers are registered in the flexible load balancing pool, so turning off the election process for Umbraco sites makes a good amount of sense across the entire cloud, saves 1 database call per site, so this setting is present by default on all Cloud sites… but the client is on Azure - the site had been migrated from Umbraco Cloud (in order to take advantage of more flexible scalability of Azure in their niche circumstance) - but the darn setting remained in their solution! 

Removing the secret setting allowed everything to ‘just work’! 

We’ve added details of the setting to the docs - https://our.umbraco.com/Documentation/Reference/Config/webconfig/ 

But it made me think you are not going to search for that if you don’t know it exists, the documentation doesn’t necessarily need to mention it, as it’s not part of setting up flexible load balancing, what we need is some sort of troubleshooting guide / diagnostics for Flexible Load Balancing that can check everything…. So I spent a Saturday morning and put what I had into a healthcheck and made a PR to the core, and it was nearly considered for a sprint! 

undefined

But this was pre-PR team, and so my PR along with others became lost in backlog purgatory - but in a way that is a little like natural selection, only the strongest and fittest PRs survive! 

Anyway over the year I’ve used it a few times to quickly get to the bottom of a flexible load balancing issue or two - so it sort of has it’s uses - and when I came across the old PR a few weeks ago and messaged to close, there was still interest but it turned out nobody really knew if my health check was checking the right things, in the right way, or providing the right information to diagnose problems...  But fortunately, there is one person who does know… Jeavon Leopold to the rescue! 

Jeavon runs the popular official Umbraco Training Course: https://umbraco.com/training/book-courses/load-balancing/ you've probably thought about going on it, you should! 

And whether he believed in the idea, or just wanted to cheer me up, (I'm not quite sure which) he helped run through all the settings and of course knew a few more little things that could also be checked too, and he announced it on twitter too…

undefined

… anyway thanks to Jeavon’s input, this is now a standalone package, and if you are having difficulties troubleshooting the setup of Flexible Load Balancing, or just want to validate your setup - then you can install the package from our.umbraco or Nuget - and get some diagnostic information - do let us know how you get on and if this helps! 

undefined

The Health Check will display the value of the UmbracoApplicationUrl, and importantly how this has been determined by Umbraco. If the UmbracoApplicationUrl has been manually set that it follows the correct pattern and can be 'requested' by the server. It will check and display the values of some key Load Balancing configuration settings, eg Distributed Calls, ElectionDisabledForSingleServer, LocalTempStorage. Finally it will display the Current Server Role, Identity and if DatabaseRegistraar is in use a list of the active servers in the Flexible Load Balancing Pool.

It's in the backlog of things to update for V8... behind uCssClassNameDropdown


Nobody really cares if you don't go to the party

Written by @marcemarc on Sunday, 11 November 2018

I’m never normally one to write up a post-festival blog post covering my experience at an event, and today I make no exception, but as the dust settles on another fabulous Umbraco UK Festival, it’s time to reflect on a great couple of days of a gathering of the Umbraco brethren...

This year the festival was held at The Barbican in London, which is a vast amazing myriad of corridors and stairs which don’t quite connect, part crystal maze, part nineteen-seventies high school… (if you like your architecture it’s well worth a visit) - fortunately, signposts and friendly faces guide you to the Umbraco Zone, congregating in the jungle-esque conservatory.

undefined

Day 1 of the festival is a Hackathon…

Because Umbraco is opensource, well developers around the world contribute, when they can, to fixes and improvements to the codebase, but often there is little chance to discuss or work with others in ‘real life’ - sometimes having a whiteboard, animated hand gestures, and just a combination of brains is the better way to discuss and resolve a problem.

The hackathon, which was amazingly well attended this year, is a great place to work alongside like-minded fellow Umbraco devs, sharing discussions on problems/approaches. There is a purpose, and so somehow it’s easier to talk to people than at the conference, where everyone is ‘just on the way to the next talk’ etc… There are tasks, some easy and not so easy,  that are up-for-grabs, and members of the Umbraco HQ development team are on hand to provide guidance. It can be great to pair up with someone (yes, even someone you don’t know) to try and tackle and work through an issue together. It’s all orchestrated by Anthony Dang’s infamous gorilla agile post-it-note driven backlog.undefined

This year, there were tasks to help out with V8, along with fixes to V7 issues (fixes to V7 are still rolled into the V8 branch, so it’s definitely still worth focussing on fixing things in V7). But it wasn’t just about code! - this year, people also took the time to ‘hack’ the Umbraco Documentation repository, fixing up grammar, removing duplication and providing information on TagQuerying…

During the day, I worked upon an ‘up for grab’ issue in the UmbracoDocs repo about providing a tutorial on ‘how to build a google xml sitemap from scratch’, progress here, it needs some more work to polish it up and add some screenshots which I’ll try to do in the coming weeks.

If Day 2 of the festival is all about announcing what is ‘just about to happen’ in the world of Umbraco, then the hackathon… sort of gives you an insight, beyond that… eg what is in the HQ development pipeline for the next year. I can really recommend the hackathon as an experience, just being there is a great learning experience and no need to feel introverted, about it being called a hackathon, it’s very relaxed, nobody is standing behind your laptop - shouting ‘hack hack hack’.

Day 2 - talks, talks, talks

The festival day proper kicked off with Mr Callum Whyte, he off-of the umbraCoffee program on the youtube, telling us all about the festival, welcoming, and stirring up the excitement for the day ahead. There was a ‘uMatchMaker’ game where every attendee had a card with either young or old pics of Umbraco luminaries on and you were encouraged to find the other attendee who had the card with the matching older or younger photo of the luminary in question, all designed to get people talking… or at least introvertedly mumbling… new and old… breaking the ice!

umarcemarcmatchmaker

The program was split into three ‘tracks’, the Theatre and Main Room, were the home to the longer talks, and the Community Space, amongst the jungle for shorter ‘lightening’ talks and panel discussions.

I didn’t see the start of Jeffrey Shoemaker’s talk on ‘Security - Let’s have some fun with Umbraco’ at Codegarden earlier this year, but he showed some great insights into how to ‘hack’ and in turn how to defend from ‘hacking’ Umbraco installations. Little nuggets you think you have covered by locking down the ‘Umbraco’ folder, but the realisation there are other files that can be requested and downloaded that can identify a site as ‘being Umbraco’, eg /config/grid.editors.config.js…. clever stuff.

I would have liked to have seen Jacquie Steele’s 100 Days of Code lightening talk on at the same time as Jeffrey’s security deep dive, as that seems to have been the most inspiring talk of the day, following her route into becoming a developer, setting goals and actioning a plan, sparked lots of conversations amongst attendees, about learning development and change.

Which leads into Emma Burstow’s talk about ‘Developing Talent’ in the Theatre, Emma is a compelling speaker and insightful thinker, she spoke about how teams can nurture talent, with practical ideas - mentoring, helping Juniors develop (bad pun) dispelling the myth that it’s only natural talent that makes a developer great.

Lunch

A wonderful lunch is always provided, and people spoke about the day so far, the talks are great, but sometimes it’s just being there that matters, listening in to the friendly conversations and general hubbub, you start to feel it is ok to talk to people that you follow on the twitter or Github, you get over the fact that they do seem to exist in real life!

Now I’m not saying it wouldn’t be an Umbraco festival without a talk from Pete Duncanson, he must be ‘one of the best’ around, laid back, funny, but making serious technical points, and not afraid to go against the grain to make a point. After lunch, he was talking about the query language for APIs, known as GraphQL which by golly does seem to be the obvious missing link between ‘Umbraco Headless’, and what frontend development needs for umm, querying data. There is an experimental github project: https://github.com/rasmusjp/umbraco-graphql started by Rasmus John Pedersen, that others in the Umbraco community have been contributing to, all very interesting… also Pete told a good joke about Mix Tapes.

Next up ‘Umbraco - we’re in this together’, Umbraco HQ’s ‘Head of PR (pull requests)’ Sebastiaan Janssen - talked about how in opensource, we’re all in this together and can help each other, and how contributions, don’t just involve providing code changes to Umbraco, even just attending the UK Festival was a way of ‘contributing’! - Bug reports, forum answers, packages, documentation, feature requests etc - all great ways to contribute, he then went through the lifecycle of a PR, and showed the latest status of community PRs, and how the new Community PR teams (although anyone can help!) are involved to help process PRs to the core and to documentation.

Kicking myself for not being around for Emma Garland’s talk on ‘When Umbraco and Mobile App development combined’ I always seem to make the wrong decisions over what to see and miss the really good talks, that everyone else rates.

Finally the keynote...

Niels Hartvig the Chief Unicorn, fresh with Brexit jokes, talking enthusiastically about the state of Umbraco, it’s growth and V8 (it will be ready when it’s ready) - some of the new features of V8, like Content Apps (companion apps to particular content page) and side by side comparison/preview of content, will really make a big difference to editors - more screen space to enter content too. (There was a panel on V8 earlier in the day). Niels reminds us too, that it’s all about humans communicating to humans really, and finishes up, inspiring, and leaving people leaving smiling.

Close, Drinks, Hugs, Trains to catch, the UK Umbraco brethren have quenched their Umbraco thirst for another year, and disperse, mumbling about variants and content apps and possibilities, enthused…

… already looking forward to next year.

Thanks to the @cogworks for all their hard work in putting the UK festival together, you'd be a fool not to attend!


The Lee and Marc Show - Atomic Design in Umbraco

Written by @marcemarc on Friday, 01 June 2018

Soooo, it's that 'can I have the slides for your talk?' season... post codegarden2018, and I'm never sure if outside the context of the presentation, whether the slides from the talks I'm involved in, make any sense. (nor, to be honest, during the talk itself either) - But for 'Lee and Marc' completists - they are here.

undefined

Some explanations may be in order..

The use of sock puppets came from an anxiety dream, I had about giving a talk at Codegarden called:

"Marc e Marc’s Sock Puppet Orchestra Presents: too orangey tales of empathy and engagement with content editors in Umbraco"

heavily influenced I think by watching The Nightmare of Milky Joe.

When out of the blue, Lee and I were asked to do a talk about 'Atomic design in Umbraco', and we weren't really sure why... Why us?, Why Atomic design?, well it then became a bit of a challenge to see whether we could work sock puppets in there somehow...

... and well, I've discovered that Lee is the sort of person that 'goes along with stuff'...

We wrote the show containing the sock puppets, knowing it would only work if they demonstrably looked like Matt and Lee - but with two days to go, we didn't have any... So Helen in the early hours of the morning leading up to the CG Retreat, worked her magic, and glue gunned heavily researched, beard, hair and eye combinations to miraculous effect, the hot glue slightly painful on my hands through the sock material, but I wasn't complaining, we had a show! -  On the last night she insisted on creating the mini marcemarc puppet (even though there was no marcemarc puppet in the show, and well... I still had to pack), but, hey, that is the level of commitment, we are talking about here.

undefined
undefined
undefined

What was it about anyway?

The gist of the talk, well, we wanted people to think about the shift from inherited document types to compositions, and how there was little proactive communication at the time of the introduction of compositions, as to how you might organise them and whether the principles of front-end Atomic Design, could help people make decisions and organise their document types and compositions in the backoffice.

This led to the notion of a Periodic table of Umbraco Property Editors - and the thought that well, we might not have found yet ALL the elemental property editors in the core yet... We should think more atomically and not just use Nested Content for everything.

undefined

Stretching the science analogy further we introduced the notion of an 'Atomic Number' for organising the order of properties from different compositions on the same tab, and highlighted other improvements to the core that could make this atomic composition approach more compelling.

undefined

Finally, asking how often people revisit, listen to editors and refactor backoffice editorial experience?

You can read more about the examples glossed over in the talk here:

Editing Crops in the content section
Media Picker - List View 
Editor Journey Times
Redirect Url Management from a Content Item -  (now an exciting PR in the core)

So remember make your backoffice interactions 'S O C K', Simple, Obvious, Composed and Kick Ass!

And the end was filmed by Jeavon:

Pictures

Also if anyone has any pictures of the puppets on stage, it would be ace to see them!