Nibble

Advanced property editor for Umbraco v7, single file deployment 3

One of the community packages that is in progress of being migrated to v7 is uComponents, as you may know the current v4/v6 version is compiled into a single assembly so it’s easy to deploy and to update (since it’s just a single file).

As a test I wanted to see if that’s also possible with v7 prop editors (so embed the views and controllers in the assembly).

If you have seen some of the v7 prop editor examples out there you know that to define your extra components you’ll need to create a manifest file http://umbraco.github.io/Belle/#/tutorials/manifest (no more need for vs)

You can also define your prop editors in code (all the core ones are defined like that) just take a look at https://github.com/umbraco/Umbraco-CMS/tree/7.0.2/src/Umbraco.Web/PropertyEditors 

So if I take the char limit example http://www.nibble.be/?p=285 the manifest file becomes

 [PropertyEditor("Example", "Example Editor", "/App_Plugins/Example/Resource/editor.html", ValueType = "TEXT")]
    [PropertyEditorAsset(ClientDependencyType.Javascript, "/App_Plugins/Example/Resource/controller.js")]
    public class ExamplePropEditor : PropertyEditor
    {
        protected override PreValueEditor CreatePreValueEditor()
        {
            return new ExamplePreValueEditor();
        }
 
        internal class ExamplePreValueEditor : PreValueEditor
        {
            public ExamplePreValueEditor()
            {
                //create the fields
                Fields.Add(new PreValueField()
                {
                    Description = "Enter the number of chars to limit on",
                    Key = "limit",
                    View = "requiredfield",
                    Name = "Number of chars"
                });
                
            }
        }
    }

 

THe editor and controller is still the same but in vs make sure to set the build action of the js and html file to embedded resource

image

Final bit is getting the controller and view out of the assembly and this is done with a simple controller

   public class EmbeddedController : Controller
    {
        public FileStreamResult Resource(string id)
        {
            var resourceName = Assembly.GetExecutingAssembly().GetManifestResourceNames().ToList().FirstOrDefault(f => f.EndsWith(id));
 
            var a = typeof(EmbeddedController).Assembly;
 
            return new FileStreamResult(a.GetManifestResourceStream(resourceName), GetMIMEType(id));
        }
 
        private string GetMIMEType(string fileId)
        {
            if (fileId.EndsWith(".js"))
            {
                return "text/javascript";
            }
            if (fileId.EndsWith(".html"))
            {
                return "text/html";
            }
            if (fileId.EndsWith(".css"))
            {
                return "text/stylesheet";
            }
            return "text";
        }
       
    }

Of course since it’s a normal mvc controller it isn’t auto routed and I need to setup the routing

    public class RouteConfig
    {
        public static void RegisterRoutes(RouteCollection routes)
        {
 
            routes.MapRoute(
                name: "Example",
                url: "App_Plugins/Example/{action}/{id}",
                defaults: new { controller = "Embedded", action = "Resource", id = UrlParameter.Optional }
            );
        }
    }

 

And make sure that the route get’s registered when the application starts

 public class StartUpHandlers : ApplicationEventHandler
    {
        protected override void ApplicationStarted(UmbracoApplicationBase umbracoApplication, ApplicationContext applicationContext)
        {
            RouteConfig.RegisterRoutes(RouteTable.Routes);
        }
    }

So now we can fetch the embedded resource by requesting

/App_Plugins/Example/Resource/resourcefilename.extension

like

/App_Plugins/Example/Resource/editor.html

And that’s it, build and just deploy the assemby to the umbraco v7 instance

Complete source of this example is available here https://github.com/TimGeyssens/EmbeddedPropEditorExample

Analytics for Umbraco 7 1

Led by Warren Buckley and in collab with Anders Bjerner we released a new package for Umbraco v7 today!

Analytics http://our.umbraco.org//projects/backoffice-extensions/analytics

The package adds a new section to your Umbraco v7 installation which allows you to view your Google Analytics statistical information directly inside Umbraco. So it’s easy for content editors, site owners to view stats without having to move to a google account and the google analytics site.

Of course your site needs to have a google analytics profile and it needs to have the necessary script includes to gather stats. The package will simply interact with the google analytics API to fetch data and display those in the Umbraco backoffice.

Install

