From 7d7ca4530bb565db8b4199b9f8f5027126b122e5 Mon Sep 17 00:00:00 2001 From: Shannon Deminick Date: Mon, 27 May 2013 18:21:07 -1000 Subject: [PATCH] Getting server side integration working from ported over Belle POC including temporary custom property editors. Many files committed will be temporary and will be removed once development between the Belle UI project and this project are merged and working. --- .../MyPackage/Common/Js/MyPackage.js | 54 +++++++++ .../ServerSidePropertyEditorsController.cs | 15 +++ .../App_Plugins/MyPackage/Package.manifest | 50 ++++++++ .../FileUploadPropertyEditor.cs | 23 ++++ .../MyPackage/PropertyEditors/Js/CsvEditor.js | 39 +++++++ .../PropertyEditors/Js/FileUploadEditor.js | 80 +++++++++++++ .../PropertyEditors/Js/PostcodeEditor.js | 11 ++ .../PropertyEditors/Js/RegexEditor.js | 10 ++ .../PropertyEditors/PostcodePropertyEditor.cs | 26 +++++ .../PropertyEditors/PostcodeValidator.cs | 43 +++++++ .../ServerInfoPropertyEditor.cs | 29 +++++ .../PropertyEditors/Views/CsvEditor.html | 16 +++ .../Views/FileUploadEditor.html | 6 + .../PropertyEditors/Views/PostcodeEditor.html | 12 ++ .../PropertyEditors/Views/RegexEditor.html | 15 +++ .../MyPackage/System/MyStartupHandler.cs | 55 +++++++++ .../MyPackage/Trees/LegacyTestTree.cs | 45 +++++++ .../ServerEnvironment.cshtml | 9 ++ .../App_Plugins/MyPackage/Views/Web.config | 58 +++++++++ src/Umbraco.Web.UI/Umbraco.Web.UI.csproj | 23 +++- .../umbraco/Views/Default.cshtml | 3 +- src/Umbraco.Web.UI/umbraco/js/umbraco.app.js | 110 +++++++++--------- .../umbraco/lib/underscore/underscore-min.js | 5 + .../ContentEditing/ContentPropertyDisplay.cs | 5 +- .../ContentEditing/ContentPropertyDto.cs | 19 +-- .../Models/Mapping/ContentModelMapper.cs | 2 +- .../UI/JavaScript/RequireJsConfig.js | 18 +-- 27 files changed, 695 insertions(+), 86 deletions(-) create mode 100644 src/Umbraco.Web.UI/App_Plugins/MyPackage/Common/Js/MyPackage.js create mode 100644 src/Umbraco.Web.UI/App_Plugins/MyPackage/Controllers/ServerSidePropertyEditorsController.cs create mode 100644 src/Umbraco.Web.UI/App_Plugins/MyPackage/Package.manifest create mode 100644 src/Umbraco.Web.UI/App_Plugins/MyPackage/PropertyEditors/FileUploadPropertyEditor.cs create mode 100644 src/Umbraco.Web.UI/App_Plugins/MyPackage/PropertyEditors/Js/CsvEditor.js create mode 100644 src/Umbraco.Web.UI/App_Plugins/MyPackage/PropertyEditors/Js/FileUploadEditor.js create mode 100644 src/Umbraco.Web.UI/App_Plugins/MyPackage/PropertyEditors/Js/PostcodeEditor.js create mode 100644 src/Umbraco.Web.UI/App_Plugins/MyPackage/PropertyEditors/Js/RegexEditor.js create mode 100644 src/Umbraco.Web.UI/App_Plugins/MyPackage/PropertyEditors/PostcodePropertyEditor.cs create mode 100644 src/Umbraco.Web.UI/App_Plugins/MyPackage/PropertyEditors/PostcodeValidator.cs create mode 100644 src/Umbraco.Web.UI/App_Plugins/MyPackage/PropertyEditors/ServerInfoPropertyEditor.cs create mode 100644 src/Umbraco.Web.UI/App_Plugins/MyPackage/PropertyEditors/Views/CsvEditor.html create mode 100644 src/Umbraco.Web.UI/App_Plugins/MyPackage/PropertyEditors/Views/FileUploadEditor.html create mode 100644 src/Umbraco.Web.UI/App_Plugins/MyPackage/PropertyEditors/Views/PostcodeEditor.html create mode 100644 src/Umbraco.Web.UI/App_Plugins/MyPackage/PropertyEditors/Views/RegexEditor.html create mode 100644 src/Umbraco.Web.UI/App_Plugins/MyPackage/System/MyStartupHandler.cs create mode 100644 src/Umbraco.Web.UI/App_Plugins/MyPackage/Trees/LegacyTestTree.cs create mode 100644 src/Umbraco.Web.UI/App_Plugins/MyPackage/Views/ServerSidePropertyEditors/ServerEnvironment.cshtml create mode 100644 src/Umbraco.Web.UI/App_Plugins/MyPackage/Views/Web.config create mode 100644 src/Umbraco.Web.UI/umbraco/lib/underscore/underscore-min.js diff --git a/src/Umbraco.Web.UI/App_Plugins/MyPackage/Common/Js/MyPackage.js b/src/Umbraco.Web.UI/App_Plugins/MyPackage/Common/Js/MyPackage.js new file mode 100644 index 0000000000..287e54b6a3 --- /dev/null +++ b/src/Umbraco.Web.UI/App_Plugins/MyPackage/Common/Js/MyPackage.js @@ -0,0 +1,54 @@ +'use strict'; + +define(['myApp'], function (app) { + + app.directive('valPostcode', function () { + + /// + /// A custom directive to validate for postcodes + /// + + return { + require: 'ngModel', + link: function (scope, elm, attrs, ctrl) { + + if (!attrs.valPostcode) + throw "valPostcode requires an attribute value specifying the country for the postcode"; + + var patternValidator = function (viewValue) { + //NOTE: we don't validate on empty values, use required validator for that + if (viewValue) { + var country = scope.$eval(attrs.valPostcode); + switch (country) { + case "Australia": + if (/^\d{4}$/.test(viewValue)) { + ctrl.$setValidity('valPostcode', true); + //reset the error msg + ctrl.errorMsg = ""; + return viewValue; + } + else { + // it is invalid, return undefined (no model update) + ctrl.$setValidity('valPostcode', false); + //assign an error msg property to the current validator + ctrl.errorMsg = "Australian postcodes must be a 4 digit number"; + return undefined; + } + + default: + throw "The country specified does not have validation logic applied"; + } + } + else { + // there is no value to validate so return that it is valid. + ctrl.$setValidity('valPostcode', true); + return viewValue; + } + }; + + ctrl.$formatters.push(patternValidator); + ctrl.$parsers.push(patternValidator); + } + }; + }); +}); \ No newline at end of file diff --git a/src/Umbraco.Web.UI/App_Plugins/MyPackage/Controllers/ServerSidePropertyEditorsController.cs b/src/Umbraco.Web.UI/App_Plugins/MyPackage/Controllers/ServerSidePropertyEditorsController.cs new file mode 100644 index 0000000000..c6afc1e5b6 --- /dev/null +++ b/src/Umbraco.Web.UI/App_Plugins/MyPackage/Controllers/ServerSidePropertyEditorsController.cs @@ -0,0 +1,15 @@ +using System.Web.Mvc; + +namespace Umbraco.Belle.App_Plugins.MyPackage.Controllers +{ + + public class ServerSidePropertyEditorsController : Controller + { + [HttpGet] + public ActionResult ServerEnvironment() + { + return View(); + } + + } +} diff --git a/src/Umbraco.Web.UI/App_Plugins/MyPackage/Package.manifest b/src/Umbraco.Web.UI/App_Plugins/MyPackage/Package.manifest new file mode 100644 index 0000000000..b6472e3358 --- /dev/null +++ b/src/Umbraco.Web.UI/App_Plugins/MyPackage/Package.manifest @@ -0,0 +1,50 @@ +{ + propertyEditors: [ + { + id: "0BA0F832-D759-4526-9B3E-94BBFC98F92E", + name: "Regex", + editor: { + view: "~/App_Plugins/MyPackage/PropertyEditors/Views/RegexEditor.html", + validation: [ + { + type: "Required" + }, + { + type: "Regex", + config: "\\d*" + } + ] + }, + preValues: { + view: "myPreValues1" + } + }, + { + id: "A24C4A00-29BF-4A57-BDE6-B1E305A96A4C", + name: "CSV Editor", + editor: { + view: "~/App_Plugins/MyPackage/PropertyEditors/Views/CsvEditor.html", + validation: [ + { + type: "Delimited", + config: { + delimiter: ",", + pattern: "^[a-zA-Z]*$" + } + }, + ] + } + } + ], + config: { + paths: { + myPackageCommon: '~/App_Plugins/MyPackage/Common/Js/MyPackage' + }, + shim: { + 'myPackageCommon': { 'exports': 'myPackageCommon' } + } + }, + init: [ + 'myPackageCommon' + ] +} \ No newline at end of file diff --git a/src/Umbraco.Web.UI/App_Plugins/MyPackage/PropertyEditors/FileUploadPropertyEditor.cs b/src/Umbraco.Web.UI/App_Plugins/MyPackage/PropertyEditors/FileUploadPropertyEditor.cs new file mode 100644 index 0000000000..d6ae8c0730 --- /dev/null +++ b/src/Umbraco.Web.UI/App_Plugins/MyPackage/PropertyEditors/FileUploadPropertyEditor.cs @@ -0,0 +1,23 @@ +using System.Collections.Generic; +using Umbraco.Belle.System.PropertyEditors; + +namespace Umbraco.Belle.App_Plugins.MyPackage.PropertyEditors +{ + [PropertyEditor("23A66468-30E2-4537-8039-625F8BC5CA1E", "File upload", + "~/App_Plugins/MyPackage/PropertyEditors/Views/FileUploadEditor.html")] + public class FileUploadPropertyEditor : PropertyEditor + { + /// + /// Creates the value editor with custom validators + /// + /// + protected override ValueEditor CreateValueEditor() + { + var editor = base.CreateValueEditor(); + + editor.Validators = new List { new PostcodeValidator() }; + + return editor; + } + } +} \ No newline at end of file diff --git a/src/Umbraco.Web.UI/App_Plugins/MyPackage/PropertyEditors/Js/CsvEditor.js b/src/Umbraco.Web.UI/App_Plugins/MyPackage/PropertyEditors/Js/CsvEditor.js new file mode 100644 index 0000000000..729709a6d6 --- /dev/null +++ b/src/Umbraco.Web.UI/App_Plugins/MyPackage/PropertyEditors/Js/CsvEditor.js @@ -0,0 +1,39 @@ +'use strict'; + +//requires namespaceMgr +define(['namespaceMgr'], function () { + + Umbraco.Sys.registerNamespace("MyPackage.PropertyEditors"); + + MyPackage.PropertyEditors.CsvEditor = function ($scope, $http, $filter) { + + var values = []; + + //this will be comma delimited + if ($scope.model && $scope.model.value && (typeof $scope.model.value == "string")) { + var splitVals = $scope.model.value.split(","); + //set the values of our object + for (var i = 0; i < splitVals.length; i++) { + values.push({ + index: i, + value: splitVals[i].trim() + }); + } + } + + //set the scope values to bind on our view to the new object + $scope.values = values; + + //set up listeners for the object to write back to our comma delimited property value + $scope.$watch('values', function (newValue, oldValue) { + var csv = []; + for (var v in newValue) { + csv.push(newValue[v].value); + } + //write the csv value back to the property + $scope.model.value = csv.join(); + }, true); + + }; + +}); \ No newline at end of file diff --git a/src/Umbraco.Web.UI/App_Plugins/MyPackage/PropertyEditors/Js/FileUploadEditor.js b/src/Umbraco.Web.UI/App_Plugins/MyPackage/PropertyEditors/Js/FileUploadEditor.js new file mode 100644 index 0000000000..be3f41df08 --- /dev/null +++ b/src/Umbraco.Web.UI/App_Plugins/MyPackage/PropertyEditors/Js/FileUploadEditor.js @@ -0,0 +1,80 @@ +'use strict'; + +//requires namespaceMgr +define(['namespaceMgr'], function () { + + Umbraco.Sys.registerNamespace("MyPackage.PropertyEditors"); + + MyPackage.PropertyEditors.FileUploadEditor = function ($scope) { + $scope.$on("fileSelected", function(event, args) { + $scope.$apply(function() { + //assign the file name to the model property + $scope.model.value = args.file.name; + //save the file object to the scope's files collection + $scope.files.push({ id: $scope.model.id, file: args.file }); + }); + }); + + }; + +}); + +function Ctrl($scope, $http) { + + //a simple model to bind to and send to the server + $scope.model = { + name: "", + comments: "" + }; + + //an array of files selected + $scope.files = []; + + //listen for the file selected event + $scope.$on("fileSelected", function (event, args) { + $scope.$apply(function () { + //add the file object to the scope's files collection + $scope.files.push(args.file); + }); + }); + + //the save method + $scope.save = function() { + $http({ + method: 'POST', + url: "/Api/SaveStuff", + //IMPORTANT!!! You might think this should be set to 'multipart/form-data' + // but this is not true because when we are sending up files the request + // needs to include a 'boundary' parameter which identifies the boundary + // name between parts in this multi-part request and setting the Content-type + // manually will not set this boundary parameter. For whatever reason, + // setting the Content-type to 'false' will force the request to automatically + // populate the headers properly including the boundary parameter. + headers: { 'Content-Type': false }, + //This method will allow us to change how the data is sent up to the server + // for which we'll need to encapsulate the model data in 'FormData' + transformRequest: function (data) { + var formData = new FormData(); + //need to convert our json object to a string version of json otherwise + // the browser will do a 'toString()' on the object which will result + // in the value '[Object object]' on the server. + formData.append("model", angular.toJson(data.model)); + //now add all of the assigned files + for (var i = 0; i < data.files; i++) { + //add each file to the form data and iteratively name them + formData.append("file" + i, data.files[i]); + } + return formData; + }, + //Create an object that contains the model and files which will be transformed + // in the above transformRequest method + data: { model: $scope.model, files: $scope.files } + }). + success(function (data, status, headers, config) { + alert("success!"); + }). + error(function (data, status, headers, config) { + alert("failed!"); + }); + }; +}; \ No newline at end of file diff --git a/src/Umbraco.Web.UI/App_Plugins/MyPackage/PropertyEditors/Js/PostcodeEditor.js b/src/Umbraco.Web.UI/App_Plugins/MyPackage/PropertyEditors/Js/PostcodeEditor.js new file mode 100644 index 0000000000..2099e8875d --- /dev/null +++ b/src/Umbraco.Web.UI/App_Plugins/MyPackage/PropertyEditors/Js/PostcodeEditor.js @@ -0,0 +1,11 @@ +'use strict'; + +define(['myApp'], function (app) { + + Umbraco.Sys.registerNamespace("MyPackage.PropertyEditors"); + + MyPackage.PropertyEditors.PostcodeEditor = function ($scope, $http, $filter) { + //change the config json model into something usable + $scope.model.config = $scope.$eval($scope.model.config); + }; +}); \ No newline at end of file diff --git a/src/Umbraco.Web.UI/App_Plugins/MyPackage/PropertyEditors/Js/RegexEditor.js b/src/Umbraco.Web.UI/App_Plugins/MyPackage/PropertyEditors/Js/RegexEditor.js new file mode 100644 index 0000000000..a7b6716526 --- /dev/null +++ b/src/Umbraco.Web.UI/App_Plugins/MyPackage/PropertyEditors/Js/RegexEditor.js @@ -0,0 +1,10 @@ +'use strict'; + +define(['myApp'], function (app) { + + Umbraco.Sys.registerNamespace("MyPackage.PropertyEditors"); + + MyPackage.PropertyEditors.RegexEditor = function ($scope, $http, $filter) { + var asdf = ""; + }; +}); \ No newline at end of file diff --git a/src/Umbraco.Web.UI/App_Plugins/MyPackage/PropertyEditors/PostcodePropertyEditor.cs b/src/Umbraco.Web.UI/App_Plugins/MyPackage/PropertyEditors/PostcodePropertyEditor.cs new file mode 100644 index 0000000000..548dbcffc7 --- /dev/null +++ b/src/Umbraco.Web.UI/App_Plugins/MyPackage/PropertyEditors/PostcodePropertyEditor.cs @@ -0,0 +1,26 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Web; +using Umbraco.Belle.System.PropertyEditors; + +namespace Umbraco.Belle.App_Plugins.MyPackage.PropertyEditors +{ + [PropertyEditor("E96E24E5-7124-4FA8-A7D7-C3D3695E100D", "Postal Code", + "~/App_Plugins/MyPackage/PropertyEditors/Views/PostcodeEditor.html")] + public class PostcodePropertyEditor : PropertyEditor + { + /// + /// Creates the value editor with custom validators + /// + /// + protected override ValueEditor CreateValueEditor() + { + var editor = base.CreateValueEditor(); + + editor.Validators = new List { new PostcodeValidator() }; + + return editor; + } + } +} \ No newline at end of file diff --git a/src/Umbraco.Web.UI/App_Plugins/MyPackage/PropertyEditors/PostcodeValidator.cs b/src/Umbraco.Web.UI/App_Plugins/MyPackage/PropertyEditors/PostcodeValidator.cs new file mode 100644 index 0000000000..aab3592757 --- /dev/null +++ b/src/Umbraco.Web.UI/App_Plugins/MyPackage/PropertyEditors/PostcodeValidator.cs @@ -0,0 +1,43 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using System.Text.RegularExpressions; +using Newtonsoft.Json.Linq; +using Umbraco.Belle.System.PropertyEditors; +using Umbraco.Core; + +namespace Umbraco.Belle.App_Plugins.MyPackage.PropertyEditors +{ + /// + /// Validates a postcode + /// + internal class PostcodeValidator : ValidatorBase + { + public override IEnumerable Validate(object value, string preValues, PropertyEditor editor) + { + var stringVal = value.ToString(); + + if (preValues.IsNullOrWhiteSpace()) yield break; + var asJson = JObject.Parse(preValues); + if (asJson["country"] == null) yield break; + + if (asJson["country"].ToString() == "Australia") + { + if (!Regex.IsMatch(stringVal, "^\\d{4}$")) + { + yield return new ValidationResult("Australian postcodes must be a 4 digit number", + new[] + { + //we only store a single value for this editor so the 'member' or 'field' + // we'll associate this error with will simply be called 'value' + "value" + }); + } + } + else + { + yield return new ValidationResult("Only Australian postcodes are supported for this validator"); + } + } + } +} \ No newline at end of file diff --git a/src/Umbraco.Web.UI/App_Plugins/MyPackage/PropertyEditors/ServerInfoPropertyEditor.cs b/src/Umbraco.Web.UI/App_Plugins/MyPackage/PropertyEditors/ServerInfoPropertyEditor.cs new file mode 100644 index 0000000000..3b4dd3ed26 --- /dev/null +++ b/src/Umbraco.Web.UI/App_Plugins/MyPackage/PropertyEditors/ServerInfoPropertyEditor.cs @@ -0,0 +1,29 @@ +using System; +using System.Web; +using System.Web.Mvc; +using System.Web.Routing; +using Umbraco.Belle.System.PropertyEditors; + +namespace Umbraco.Belle.App_Plugins.MyPackage.PropertyEditors +{ + [PropertyEditor("AD056473-492B-47F8-9613-5A4936666C67", "Server Info")] + public class ServerInfoPropertyEditor : PropertyEditor + { + protected override ValueEditor CreateValueEditor() + { + if (HttpContext.Current == null) + { + throw new InvalidOperationException("This property editor only works in a web context"); + } + + var urlHelper = new UrlHelper(new RequestContext(new HttpContextWrapper(HttpContext.Current), new RouteData())); + + return new ValueEditor(urlHelper.Action("ServerEnvironment", "ServerSidePropertyEditors", new {area = "MyPackage"})); + } + + protected override PreValueEditor CreatePreValueEditor() + { + return new PreValueEditor(); + } + } +} \ No newline at end of file diff --git a/src/Umbraco.Web.UI/App_Plugins/MyPackage/PropertyEditors/Views/CsvEditor.html b/src/Umbraco.Web.UI/App_Plugins/MyPackage/PropertyEditors/Views/CsvEditor.html new file mode 100644 index 0000000000..26cc63e9fa --- /dev/null +++ b/src/Umbraco.Web.UI/App_Plugins/MyPackage/PropertyEditors/Views/CsvEditor.html @@ -0,0 +1,16 @@ +
+ +
+ + + + {{multiFormVal.myPackage_multiVal.errorMsg}} + +
+
+
+ + {{model.value}} +
\ No newline at end of file diff --git a/src/Umbraco.Web.UI/App_Plugins/MyPackage/PropertyEditors/Views/FileUploadEditor.html b/src/Umbraco.Web.UI/App_Plugins/MyPackage/PropertyEditors/Views/FileUploadEditor.html new file mode 100644 index 0000000000..e4cdd234d4 --- /dev/null +++ b/src/Umbraco.Web.UI/App_Plugins/MyPackage/PropertyEditors/Views/FileUploadEditor.html @@ -0,0 +1,6 @@ +
+ +
    +
  • {{file.file.name}}
  • +
+
\ No newline at end of file diff --git a/src/Umbraco.Web.UI/App_Plugins/MyPackage/PropertyEditors/Views/PostcodeEditor.html b/src/Umbraco.Web.UI/App_Plugins/MyPackage/PropertyEditors/Views/PostcodeEditor.html new file mode 100644 index 0000000000..9a5a5f05b8 --- /dev/null +++ b/src/Umbraco.Web.UI/App_Plugins/MyPackage/PropertyEditors/Views/PostcodeEditor.html @@ -0,0 +1,12 @@ +
+

+ Enter a postcode for country {{model.config.country}} +

+ + + {{propertyForm.myPackage_postcode.errorMsg}} + {{propertyForm.myPackage_postcode.errorMsg}} +
\ No newline at end of file diff --git a/src/Umbraco.Web.UI/App_Plugins/MyPackage/PropertyEditors/Views/RegexEditor.html b/src/Umbraco.Web.UI/App_Plugins/MyPackage/PropertyEditors/Views/RegexEditor.html new file mode 100644 index 0000000000..ccbeebfb34 --- /dev/null +++ b/src/Umbraco.Web.UI/App_Plugins/MyPackage/PropertyEditors/Views/RegexEditor.html @@ -0,0 +1,15 @@ +
+

+ Value in the format of {{model.config}} +

+ + + + Required! + {{propertyForm.regex.errorMsg}} +
\ No newline at end of file diff --git a/src/Umbraco.Web.UI/App_Plugins/MyPackage/System/MyStartupHandler.cs b/src/Umbraco.Web.UI/App_Plugins/MyPackage/System/MyStartupHandler.cs new file mode 100644 index 0000000000..ef6b7f159f --- /dev/null +++ b/src/Umbraco.Web.UI/App_Plugins/MyPackage/System/MyStartupHandler.cs @@ -0,0 +1,55 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Web; +using System.Web.Mvc; +using System.Web.Routing; +using Umbraco.Belle.System; +using Umbraco.Core; +using umbraco.businesslogic; + +namespace Umbraco.Belle.App_Plugins.MyPackage.System +{ + public class MyStartupHandler : ApplicationEventHandler + { + + //TODO: We will remove these when we move to Umbraco core. + protected override bool ExecuteWhenApplicationNotConfigured + { + get { return true; } + } + protected override bool ExecuteWhenDatabaseNotConfigured + { + get { return true; } + } + + protected override void ApplicationStarted(UmbracoApplicationBase umbracoApplication, ApplicationContext applicationContext) + { + base.ApplicationStarted(umbracoApplication, applicationContext); + + //create a custom server variable to be exposed in JS + ServerVariablesParser.Parsing += (sender, dictionary) => + { + + var httpContext = HttpContext.Current; + if (httpContext == null) return; + + var urlHelper = new UrlHelper(new RequestContext(new HttpContextWrapper(httpContext), new RouteData())); + + dictionary.Add("MyPackage", new Dictionary() + { + {"serverEnvironmentView", urlHelper.Action("ServerEnvironment", "ServerSidePropertyEditors", new {area = "MyPackage"})} + }); + }; + + //For testing for now we'll route to /Belle/Main + var route = RouteTable.Routes.MapRoute( + "umbraco-server-side-property-editors", + "Belle/PropertyEditors/{controller}/{action}/{id}", + new { controller = "ServerSidePropertyEditors", action = "Index", id = UrlParameter.Optional }); + //assign it to an area so that the plugin view engine looks for us + route.DataTokens.Add("area", "MyPackage"); + } + + } +} \ No newline at end of file diff --git a/src/Umbraco.Web.UI/App_Plugins/MyPackage/Trees/LegacyTestTree.cs b/src/Umbraco.Web.UI/App_Plugins/MyPackage/Trees/LegacyTestTree.cs new file mode 100644 index 0000000000..e5d013d6a0 --- /dev/null +++ b/src/Umbraco.Web.UI/App_Plugins/MyPackage/Trees/LegacyTestTree.cs @@ -0,0 +1,45 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Web; +using umbraco.cms.presentation.Trees; + +namespace Umbraco.Belle.App_Plugins.MyPackage.Trees +{ + public class LegacyTestTree : BaseTree + { + public LegacyTestTree(string application) : base(application) + { + } + + public override string TreeAlias + { + get { return "legacyTestTree"; } + } + + public override int StartNodeID + { + get { return -1; } + } + + public override void RenderJS(ref StringBuilder javascript) + { + } + + public override void Render(ref XmlTree tree) + { + for (var i = 0; i < 10; i++) + { + var node = XmlTreeNode.Create(this); + node.Text = "Node " + i; + tree.Add(node); + } + } + + protected override void CreateRootNode(ref XmlTreeNode rootNode) + { + + } + } +} \ No newline at end of file diff --git a/src/Umbraco.Web.UI/App_Plugins/MyPackage/Views/ServerSidePropertyEditors/ServerEnvironment.cshtml b/src/Umbraco.Web.UI/App_Plugins/MyPackage/Views/ServerSidePropertyEditors/ServerEnvironment.cshtml new file mode 100644 index 0000000000..f949999089 --- /dev/null +++ b/src/Umbraco.Web.UI/App_Plugins/MyPackage/Views/ServerSidePropertyEditors/ServerEnvironment.cshtml @@ -0,0 +1,9 @@ +@model dynamic + + +

+ Computer Name@Environment.MachineName +

+

+ Computer Time@DateTime.Now +

\ No newline at end of file diff --git a/src/Umbraco.Web.UI/App_Plugins/MyPackage/Views/Web.config b/src/Umbraco.Web.UI/App_Plugins/MyPackage/Views/Web.config new file mode 100644 index 0000000000..f179ab8806 --- /dev/null +++ b/src/Umbraco.Web.UI/App_Plugins/MyPackage/Views/Web.config @@ -0,0 +1,58 @@ + + + + + +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj b/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj index f95e703d87..5472d1201a 100644 --- a/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj +++ b/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj @@ -283,6 +283,13 @@ Properties\SolutionInfo.cs + + + + + + + default.aspx ASPXCodeBehind @@ -545,6 +552,15 @@ umbraco.aspx + + + + + + + + + @@ -552,6 +568,9 @@ + + + 404handlers.config @@ -2527,13 +2546,13 @@ - + + - diff --git a/src/Umbraco.Web.UI/umbraco/Views/Default.cshtml b/src/Umbraco.Web.UI/umbraco/Views/Default.cshtml index 6280ca4c64..23dbdb7a19 100644 --- a/src/Umbraco.Web.UI/umbraco/Views/Default.cshtml +++ b/src/Umbraco.Web.UI/umbraco/Views/Default.cshtml @@ -98,7 +98,8 @@
{{model}}
- + @**@ + diff --git a/src/Umbraco.Web.UI/umbraco/js/umbraco.app.js b/src/Umbraco.Web.UI/umbraco/js/umbraco.app.js index ce1c80e082..ba5b655f01 100644 --- a/src/Umbraco.Web.UI/umbraco/js/umbraco.app.js +++ b/src/Umbraco.Web.UI/umbraco/js/umbraco.app.js @@ -348,36 +348,36 @@ define(['angular', 'namespaceMgr'], function (angular) { //This directive will bubble up a notification via an emit event (upwards) // describing the state of the validation element. This is useful for // parent elements to know about child element validation state. -app.directive('valBubble', function (u$AngularHelper) { - return { - require: 'ngModel', - restrict: "A", - link: function (scope, element, attr, ctrl) { + app.directive('valBubble', function (u$AngularHelper) { + return { + require: 'ngModel', + restrict: "A", + link: function (scope, element, attr, ctrl) { - if (!attr.name) { - throw "valBubble must be set on an input element that has a 'name' attribute"; - } - - var currentForm = u$AngularHelper.getCurrentForm(scope); - if (!currentForm || !currentForm.$name) - throw "valBubble requires that a name is assigned to the ng-form containing the validated input"; - - //watch the current form's validation for the current field name - scope.$watch(currentForm.$name + "." + ctrl.$name + ".$valid", function (isValid, lastValue) { - if (isValid != undefined) { - //emit an event upwards - scope.$emit("valBubble", { - isValid: isValid, // if the field is valid - element: element, // the element that the validation applies to - expression: this.exp, // the expression that was watched to check validity - scope: scope, // the current scope - ctrl: ctrl // the current controller - }); + if (!attr.name) { + throw "valBubble must be set on an input element that has a 'name' attribute"; } - }); - } - }; -}); + + var currentForm = u$AngularHelper.getCurrentForm(scope); + if (!currentForm || !currentForm.$name) + throw "valBubble requires that a name is assigned to the ng-form containing the validated input"; + + //watch the current form's validation for the current field name + scope.$watch(currentForm.$name + "." + ctrl.$name + ".$valid", function (isValid, lastValue) { + if (isValid != undefined) { + //emit an event upwards + scope.$emit("valBubble", { + isValid: isValid, // if the field is valid + element: element, // the element that the validation applies to + expression: this.exp, // the expression that was watched to check validity + scope: scope, // the current scope + ctrl: ctrl // the current controller + }); + } + }); + } + }; + }); //This directive will display a validation summary for the current form based on the //content properties of the current content item. @@ -490,34 +490,34 @@ app.directive('valBubble', function (u$AngularHelper) { }); //This service is some helper methods for extending angular -contentHelpers.factory('u$AngularHelper', function() { - return { - getCurrentForm: function(scope) { - /// Returns the current form object applied to the scope or null if one is not found - //NOTE: There isn't a way in angular to get a reference to the current form object since the form object - // is just defined as a property of the scope when it is named but you'll always need to know the name which - // isn't very convenient. If we want to watch for validation changes we need to get a form reference. - // The way that we detect the form object is a bit hackerific in that we detect all of the required properties - // that exist on a form object. + contentHelpers.factory('u$AngularHelper', function() { + return { + getCurrentForm: function(scope) { + /// Returns the current form object applied to the scope or null if one is not found + //NOTE: There isn't a way in angular to get a reference to the current form object since the form object + // is just defined as a property of the scope when it is named but you'll always need to know the name which + // isn't very convenient. If we want to watch for validation changes we need to get a form reference. + // The way that we detect the form object is a bit hackerific in that we detect all of the required properties + // that exist on a form object. - var form = null; - var requiredFormProps = ["$error", "$name", "$dirty", "$pristine", "$valid", "$invalid", "$addControl", "$removeControl", "$setValidity", "$setDirty"]; - for (var p in scope) { - if (_.isObject(scope[p]) && !_.isFunction(scope[p]) && !_.isArray(scope[p]) && p.substr(0, 1) != "$") { - var props = _.keys(scope[p]); - if (props.length < requiredFormProps.length) continue; - if (_.every(requiredFormProps, function(item) { - return _.contains(props, item); - })) { - form = scope[p]; - break; + var form = null; + var requiredFormProps = ["$error", "$name", "$dirty", "$pristine", "$valid", "$invalid", "$addControl", "$removeControl", "$setValidity", "$setDirty"]; + for (var p in scope) { + if (_.isObject(scope[p]) && !_.isFunction(scope[p]) && !_.isArray(scope[p]) && p.substr(0, 1) != "$") { + var props = _.keys(scope[p]); + if (props.length < requiredFormProps.length) continue; + if (_.every(requiredFormProps, function(item) { + return _.contains(props, item); + })) { + form = scope[p]; + break; + } } } - } - return form; - } - }; -}); + return form; + } + }; + }); //This service is used to wire up all server-side valiation messages // back into the UI in a consistent format. @@ -630,7 +630,7 @@ contentHelpers.factory('u$AngularHelper', function() { $scope.serverErrors = u$ServerValidation; //the url to get the content from - var getContentUrl = Umbraco.Sys.ServerVariables.contentEditorApiBaseUrl + "GetContent?id=" + 1; + var getContentUrl = Umbraco.Sys.ServerVariables.contentEditorApiBaseUrl + "GetContent?id=" + 1166; var saveContentUrl = Umbraco.Sys.ServerVariables.contentEditorApiBaseUrl + "PostSaveContent"; //go get the content from the server @@ -670,7 +670,7 @@ contentHelpers.factory('u$AngularHelper', function() { transformRequest: function (data) { var formData = new FormData(); //need to convert our json object to a string version of json - formData.append("model", angular.toJson(u$ContentHelper.formatPostData(data.model))); + formData.append("contentItem", angular.toJson(u$ContentHelper.formatPostData(data.model))); //now add all of the assigned files for (var f in data.files) { //each item has a property id and the file object, we'll ensure that the id is suffixed to the key diff --git a/src/Umbraco.Web.UI/umbraco/lib/underscore/underscore-min.js b/src/Umbraco.Web.UI/umbraco/lib/underscore/underscore-min.js new file mode 100644 index 0000000000..83292f0902 --- /dev/null +++ b/src/Umbraco.Web.UI/umbraco/lib/underscore/underscore-min.js @@ -0,0 +1,5 @@ +// Underscore.js 1.4.1 +// http://underscorejs.org +// (c) 2009-2012 Jeremy Ashkenas, DocumentCloud Inc. +// Underscore may be freely distributed under the MIT license. +(function(){var e=this,t=e._,n={},r=Array.prototype,i=Object.prototype,s=Function.prototype,o=r.push,u=r.slice,a=r.concat,f=r.unshift,l=i.toString,c=i.hasOwnProperty,h=r.forEach,p=r.map,d=r.reduce,v=r.reduceRight,m=r.filter,g=r.every,y=r.some,b=r.indexOf,w=r.lastIndexOf,E=Array.isArray,S=Object.keys,x=s.bind,T=function(e){if(e instanceof T)return e;if(!(this instanceof T))return new T(e);this._wrapped=e};typeof exports!="undefined"?(typeof module!="undefined"&&module.exports&&(exports=module.exports=T),exports._=T):e._=T,T.VERSION="1.4.1";var N=T.each=T.forEach=function(e,t,r){if(h&&e.forEach===h)e.forEach(t,r);else if(e.length===+e.length){for(var i=0,s=e.length;i2;if(d&&e.reduce===d)return r&&(t=T.bind(t,r)),i?e.reduce(t,n):e.reduce(t);N(e,function(e,s,o){i?n=t.call(r,n,e,s,o):(n=e,i=!0)});if(!i)throw new TypeError("Reduce of empty array with no initial value");return n},T.reduceRight=T.foldr=function(e,t,n,r){var i=arguments.length>2;if(v&&e.reduceRight===v)return r&&(t=T.bind(t,r)),arguments.length>2?e.reduceRight(t,n):e.reduceRight(t);var s=e.length;if(s!==+s){var o=T.keys(e);s=o.length}N(e,function(u,a,f){a=o?o[--s]:--s,i?n=t.call(r,n,e[a],a,f):(n=e[a],i=!0)});if(!i)throw new TypeError("Reduce of empty array with no initial value");return n},T.find=T.detect=function(e,t,n){var r;return C(e,function(e,i,s){if(t.call(n,e,i,s))return r=e,!0}),r},T.filter=T.select=function(e,t,n){var r=[];return m&&e.filter===m?e.filter(t,n):(N(e,function(e,i,s){t.call(n,e,i,s)&&(r[r.length]=e)}),r)},T.reject=function(e,t,n){var r=[];return N(e,function(e,i,s){t.call(n,e,i,s)||(r[r.length]=e)}),r},T.every=T.all=function(e,t,r){t||(t=T.identity);var i=!0;return g&&e.every===g?e.every(t,r):(N(e,function(e,s,o){if(!(i=i&&t.call(r,e,s,o)))return n}),!!i)};var C=T.some=T.any=function(e,t,r){t||(t=T.identity);var i=!1;return y&&e.some===y?e.some(t,r):(N(e,function(e,s,o){if(i||(i=t.call(r,e,s,o)))return n}),!!i)};T.contains=T.include=function(e,t){var n=!1;return b&&e.indexOf===b?e.indexOf(t)!=-1:(n=C(e,function(e){return e===t}),n)},T.invoke=function(e,t){var n=u.call(arguments,2);return T.map(e,function(e){return(T.isFunction(t)?t:e[t]).apply(e,n)})},T.pluck=function(e,t){return T.map(e,function(e){return e[t]})},T.where=function(e,t){return T.isEmpty(t)?[]:T.filter(e,function(e){for(var n in t)if(t[n]!==e[n])return!1;return!0})},T.max=function(e,t,n){if(!t&&T.isArray(e)&&e[0]===+e[0]&&e.length<65535)return Math.max.apply(Math,e);if(!t&&T.isEmpty(e))return-Infinity;var r={computed:-Infinity};return N(e,function(e,i,s){var o=t?t.call(n,e,i,s):e;o>=r.computed&&(r={value:e,computed:o})}),r.value},T.min=function(e,t,n){if(!t&&T.isArray(e)&&e[0]===+e[0]&&e.length<65535)return Math.min.apply(Math,e);if(!t&&T.isEmpty(e))return Infinity;var r={computed:Infinity};return N(e,function(e,i,s){var o=t?t.call(n,e,i,s):e;or||n===void 0)return 1;if(n>>1;n.call(r,e[u])=0})})},T.difference=function(e){var t=a.apply(r,u.call(arguments,1));return T.filter(e,function(e){return!T.contains(t,e)})},T.zip=function(){var e=u.call(arguments),t=T.max(T.pluck(e,"length")),n=new Array(t);for(var r=0;r=0;n--)t=[e[n].apply(this,t)];return t[0]}},T.after=function(e,t){return e<=0?t():function(){if(--e<1)return t.apply(this,arguments)}},T.keys=S||function(e){if(e!==Object(e))throw new TypeError("Invalid object");var t=[];for(var n in e)T.has(e,n)&&(t[t.length]=n);return t},T.values=function(e){var t=[];for(var n in e)T.has(e,n)&&t.push(e[n]);return t},T.pairs=function(e){var t=[];for(var n in e)T.has(e,n)&&t.push([n,e[n]]);return t},T.invert=function(e){var t={};for(var n in e)T.has(e,n)&&(t[e[n]]=n);return t},T.functions=T.methods=function(e){var t=[];for(var n in e)T.isFunction(e[n])&&t.push(n);return t.sort()},T.extend=function(e){return N(u.call(arguments,1),function(t){for(var n in t)e[n]=t[n]}),e},T.pick=function(e){var t={},n=a.apply(r,u.call(arguments,1));return N(n,function(n){n in e&&(t[n]=e[n])}),t},T.omit=function(e){var t={},n=a.apply(r,u.call(arguments,1));for(var i in e)T.contains(n,i)||(t[i]=e[i]);return t},T.defaults=function(e){return N(u.call(arguments,1),function(t){for(var n in t)e[n]==null&&(e[n]=t[n])}),e},T.clone=function(e){return T.isObject(e)?T.isArray(e)?e.slice():T.extend({},e):e},T.tap=function(e,t){return t(e),e};var M=function(e,t,n,r){if(e===t)return e!==0||1/e==1/t;if(e==null||t==null)return e===t;e instanceof T&&(e=e._wrapped),t instanceof T&&(t=t._wrapped);var i=l.call(e);if(i!=l.call(t))return!1;switch(i){case"[object String]":return e==String(t);case"[object Number]":return e!=+e?t!=+t:e==0?1/e==1/t:e==+t;case"[object Date]":case"[object Boolean]":return+e==+t;case"[object RegExp]":return e.source==t.source&&e.global==t.global&&e.multiline==t.multiline&&e.ignoreCase==t.ignoreCase}if(typeof e!="object"||typeof t!="object")return!1;var s=n.length;while(s--)if(n[s]==e)return r[s]==t;n.push(e),r.push(t);var o=0,u=!0;if(i=="[object Array]"){o=e.length,u=o==t.length;if(u)while(o--)if(!(u=M(e[o],t[o],n,r)))break}else{var a=e.constructor,f=t.constructor;if(a!==f&&!(T.isFunction(a)&&a instanceof a&&T.isFunction(f)&&f instanceof f))return!1;for(var c in e)if(T.has(e,c)){o++;if(!(u=T.has(t,c)&&M(e[c],t[c],n,r)))break}if(u){for(c in t)if(T.has(t,c)&&!(o--))break;u=!o}}return n.pop(),r.pop(),u};T.isEqual=function(e,t){return M(e,t,[],[])},T.isEmpty=function(e){if(e==null)return!0;if(T.isArray(e)||T.isString(e))return e.length===0;for(var t in e)if(T.has(e,t))return!1;return!0},T.isElement=function(e){return!!e&&e.nodeType===1},T.isArray=E||function(e){return l.call(e)=="[object Array]"},T.isObject=function(e){return e===Object(e)},N(["Arguments","Function","String","Number","Date","RegExp"],function(e){T["is"+e]=function(t){return l.call(t)=="[object "+e+"]"}}),T.isArguments(arguments)||(T.isArguments=function(e){return!!e&&!!T.has(e,"callee")}),typeof /./!="function"&&(T.isFunction=function(e){return typeof e=="function"}),T.isFinite=function(e){return T.isNumber(e)&&isFinite(e)},T.isNaN=function(e){return T.isNumber(e)&&e!=+e},T.isBoolean=function(e){return e===!0||e===!1||l.call(e)=="[object Boolean]"},T.isNull=function(e){return e===null},T.isUndefined=function(e){return e===void 0},T.has=function(e,t){return c.call(e,t)},T.noConflict=function(){return e._=t,this},T.identity=function(e){return e},T.times=function(e,t,n){for(var r=0;r":">",'"':""","'":"'","/":"/"}};_.unescape=T.invert(_.escape);var D={escape:new RegExp("["+T.keys(_.escape).join("")+"]","g"),unescape:new RegExp("("+T.keys(_.unescape).join("|")+")","g")};T.each(["escape","unescape"],function(e){T[e]=function(t){return t==null?"":(""+t).replace(D[e],function(t){return _[e][t]})}}),T.result=function(e,t){if(e==null)return null;var n=e[t];return T.isFunction(n)?n.call(e):n},T.mixin=function(e){N(T.functions(e),function(t){var n=T[t]=e[t];T.prototype[t]=function(){var e=[this._wrapped];return o.apply(e,arguments),F.call(this,n.apply(T,e))}})};var P=0;T.uniqueId=function(e){var t=P++;return e?e+t:t},T.templateSettings={evaluate:/<%([\s\S]+?)%>/g,interpolate:/<%=([\s\S]+?)%>/g,escape:/<%-([\s\S]+?)%>/g};var H=/(.)^/,B={"'":"'","\\":"\\","\r":"r","\n":"n"," ":"t","\u2028":"u2028","\u2029":"u2029"},j=/\\|'|\r|\n|\t|\u2028|\u2029/g;T.template=function(e,t,n){n=T.defaults({},n,T.templateSettings);var r=new RegExp([(n.escape||H).source,(n.interpolate||H).source,(n.evaluate||H).source].join("|")+"|$","g"),i=0,s="__p+='";e.replace(r,function(t,n,r,o,u){s+=e.slice(i,u).replace(j,function(e){return"\\"+B[e]}),s+=n?"'+\n((__t=("+n+"))==null?'':_.escape(__t))+\n'":r?"'+\n((__t=("+r+"))==null?'':__t)+\n'":o?"';\n"+o+"\n__p+='":"",i=u+t.length}),s+="';\n",n.variable||(s="with(obj||{}){\n"+s+"}\n"),s="var __t,__p='',__j=Array.prototype.join,print=function(){__p+=__j.call(arguments,'');};\n"+s+"return __p;\n";try{var o=new Function(n.variable||"obj","_",s)}catch(u){throw u.source=s,u}if(t)return o(t,T);var a=function(e){return o.call(this,e,T)};return a.source="function("+(n.variable||"obj")+"){\n"+s+"}",a},T.chain=function(e){return T(e).chain()};var F=function(e){return this._chain?T(e).chain():e};T.mixin(T),N(["pop","push","reverse","shift","sort","splice","unshift"],function(e){var t=r[e];T.prototype[e]=function(){var n=this._wrapped;return t.apply(n,arguments),(e=="shift"||e=="splice")&&n.length===0&&delete n[0],F.call(this,n)}}),N(["concat","join","slice"],function(e){var t=r[e];T.prototype[e]=function(){return F.call(this,t.apply(this._wrapped,arguments))}}),T.extend(T.prototype,{chain:function(){return this._chain=!0,this},value:function(){return this._wrapped}})}).call(this); \ No newline at end of file diff --git a/src/Umbraco.Web/Models/ContentEditing/ContentPropertyDisplay.cs b/src/Umbraco.Web/Models/ContentEditing/ContentPropertyDisplay.cs index 34a734aa54..d3aa1d5452 100644 --- a/src/Umbraco.Web/Models/ContentEditing/ContentPropertyDisplay.cs +++ b/src/Umbraco.Web/Models/ContentEditing/ContentPropertyDisplay.cs @@ -1,4 +1,5 @@ -using System.ComponentModel.DataAnnotations; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; using System.Runtime.Serialization; namespace Umbraco.Web.Models.ContentEditing @@ -24,6 +25,6 @@ namespace Umbraco.Web.Models.ContentEditing public string View { get; set; } [DataMember(Name = "config")] - public string Config { get; set; } + public IEnumerable Config { get; set; } } } \ No newline at end of file diff --git a/src/Umbraco.Web/Models/ContentEditing/ContentPropertyDto.cs b/src/Umbraco.Web/Models/ContentEditing/ContentPropertyDto.cs index 2b453b6f6c..e3f8650689 100644 --- a/src/Umbraco.Web/Models/ContentEditing/ContentPropertyDto.cs +++ b/src/Umbraco.Web/Models/ContentEditing/ContentPropertyDto.cs @@ -1,4 +1,5 @@ -using Umbraco.Core.Models; +using System.Collections.Generic; +using Umbraco.Core.Models; namespace Umbraco.Web.Models.ContentEditing { @@ -10,20 +11,6 @@ namespace Umbraco.Web.Models.ContentEditing public IDataTypeDefinition DataType { get; set; } public string Label { get; set; } public string Alias { get; set; } - public string Description { get; set; } - - public ContentPropertyDisplay ForDisplay(string getPreValue, string view) - { - return new ContentPropertyDisplay - { - Alias = Alias, - Id = Id, - View = view, - Config = getPreValue, - Description = Description, - Label = Label, - Value = Value - }; - } + public string Description { get; set; } } } \ No newline at end of file diff --git a/src/Umbraco.Web/Models/Mapping/ContentModelMapper.cs b/src/Umbraco.Web/Models/Mapping/ContentModelMapper.cs index 76f5222a5a..22567277a5 100644 --- a/src/Umbraco.Web/Models/Mapping/ContentModelMapper.cs +++ b/src/Umbraco.Web/Models/Mapping/ContentModelMapper.cs @@ -39,7 +39,7 @@ namespace Umbraco.Web.Models.Mapping Id = p.Id, Description = p.PropertyType.Description, Label = p.PropertyType.Name, - Config = _applicationContext.Services.DataTypeService.GetPreValueAsString(p.PropertyType.DataTypeDefinitionId), + Config = _applicationContext.Services.DataTypeService.GetPreValuesByDataTypeId(p.PropertyType.DataTypeDefinitionId), Value = p.Value.ToString(), View = editor.ValueEditor.View }; diff --git a/src/Umbraco.Web/UI/JavaScript/RequireJsConfig.js b/src/Umbraco.Web/UI/JavaScript/RequireJsConfig.js index 5be5db0bb9..cda72178ef 100644 --- a/src/Umbraco.Web/UI/JavaScript/RequireJsConfig.js +++ b/src/Umbraco.Web/UI/JavaScript/RequireJsConfig.js @@ -1,15 +1,15 @@ { waitSeconds: 120, paths: { - jquery: '../lib/jquery/jquery-1.8.2.min', - underscore: '../lib/underscore/underscore', - angular: '../lib/angular/angular', - angularResource: '../lib/angular/angular-resource', - statemanager: '../lib/angular/statemanager', - text: '../lib/require/text', - async: '../lib/require/async', - namespaceMgr: '../lib/Umbraco/NamespaceManager', - myApp: '../js/myApp' + jquery: 'lib/jquery/jquery-1.8.2.min', + underscore: 'lib/underscore/underscore-min', + angular: 'lib/angular/angular', + angularResource: 'lib/angular/angular-resource', + statemanager: 'lib/angular/statemanager', + text: 'lib/require/text', + async: 'lib/require/async', + namespaceMgr: 'lib/Umbraco/NamespaceManager', + myApp: 'js/umbraco.app' }, shim: { 'angular' : {'exports' : 'angular'},