Just get it from http://our.umbraco.org//projects/backoffice-extensions/analytics and go to developer/packages/install local package in your Umbraco backoffice

image

Then follow the installation wizard and as a final step you should see this screen

image

Then use the button to move to the new section.

Setup

Make sure to clear your cache if you are getting 404 error messages and then hit f5 (v7 needs some good cache busting)

Next you’ll see the settings screen where you need to authorize against google analytics and select the correct profile( again the package won’t gather stats that is done by google analytics so make sure that is setup for the site first).

image

So hit the Authorise button and you should see a new window popup

image

Login with google and then authorize the application (this will give it access to the stats)

Once that is done you should get a confirm message

image

Closing that will reload the settings screen and allow you to choose an account and profile

So select and then save the settings

image

Usage

Once the profile is selected you can view stats Smile

Dashboard will show some stats sfrom latest 7 days

image

Fur further stats, just select something from the tree, on those detailed stats you can also specify a date range (that will be remembered when moving between stats)

image

So that’s a quick intro, make sure to give it a try http://our.umbraco.org//projects/backoffice-extensions/analytics

Config tree On Umbraco v7 0

Another package ready for umbraco v7 (well actually thanks to the awesome work by Per and Shannon it already worked on v7 it just needed some super small UI updates, updating tree icon and updating save button)

ConfigTreeV7

Also added ctrl-s support for saving the file

http://our.umbraco.org/projects/developer-tools/config-tree

Umbraco BE Festival, 25Th April 2014 0

After the successful BE Festival in 2011, the Belgian Umbraco User Group(buug.be) is throwing another edition.

They have some great speakers lined up including Umbraco founder Niels Hartvig and other speakers from DK,UK,SE,NL,FR and BE.

For full details please go to http://www.buug.be/en/events/umbraco-festival-2014 and get your ticket today!

5536568903_15ce073856_b

There is no spoon 1.0 Release (matrix prop editor for Umbraco v7) 0

I’ve just released a packaged version of the matrix prop editor I created as an example prop editor for Umbraco v7.

The package is available for download on http://our.umbraco.org/projects/backoffice-extensions/there-is-no-spoon (this if for Umbraco v7 only)

The settings looks like

MatrixPropEditorSettings

So you can set

  • initial number of cols and rows
  • let the content editor add/remove rows
  • Show row labels
  • define labels for rows and cols

An example of the editor (with manage rows enabled)

MatrixPropEditor

Advanced property editors for Umbraco v7, dynamic prevalue editors 0

Working with the value from 1 prevalue editor on the other, that’s easily possible with Umbraco v7 Smile

Since you can access the editorState http://umbraco.github.io/Belle/#/api/umbraco.services.editorState

As an example I’ve updated the matrix prop editor http://www.nibble.be/?p=330

What I wanted to do is to make it possible to setup headers for the rows and columns but since the amount of rows and columns isn’t fixed…

So first step is to create a new view and controller for the custom prevalue editor (just use what you know from creating prop editors)

And then use that as a prevalue editor

                {
                    label: "Labels",
                    description: "Enter the labels for the cols/rows",
                    key: "rowheaders",
                    view: "~/App_Plugins/MatrixEditor/matrixlabeleditor.html",
                    
                }

Then in the controller it’s possible to inject the editorState and access the other prevalues

    function ($scope,editorState) {
 
    $scope.current = editorState.current;
    $scope.rows = _.where($scope.current.preValues, {key: "rows"})[0];
    $scope.cols = _.where($scope.current.preValues, {key: "cols"})[0];

(using some underscore the easily fetch the correct prevalue)

So once I have the amount of rows and cols I can dynamic build up my editor

<div ng-controller="Nibble.MatrixLabelEditor" class="matrix-label-editor">
     <div>
            <h6>Column labels</h6>
            <div  ng-repeat="label in model.value.collabels track by $id($index)" class="lbl-cont">
                <input type="text" ng-model="model.value.collabels[$index]"/>
            </div >
     </div>
     <div>
         <h6>Row labels</h6>
         <div ng-repeat="label in model.value.rowlabels track by $id($index)" class="lbl-cont">
            <input type="text" ng-model="model.value.rowlabels[$index]"/>
         </div>
     </div>
 
 
</div>

collabels and rowlabels are both arrays

The end result looks like

image

And then of course the prop editor view needs to be updated to include the headers (only for cols atm)

<div ng-controller="Nibble.MatrixEditor">
     <table>
        <thead>
            <tr>
              <th ng-repeat="head in model.config.rowheaders.collabels">{{head}}</th>
            </tr>
          </thead>
        <tbody>
            <tr ng-repeat="row in model.value">
                <td ng-repeat="col in row  track by $id($index)">
                     <input type="text" ng-model="row[$index]"></td>
            </tr>
        </tbody>
    </table>
</div>

 

For a quick demo check out

As a final touch I’ll need to get rid of refreshing the page but haven’t figured that one out yet

Sourcecode is available on github https://github.com/TimGeyssens/MatrixPropEditor

Advanced property editors for Umbraco v7, prevalue editors 1

As you could see in the 2 prop editors for Umbraco examples it’s super easy to add config options to your v7 prop editors (http://www.nibble.be/?p=330, http://www.nibble.be/?p=285)

As it mentions in the manifest docs http://umbraco.github.io/Belle/#/tutorials/manifest there is a prevalues part where you can setup your config options…

So

prevalues: {
            fields: [
                {
                    label: "Number of chars",
                    description: "Enter the number of chars to limit on",
                    key: "limit",
                    view: "requiredfield",
                    validation: [
                        {
                            type: "Required" 
                        }                        
                    ]
                }
            ]
        }

Results in

Changing the type of prevalue editor

Of course you aren’t limited to a simple text input if you take a look at the available out of the box types (found in \Umbraco\Views\prevalueeditors )

You’ll find

image

So if I want to update my matrix prop editor to have numeric prevalues (since I need to define number or rows and columns)

I just need the name of the view (and don’t need the .html)

That then becomes

            fields: [
                {
                    label: "Number of columns",
                    description: "Enter the number of columns",
                    key: "cols",
                    view: "number",
                    validation: [
                        {
                            type: "Required" 
                        }                        
                    ]
                },
                {
                    label: "Number of rows",
                    description: "Enter the number of rows",
                    key: "rows",
                    view: "number",
                    validation: [
                        {
                            type: "Required" 
                        }                        
                    ]
                },

And results in

image

Using prop editors as prevalue editors

It’s also possible to plug in custom prevalue editors, all  you need to do is point it to a view and you can use a prop editor as a prevalue editor!

So adding this

                {
                    label: "Testing",
                    description: "Test",
                    key: "test",
                    view: "~/App_Plugins/MatrixEditor/matrixeditor.html",
                    validation: [
                        {
                            type: "Required" 
                        }                        
                    ]
                }

Will make it possible to use the matrix prop editor as a prevalue editor on it’s own settings

image

Currently you’ll have to manually check in your controller if the config has values or not since it’s not possible to set default values that get passed to the prevalue editor (but should be possible soon)

Autobots, Roll out! Optimus 1.2.0 Release with Umbraco v7 Compatibility is available 0

Like I mentioned during the Uk fest, adding v7 support to your packages is easy Smile (the hard part was writing this blog post)

So I’m glad to announce a new release of Optimus

If you haven’t seen it in action be sure to check out this 5 minute show and tell

If you don’t have 5 minutes to spare here are some screenshots
OptimusBundlerOptimusBundleEditorOptimusBundleFileEditor

Special thanks to Jeavon Leopold for all the hard work! If you are looking for someone to build your Umbraco site make sure to check http://www.crumpled-dog.com/

Advanced property editors for Umbraco v7, Validation 0

Look at the following example prop editor (it’s basically a port of the sample todo app on the http://angularjs.org/ homepage, a bit simplified to focus on the important bits)

image

So in this case the prop editor contains a form that will add items to a array/list

The controller

angular.module("umbraco").controller("SampleValidationController",
        function ($scope) {
 
         if(!(Object.prototype.toString.call($scope.model.value) === ‘[object Array]’)){
             $scope.model.value = new Array();
         }
 
         $scope.addTodo = function() {
            $scope.model.value.push({text:$scope.todoText, done:false});
            $scope.todoText = ;
          };
 
        });

The View

 <div ng-controller="SampleValidationController">
 
         <ul class="unstyled">
           <li ng-repeat="todo in model.value">
             <input type="checkbox" ng-model="todo.done">
             <span class="done-{{todo.done}}">{{todo.text}}</span>
           </li>
         </ul>
         <form ng-submit="addTodo()">
           <input type="text" ng-model="todoText"  size="30"
                  placeholder="add new todo here">
           <input class="btn-primary" type="submit" value="add">
      </form>
 
 </div>

Of course when people click the add we want to make sure not to add an empty item to the list….

So the easiest would be to add a required attribute to the text input.. that works

image

but doing that will interfere with the page publish

image

And that’s not what we want… so the validation only needs to happen when we hit the add not publish…

So we’ll need to create a variable in our controller that will hold the validation state (initially set this to false and the manually check if we want to proceed and change the value of the validation state…)

angular.module("umbraco").controller("SampleValidationController",
        function ($scope) {
 
        $scope.hasError = false;
 
         if(!(Object.prototype.toString.call($scope.model.value) === ‘[object Array]’)){
             $scope.model.value = new Array();
         }
 
         $scope.addTodo = function() {
            if($scope.todoText)
            {
                $scope.model.value.push({text:$scope.todoText, done:false});
                $scope.todoText = ;
                $scope.hasError = false;
            }
            else
            {
                $scope.hasError = true;
            }
          };
 
        });

 

In our view we can now use a custom directive to show a bit of feedback to the user val-highlight="hasError" (of course passing in the variable name) and getting rid of the required

<input type="text" ng-model="todoText"  size="30"
                  placeholder="add new todo here" val-highlight="hasError">

So now when I try to hit the add without filling in a value I’ll get a red border for a couple of seconds

image

And we don’t interfere with the page publish validation…

Advanced property editor for Umbraco v7, working with custom data 0

These prop editor posts just keep coming Winking smile

Is this one I’ll outline how to fetch some third party data in your prop editor

So first I’ll need to expose some data using an API controller

    [PluginController("Contour")]
    public class FormsApiController : UmbracoAuthorizedJsonController
    {
        public IEnumerable<Models.Form> GetAll()
        {
            var forms = new List<Models.Form>();
            FormStorage s = new FormStorage();
 
            foreach (var form in s.GetAllForms(false))
            {
                if (UI.Security.HasAccessToForm(form.Id))
                {
                    Models.Form f = new Models.Form();
                    f.Id = form.Id;
                    f.Name = form.Name;
                    f.Fields = GetFormFields(form);
                    forms.Add(f);
                }
            }
            s.Dispose();
 
            return forms;
        }
}

Notice that I’m using an UmbracoAuthorizedJsonController to make sure only logged in Umbraco backoffice users have access…

Then I’m simply returning a list of Forms (forms is a custom model that looks like)

 public class Form
    {
        public Guid Id { get; set; }
        public string Name { get; set; }
        public string Fields { get; set; }
    }

So I’m using Contour to fetch all forms (but since those have to much data I’m creating them as my simple form object) and then returning them a a list.

So that’s the api controller done,

Next is the angular controller

angular.module("umbraco").controller("Contour.FormPickerController",
        function ($scope, $http) {
            $scope.loading = true;
            $http({ method: ‘GET’, url: ‘Contour/FormsApi/GetAll’ })
                .success(function (data) {
                    $scope.forms  = data;
                    $scope.loading = false;
                })
                .error(function () {
                    $scope.error = "An Error has occured while loading!";
                    $scope.loading = false;
                });
        });

So it does a get request of Contour/FormsApi/GetAll (that is where we’ll find our api controller method since this is auto routed) and assigns the result to $scope.forms

And the final bit, the view looks like

 <div ng-controller="Contour.FormPickerController">
     
     <div class="radio" ng-repeat="form in forms">
         <label>
             <input ng-model="model.value" value="{{form.Id}}" type="radio" name="form">
             {{form.Name}}
             <small>{{form.Fields}}</small>
         </label>
     </div>
 
 </div>

So it’s just looping the form objects and outputting them as radiobuttons (setting model.value)

End result looks like

FormPicker

You’ll see that in this example the data is fetched async ideally I would also like to set a scope object on load, maybe that’s something for the next post Winking smile

« Previous PageNext Page »