From 4b68d1950c5a8fca15fcbbdbb9f8ceb3999bffd7 Mon Sep 17 00:00:00 2001 From: Per Ploug Date: Tue, 18 Jun 2013 10:51:26 +0200 Subject: [PATCH] Replaces require.js with jepnope Gets rid of the AMD pattern, adds scriptLoader service, work on security service started --- .gitignore | 3 +- src/Umbraco.Web.UI.Client/gruntFile.js | 52 ++---- .../lib/yepnope/yepnope.min.js | 2 + src/Umbraco.Web.UI.Client/src/app.js | 9 +- src/Umbraco.Web.UI.Client/src/app_dev.js | 9 +- .../common/filters/treeiconclass.filter.js | 2 +- .../mocks/resources/content.resource.js | 164 +++++++++--------- .../common/mocks/resources/media.resource.js | 18 +- .../common/mocks/resources/tree.resource.js | 83 ++++----- .../src/common/resources/content.resource.js | 2 +- .../src/common/resources/media.resource.js | 2 +- .../src/common/security/_module.js | 4 + .../src/common/security/interceptor.js | 23 +++ .../src/common/security/retryqueue.js | 68 ++++++++ .../src/common/security/security.service.js | 114 ++++++++++++ .../common/services/scriptloader.service.js | 19 ++ .../src/common/services/scripts.js | 1 - .../src/common/services/utill.service.js | 6 +- src/Umbraco.Web.UI.Client/src/index.html | 5 + src/Umbraco.Web.UI.Client/src/loader.js | 28 +++ src/Umbraco.Web.UI.Client/src/main.js | 6 +- src/Umbraco.Web.UI.Client/src/routes.js | 10 +- .../views/common/application.controller.js | 24 ++- .../src/views/common/dashboard.html | 2 +- .../datepicker/datepicker.controller.js | 13 +- .../googlemaps/googlemaps.controller.js | 143 +++++++-------- .../umbraco/rte/rte.controller.js | 129 ++++++-------- .../umbraco/tags/tags.controller.js | 11 +- src/Umbraco.Web.UI.Client/test/config/unit.js | 8 +- ...r.spec.js => editContentController.def.js} | 0 .../common/services/contentFactory.spec.js | 8 +- .../Js/googlemaps.controller.js | 39 +++-- .../PropertyEditors/Views/simpleeditor.html | 29 ++++ .../PropertyEditors/js/simpleeditor.js | 10 ++ .../App_Plugins/SimpleEditor/package.manifest | 19 ++ .../umbraco/Views/Default.cshtml | 1 - 36 files changed, 681 insertions(+), 385 deletions(-) create mode 100644 src/Umbraco.Web.UI.Client/lib/yepnope/yepnope.min.js create mode 100644 src/Umbraco.Web.UI.Client/src/common/security/_module.js create mode 100644 src/Umbraco.Web.UI.Client/src/common/security/interceptor.js create mode 100644 src/Umbraco.Web.UI.Client/src/common/security/retryqueue.js create mode 100644 src/Umbraco.Web.UI.Client/src/common/security/security.service.js create mode 100644 src/Umbraco.Web.UI.Client/src/common/services/scriptloader.service.js delete mode 100644 src/Umbraco.Web.UI.Client/src/common/services/scripts.js create mode 100644 src/Umbraco.Web.UI.Client/src/loader.js rename src/Umbraco.Web.UI.Client/test/unit/app/content/{editContentController.spec.js => editContentController.def.js} (100%) create mode 100644 src/Umbraco.Web.UI/App_Plugins/SimpleEditor/PropertyEditors/Views/simpleeditor.html create mode 100644 src/Umbraco.Web.UI/App_Plugins/SimpleEditor/PropertyEditors/js/simpleeditor.js create mode 100644 src/Umbraco.Web.UI/App_Plugins/SimpleEditor/package.manifest diff --git a/.gitignore b/.gitignore index 54827f7960..bc84c44c73 100644 --- a/.gitignore +++ b/.gitignore @@ -76,7 +76,8 @@ src/Umbraco.Web.UI/umbraco/[V]iews/**/*.css src/Umbraco.Web.UI/umbraco/[V]iews/**/*.html src/Umbraco.Web.UI/umbraco/assets/* src/Umbraco.Web.UI.Client/build/* -src/Umbraco.Web.UI.Client/build/* +src/Umbraco.Web.UI.Client/build/**/*.* src/Umbraco.Web.UI.Client/build/belle/ src/Umbraco.Web.UI/UserControls/ build/_BuildOutput/ +build/belle/ diff --git a/src/Umbraco.Web.UI.Client/gruntFile.js b/src/Umbraco.Web.UI.Client/gruntFile.js index 9acd5611d3..c765cba57d 100644 --- a/src/Umbraco.Web.UI.Client/gruntFile.js +++ b/src/Umbraco.Web.UI.Client/gruntFile.js @@ -105,8 +105,8 @@ module.exports = function (grunt) { }, app: { files: [ - { dest: '<%= distdir %>/js', src : 'main.js', expand: true, cwd: 'src/' }, - { dest: '<%= distdir %>/js', src : 'routes.js', expand: true, cwd: 'src/' }] + { dest: '<%= distdir %>/js', src : '*.js', expand: true, cwd: 'src/' } + ] }, media: { files: [{ dest: 'build/media', src : '*.*', expand: true, cwd: 'media/' }] @@ -130,65 +130,37 @@ module.exports = function (grunt) { process: true } }, - app: { - src: ['src/app.js'], - dest: '<%= distdir %>/js/app.js', - options:{ - banner: "<%= banner %>'use strict';\ndefine(['angular'], function (angular) {\n", - footer: "\n\nreturn app;\n});" - } - }, angular: { src:['vendor/angular/angular.min.js'], dest: '<%= distdir %>/lib/angular/angular.min.js' }, controllers: { src:['src/views/**/*.controller.js'], - dest: '<%= distdir %>/js/umbraco.controllers.js', - options:{ - banner: "'use strict';\n<%= banner %>\ndefine(['app', 'angular'], function (app, angular) {\n", - footer: "\n\nreturn angular;\n});" - } + dest: '<%= distdir %>/js/umbraco.controllers.js' }, services: { src:['src/common/services/*.js'], - dest: '<%= distdir %>/js/umbraco.services.js', - options:{ - banner: "'use strict';\ndefine(['app','angular'], function (app, angular) {\n", - footer: "\n\nreturn angular;\n});" - } + dest: '<%= distdir %>/js/umbraco.services.js' + }, + security: { + src:['src/common/security/*.js'], + dest: '<%= distdir %>/js/umbraco.security.js' }, resources: { src:['src/common/resources/*.js'], - dest: '<%= distdir %>/js/umbraco.resources.js', - options:{ - banner: "<%= banner %>'use strict';\ndefine(['app', 'angular'], function (app, angular) {\n", - footer: "\n\nreturn angular;\n});" - } + dest: '<%= distdir %>/js/umbraco.resources.js' }, mocks: { src:['src/common/mocks/**/*.js'], - dest: '<%= distdir %>/js/umbraco.mocks.js', - options:{ - banner: "<%= banner %>'use strict';\ndefine(['app', 'angular'], function (app, angular) {\n", - footer: "\n\nreturn angular;\n});" - } + dest: '<%= distdir %>/js/umbraco.mocks.js' }, directives: { src:['src/common/directives/*.js'], - dest: '<%= distdir %>/js/umbraco.directives.js', - options:{ - banner: "<%= banner %>'use strict';\ndefine(['app','angular','underscore'], function (app, angular,_) {\n", - footer: "\n\nreturn angular;\n});" - } + dest: '<%= distdir %>/js/umbraco.directives.js' }, filters: { src:['src/common/filters/*.js'], - dest: '<%= distdir %>/js/umbraco.filters.js', - options:{ - banner: "<%= banner %>'use strict';\ndefine([ 'app','angular'], function (app,angular) {\n", - footer: "\n\nreturn app;\n});" - } + dest: '<%= distdir %>/js/umbraco.filters.js' } }, diff --git a/src/Umbraco.Web.UI.Client/lib/yepnope/yepnope.min.js b/src/Umbraco.Web.UI.Client/lib/yepnope/yepnope.min.js new file mode 100644 index 0000000000..73655a5b27 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/lib/yepnope/yepnope.min.js @@ -0,0 +1,2 @@ +/*yepnope1.5.x|WTFPL*/ +(function(a,b,c){function d(a){return"[object Function]"==o.call(a)}function e(a){return"string"==typeof a}function f(){}function g(a){return!a||"loaded"==a||"complete"==a||"uninitialized"==a}function h(){var a=p.shift();q=1,a?a.t?m(function(){("c"==a.t?B.injectCss:B.injectJs)(a.s,0,a.a,a.x,a.e,1)},0):(a(),h()):q=0}function i(a,c,d,e,f,i,j){function k(b){if(!o&&g(l.readyState)&&(u.r=o=1,!q&&h(),l.onload=l.onreadystatechange=null,b)){"img"!=a&&m(function(){t.removeChild(l)},50);for(var d in y[c])y[c].hasOwnProperty(d)&&y[c][d].onload()}}var j=j||B.errorTimeout,l=b.createElement(a),o=0,r=0,u={t:d,s:c,e:f,a:i,x:j};1===y[c]&&(r=1,y[c]=[]),"object"==a?l.data=c:(l.src=c,l.type=a),l.width=l.height="0",l.onerror=l.onload=l.onreadystatechange=function(){k.call(this,r)},p.splice(e,0,u),"img"!=a&&(r||2===y[c]?(t.insertBefore(l,s?null:n),m(k,j)):y[c].push(l))}function j(a,b,c,d,f){return q=0,b=b||"j",e(a)?i("c"==b?v:u,a,b,this.i++,c,d,f):(p.splice(this.i++,0,a),1==p.length&&h()),this}function k(){var a=B;return a.loader={load:j,i:0},a}var l=b.documentElement,m=a.setTimeout,n=b.getElementsByTagName("script")[0],o={}.toString,p=[],q=0,r="MozAppearance"in l.style,s=r&&!!b.createRange().compareNode,t=s?l:n.parentNode,l=a.opera&&"[object Opera]"==o.call(a.opera),l=!!b.attachEvent&&!l,u=r?"object":l?"script":"img",v=l?"script":u,w=Array.isArray||function(a){return"[object Array]"==o.call(a)},x=[],y={},z={timeout:function(a,b){return b.length&&(a.timeout=b[0]),a}},A,B;B=function(a){function b(a){var a=a.split("!"),b=x.length,c=a.pop(),d=a.length,c={url:c,origUrl:c,prefixes:a},e,f,g;for(f=0;faskjdkasj lasjd

" }, + { alias: "textarea", label: "textarea", view: "umbraco.textarea", value: "ajsdka sdjkds", config: { rows: 4 } }, + { alias: "map", label: "Map", view: "umbraco.googlemaps", value: "37.4419,-122.1419", config: { mapType: "ROADMAP", zoom: 4 } }, + { alias: "media", label: "Media picker", view: "umbraco.mediapicker", value: "" }, + { alias: "content", label: "Content picker", view: "umbraco.contentpicker", value: "" } + ] + }, + { + label: "Sample Editor", + alias: "tab02", + id: 2, + properties: [ + { alias: "datepicker", label: "Datepicker", view: "umbraco.datepicker", config: { rows: 7 } }, + { alias: "tags", label: "Tags", view: "umbraco.tags", value: ""} + ] + }, + { + label: "Grid", + alias: "tab03", + id: 3, + properties: [ + { alias: "grid", label: "Grid", view: "umbraco.grid", controller: "umbraco.grid", value: "test", hideLabel: true } + ] + },{ + label: "WIP", + alias: "tab04", + id: 4, + properties: [ + { alias: "tes", label: "Stuff", view: "umbraco.test", controller: "umbraco.embeddedcontent", value: "", + + config: { + fields: [ + { alias: "embedded", label: "Embbeded", view: "umbraco.textstring", value: ""}, + { alias: "embedded2", label: "Embbeded 2", view: "umbraco.contentpicker", value: ""}, + { alias: "embedded3", label: "Embbeded 3", view: "umbraco.textarea", value: ""}, + { alias: "embedded4", label: "Embbeded 4", view: "umbraco.datepicker", value: ""} + ] + } + } + ] + } + ] + }; +} + + + + angular.module('umbraco.mocks.resources') -.factory('contentResource', function () { - +.factory('contentResource', function ($q) { var contentArray = []; - var factory = { - _cachedItems: contentArray, - getContent: function (id) { - + getById: function (id) { + var deferred = $q.defer(); if (contentArray[id] !== undefined){ - return contentArray[id]; + deferred.resolve(contentArray[id]); + }else{ + deferred.resolve(_getNode(id)); } - var content = { - name: "My content with id: " + id, - updateDate: new Date(), - publishDate: new Date(), - id: id, - parentId: 1234, - icon: "icon-file-alt", - owner: {name: "Administrator", id: 0}, - updater: {name: "Per Ploug Krogslund", id: 1}, - - tabs: [ - { - label: "Child documents", - alias: "tab00", - id: 0, - active: true, - properties: [ - { alias: "list", label: "List", view: "umbraco.listview", value: "", hideLabel: true } - ] - }, - { - label: "Content", - alias: "tab01", - id: 1, - properties: [ - { alias: "bodyText", label: "Body Text", description:"Here you enter the primary article contents", view: "umbraco.rte", value: "

askjdkasj lasjd

" }, - { alias: "textarea", label: "textarea", view: "umbraco.textarea", value: "ajsdka sdjkds", config: { rows: 4 } }, - { alias: "map", label: "Map", view: "umbraco.googlemaps", value: "37.4419,-122.1419", config: { mapType: "ROADMAP", zoom: 4 } }, - { alias: "media", label: "Media picker", view: "umbraco.mediapicker", value: "" }, - { alias: "content", label: "Content picker", view: "umbraco.contentpicker", value: "" } - ] - }, - { - label: "Sample Editor", - alias: "tab02", - id: 2, - properties: [ - { alias: "datepicker", label: "Datepicker", view: "umbraco.datepicker", config: { rows: 7 } }, - { alias: "tags", label: "Tags", view: "umbraco.tags", value: ""} - ] - }, - { - label: "Grid", - alias: "tab03", - id: 3, - properties: [ - { alias: "grid", label: "Grid", view: "umbraco.grid", controller: "umbraco.grid", value: "test", hideLabel: true } - ] - },{ - label: "WIP", - alias: "tab04", - id: 4, - properties: [ - { alias: "tes", label: "Stuff", view: "umbraco.test", controller: "umbraco.embeddedcontent", value: "", - - config: { - fields: [ - { alias: "embedded", label: "Embbeded", view: "umbraco.textstring", value: ""}, - { alias: "embedded2", label: "Embbeded 2", view: "umbraco.contentpicker", value: ""}, - { alias: "embedded3", label: "Embbeded 3", view: "umbraco.textarea", value: ""}, - { alias: "embedded4", label: "Embbeded 4", view: "umbraco.datepicker", value: ""} - ] - } - } - ] - } - - - ] - }; - - // return undefined; - - return content; + return deferred.promise; }, //returns an empty content object which can be persistent on the content service @@ -131,7 +131,7 @@ angular.module('umbraco.mocks.resources') var _id = 0; for (var i = 0; i < collection.take; i++) { _id = (parentId + i) * options.offset; - var cnt = this.getContent(_id); + var cnt = this.getById(_id); //here we fake filtering if(options.filter !== ''){ diff --git a/src/Umbraco.Web.UI.Client/src/common/mocks/resources/media.resource.js b/src/Umbraco.Web.UI.Client/src/common/mocks/resources/media.resource.js index 9eddb304d8..7fe28ecab1 100644 --- a/src/Umbraco.Web.UI.Client/src/common/mocks/resources/media.resource.js +++ b/src/Umbraco.Web.UI.Client/src/common/mocks/resources/media.resource.js @@ -1,13 +1,19 @@ angular.module('umbraco.mocks.resources') -.factory('mediaResource', function () { +.factory('mediaResource', function ($q) { var mediaArray = []; return { rootMedia: function(){ - return [ - {id: 1234, src: "/Media/boston.jpg", thumbnail: "/Media/boston.jpg" }, - {src: "/Media/bird.jpg", thumbnail: "/Media/bird.jpg" }, - {src: "/Media/frog.jpg", thumbnail: "/Media/frog.jpg" } - ]; + + var deferred = $q.defer(); + + deferred.resolve( + [ + {id: 1234, src: "/Media/boston.jpg", thumbnail: "/Media/boston.jpg" }, + {src: "/Media/bird.jpg", thumbnail: "/Media/bird.jpg" }, + {src: "/Media/frog.jpg", thumbnail: "/Media/frog.jpg" } + ]); + + return deferred.promise; } }; }); \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/common/mocks/resources/tree.resource.js b/src/Umbraco.Web.UI.Client/src/common/mocks/resources/tree.resource.js index 0158f0a8ad..2489631ea2 100644 --- a/src/Umbraco.Web.UI.Client/src/common/mocks/resources/tree.resource.js +++ b/src/Umbraco.Web.UI.Client/src/common/mocks/resources/tree.resource.js @@ -21,10 +21,10 @@ function treeResource($q) { } return [ - { name: "child-of-" + treeItem.name, id: iLevel + "" + 1234, icon: "icon-file-alt", view: section + "/edit/" + iLevel + "" + 1234, children: [], expanded: false, level: iLevel, defaultAction: action }, - { name: "random-name-" + section, id: iLevel + "" + 1235, icon: "icon-file-alt", view: section + "/edit/" + iLevel + "" + 1235, children: [], expanded: false, level: iLevel, defaultAction: action }, - { name: "random-name-" + section, id: iLevel + "" + 1236, icon: "icon-file-alt", view: section + "/edit/" + iLevel + "" + 1236, children: [], expanded: false, level: iLevel, defaultAction: action }, - { name: "random-name-" + section, id: iLevel + "" + 1237, icon: "icon-file-alt", view: "common/legacy/1237?p=" + encodeURI("developer/contentType.aspx?idequal1234"), children: [], expanded: false, level: iLevel, defaultAction: action } + { name: "child-of-" + treeItem.name, id: iLevel + "" + 1234, icon: "icon-file-alt", view: section + "/edit/" + iLevel + "" + 1234, children: [], expanded: false, hasChildren: true, level: iLevel, defaultAction: action }, + { name: "random-name-" + section, id: iLevel + "" + 1235, icon: "icon-file-alt", view: section + "/edit/" + iLevel + "" + 1235, children: [], expanded: false, hasChildren: true, level: iLevel, defaultAction: action }, + { name: "random-name-" + section, id: iLevel + "" + 1236, icon: "icon-file-alt", view: section + "/edit/" + iLevel + "" + 1236, children: [], expanded: false, hasChildren: true, level: iLevel, defaultAction: action }, + { name: "random-name-" + section, id: iLevel + "" + 1237, icon: "icon-file-alt", view: "common/legacy/1237?p=" + encodeURI("developer/contentType.aspx?idequal1234"), children: [], expanded: false, hasChildren: true, level: iLevel, defaultAction: action } ]; } @@ -36,7 +36,7 @@ function treeResource($q) { var section = options.section || 'content'; var cacheKey = options.cachekey || ''; - cacheKey += "_" + section; + cacheKey += "_" + section; if (treeArray[cacheKey] !== undefined){ return treeArray[cacheKey]; @@ -46,59 +46,39 @@ function treeResource($q) { switch(section){ case "content": - t = { - name: section, - alias: section, - - children: [ - { name: "My website", id: 1234, icon: "icon-home", view: section + "/edit/" + 1234, children: [], expanded: false, level: 1, defaultAction: "create" }, - { name: "Components", id: 1235, icon: "icon-cogs", view: section + "/edit/" + 1235, children: [], expanded: false, level: 1, defaultAction: "create" }, - { name: "Archieve", id: 1236, icon: "icon-folder-close", view: section + "/edit/" + 1236, children: [], expanded: false, level: 1, defaultAction: "create" }, - { name: "Recycle Bin", id: 1237, icon: "icon-trash", view: section + "/trash/view/", children: [], expanded: false, level: 1, defaultAction: "create" } - ] - }; + t = [ + { name: "My website", id: 1234, icon: "icon-home", view: section + "/edit/" + 1234, children: [], expanded: false, hasChildren: true, level: 1, defaultAction: "create" }, + { name: "Components", id: 1235, icon: "icon-cogs", view: section + "/edit/" + 1235, children: [], expanded: false, hasChildren: true, level: 1, defaultAction: "create" }, + { name: "Archieve", id: 1236, icon: "icon-folder-close", view: section + "/edit/" + 1236, children: [], expanded: false, hasChildren: true, level: 1, defaultAction: "create" }, + { name: "Recycle Bin", id: 1237, icon: "icon-trash", view: section + "/trash/view/", children: [], expanded: false, hasChildren: true, level: 1, defaultAction: "create" } + ]; break; case "developer": - t = { - name: section, - alias: section, - - children: [ - { name: "Data types", id: 1234, icon: "icon-folder-close", view: section + "/edit/" + 1234, children: [], expanded: false, level: 1 }, - { name: "Macros", id: 1235, icon: "icon-folder-close", view: section + "/edit/" + 1235, children: [], expanded: false, level: 1 }, - { name: "Pacakges", id: 1236, icon: "icon-folder-close", view: section + "/edit/" + 1236, children: [], expanded: false, level: 1 }, - { name: "XSLT Files", id: 1237, icon: "icon-folder-close", view: section + "/edit/" + 1237, children: [], expanded: false, level: 1 }, - { name: "Razor Files", id: 1237, icon: "icon-folder-close", view: section + "/edit/" + 1237, children: [], expanded: false, level: 1 } - ] - }; + t = [ + { name: "Data types", id: 1234, icon: "icon-folder-close", view: section + "/edit/" + 1234, children: [], expanded: false, hasChildren: true, level: 1 }, + { name: "Macros", id: 1235, icon: "icon-folder-close", view: section + "/edit/" + 1235, children: [], expanded: false, hasChildren: true, level: 1 }, + { name: "Pacakges", id: 1236, icon: "icon-folder-close", view: section + "/edit/" + 1236, children: [], expanded: false, hasChildren: true, level: 1 }, + { name: "XSLT Files", id: 1237, icon: "icon-folder-close", view: section + "/edit/" + 1237, children: [], expanded: false, hasChildren: true, level: 1 }, + { name: "Razor Files", id: 1237, icon: "icon-folder-close", view: section + "/edit/" + 1237, children: [], expanded: false, hasChildren: true, level: 1 } + ]; break; case "settings": - t = { - name: section, - alias: section, - - children: [ - { name: "Stylesheets", id: 1234, icon: "icon-folder-close", view: section + "/edit/" + 1234, children: [], expanded: false, level: 1 }, - { name: "Templates", id: 1235, icon: "icon-folder-close", view: section + "/edit/" + 1235, children: [], expanded: false, level: 1 }, - { name: "Dictionary", id: 1236, icon: "icon-folder-close", view: section + "/edit/" + 1236, children: [], expanded: false, level: 1 }, - { name: "Media types", id: 1237, icon: "icon-folder-close", view: section + "/edit/" + 1237, children: [], expanded: false, level: 1 }, - { name: "Document types", id: 1237, icon: "icon-folder-close", view: section + "/edit/" + 1237, children: [], expanded: false, level: 1 } - ] - }; + t = [ + { name: "Stylesheets", id: 1234, icon: "icon-folder-close", view: section + "/edit/" + 1234, children: [], expanded: false, hasChildren: true, level: 1 }, + { name: "Templates", id: 1235, icon: "icon-folder-close", view: section + "/edit/" + 1235, children: [], expanded: false, hasChildren: true, level: 1 }, + { name: "Dictionary", id: 1236, icon: "icon-folder-close", view: section + "/edit/" + 1236, children: [], expanded: false, hasChildren: true, level: 1 }, + { name: "Media types", id: 1237, icon: "icon-folder-close", view: section + "/edit/" + 1237, children: [], expanded: false, hasChildren: true, level: 1 }, + { name: "Document types", id: 1237, icon: "icon-folder-close", view: section + "/edit/" + 1237, children: [], expanded: false, hasChildren: true, level: 1 } + ]; break; default: - t = { - name: section, - alias: section, - - children: [ - { name: "random-name-" + section, id: 1234, icon: "icon-home", defaultAction: "create", view: section + "/edit/" + 1234, children: [], expanded: false, level: 1 }, - { name: "random-name-" + section, id: 1235, icon: "icon-folder-close", defaultAction: "create", view: section + "/edit/" + 1235, children: [], expanded: false, level: 1 }, - { name: "random-name-" + section, id: 1236, icon: "icon-folder-close", defaultAction: "create", view: section + "/edit/" + 1236, children: [], expanded: false, level: 1 }, - { name: "random-name-" + section, id: 1237, icon: "icon-folder-close", defaultAction: "create", view: section + "/edit/" + 1237, children: [], expanded: false, level: 1 } - ] - }; + t = [ + { name: "random-name-" + section, id: 1234, icon: "icon-home", defaultAction: "create", view: section + "/edit/" + 1234, children: [], expanded: false, hasChildren: true, level: 1 }, + { name: "random-name-" + section, id: 1235, icon: "icon-folder-close", defaultAction: "create", view: section + "/edit/" + 1235, children: [], expanded: false, hasChildren: true, level: 1 }, + { name: "random-name-" + section, id: 1236, icon: "icon-folder-close", defaultAction: "create", view: section + "/edit/" + 1236, children: [], expanded: false, hasChildren: true, level: 1 }, + { name: "random-name-" + section, id: 1237, icon: "icon-folder-close", defaultAction: "create", view: section + "/edit/" + 1237, children: [], expanded: false, hasChildren: true, level: 1 } + ]; break; } @@ -121,7 +101,6 @@ function treeResource($q) { var deferred = $q.defer(); var data = _getChildren(options); - deferred.resolve(data); return deferred.promise; } diff --git a/src/Umbraco.Web.UI.Client/src/common/resources/content.resource.js b/src/Umbraco.Web.UI.Client/src/common/resources/content.resource.js index 24cdc63116..c33e6aacf8 100644 --- a/src/Umbraco.Web.UI.Client/src/common/resources/content.resource.js +++ b/src/Umbraco.Web.UI.Client/src/common/resources/content.resource.js @@ -52,7 +52,7 @@ function contentResource($q, $http, umbDataFormatter, umbRequestHelper) { deferred.reject('Failed to retreive data for content id ' + id); }); - return deferred.promise; + return deferred.promise; }, getByIds: function (ids) { diff --git a/src/Umbraco.Web.UI.Client/src/common/resources/media.resource.js b/src/Umbraco.Web.UI.Client/src/common/resources/media.resource.js index 51373415a8..2673bbd343 100644 --- a/src/Umbraco.Web.UI.Client/src/common/resources/media.resource.js +++ b/src/Umbraco.Web.UI.Client/src/common/resources/media.resource.js @@ -121,7 +121,7 @@ function mediaResource($q, $http, umbDataFormatter, umbRequestHelper) { /** saves or updates a media object */ saveMedia: function (media, isNew, files) { return saveMediaItem(media, "save" + (isNew ? "New" : ""), files); - }, + } }; } diff --git a/src/Umbraco.Web.UI.Client/src/common/security/_module.js b/src/Umbraco.Web.UI.Client/src/common/security/_module.js new file mode 100644 index 0000000000..93b0f58c1d --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/common/security/_module.js @@ -0,0 +1,4 @@ +// Based loosely around work by Witold Szczerba - https://github.com/witoldsz/angular-http-auth +angular.module('umbraco.security', [ + 'umbraco.security.service', + 'umbraco.security.interceptor']); \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/common/security/interceptor.js b/src/Umbraco.Web.UI.Client/src/common/security/interceptor.js new file mode 100644 index 0000000000..892b46fe24 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/common/security/interceptor.js @@ -0,0 +1,23 @@ +angular.module('umbraco.security.interceptor', ['umbraco.security.retryQueue']) + +// This http interceptor listens for authentication failures +.factory('securityInterceptor', ['$injector', 'securityRetryQueue', function($injector, queue) { + return function(promise) { + // Intercept failed requests + return promise.then(null, function(originalResponse) { + if(originalResponse.status === 401) { + // The request bounced because it was not authorized - add a new request to the retry queue + promise = queue.pushRetryFn('unauthorized-server', function retryRequest() { + // We must use $injector to get the $http service to prevent circular dependency + return $injector.get('$http')(originalResponse.config); + }); + } + return promise; + }); + }; +}]) + +// We have to add the interceptor to the queue as a string because the interceptor depends upon service instances that are not available in the config block. +.config(['$httpProvider', function($httpProvider) { + $httpProvider.responseInterceptors.push('securityInterceptor'); +}]); \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/common/security/retryqueue.js b/src/Umbraco.Web.UI.Client/src/common/security/retryqueue.js new file mode 100644 index 0000000000..f734eecb87 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/common/security/retryqueue.js @@ -0,0 +1,68 @@ +angular.module('umbraco.security.retryQueue', []) + +// This is a generic retry queue for security failures. Each item is expected to expose two functions: retry and cancel. +.factory('securityRetryQueue', ['$q', '$log', function($q, $log) { + var retryQueue = []; + var service = { + // The security service puts its own handler in here! + onItemAddedCallbacks: [], + + hasMore: function() { + return retryQueue.length > 0; + }, + push: function(retryItem) { + retryQueue.push(retryItem); + // Call all the onItemAdded callbacks + angular.forEach(service.onItemAddedCallbacks, function(cb) { + try { + cb(retryItem); + } catch(e) { + $log.error('securityRetryQueue.push(retryItem): callback threw an error' + e); + } + }); + }, + pushRetryFn: function(reason, retryFn) { + // The reason parameter is optional + if ( arguments.length === 1) { + retryFn = reason; + reason = undefined; + } + + // The deferred object that will be resolved or rejected by calling retry or cancel + var deferred = $q.defer(); + var retryItem = { + reason: reason, + retry: function() { + // Wrap the result of the retryFn into a promise if it is not already + $q.when(retryFn()).then(function(value) { + // If it was successful then resolve our deferred + deferred.resolve(value); + }, function(value) { + // Othewise reject it + deferred.reject(value); + }); + }, + cancel: function() { + // Give up on retrying and reject our deferred + deferred.reject(); + } + }; + service.push(retryItem); + return deferred.promise; + }, + retryReason: function() { + return service.hasMore() && retryQueue[0].reason; + }, + cancelAll: function() { + while(service.hasMore()) { + retryQueue.shift().cancel(); + } + }, + retryAll: function() { + while(service.hasMore()) { + retryQueue.shift().retry(); + } + } + }; + return service; +}]); \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/common/security/security.service.js b/src/Umbraco.Web.UI.Client/src/common/security/security.service.js new file mode 100644 index 0000000000..bc6406d744 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/common/security/security.service.js @@ -0,0 +1,114 @@ +// Based loosely around work by Witold Szczerba - https://github.com/witoldsz/angular-http-auth +angular.module('umbraco.security.service', [ + 'umbraco.security.retryQueue', // Keeps track of failed requests that need to be retried once the user logs in + 'umbraco.services' +]) + +.factory('security', ['$http', '$q', '$location', 'securityRetryQueue', 'dialogService', function($http, $q, $location, queue, $dialog) { + + // Redirect to the given url (defaults to '/') + function redirect(url) { + url = url || '/'; + $location.path(url); + } + + // Login form dialog stuff + var loginDialog = null; + + function openLoginDialog() { + if ( loginDialog ) { + throw new Error('Trying to open a dialog that is already open!'); + } + + //loginDialog = $dialog.dialog(); + //loginDialog.open('security/login/form.tpl.html', 'LoginFormController').then(onLoginDialogClose); + } + function closeLoginDialog(success) { + if (loginDialog) { + loginDialog.close(success); + } + } + + function onLoginDialogClose(success) { + loginDialog = null; + if ( success ) { + queue.retryAll(); + } else { + queue.cancelAll(); + redirect(); + } + } + + // Register a handler for when an item is added to the retry queue + queue.onItemAddedCallbacks.push(function(retryItem) { + if ( queue.hasMore() ) { + service.showLogin(); + } + }); + + // The public API of the service + var service = { + + // Get the first reason for needing a login + getLoginReason: function() { + return queue.retryReason(); + }, + + // Show the modal login dialog + showLogin: function() { + openLoginDialog(); + }, + + // Attempt to authenticate a user by the given email and password + login: function(email, password) { + var request = $http.post('/login', {email: email, password: password}); + return request.then(function(response) { + service.currentUser = response.data.user; + if ( service.isAuthenticated() ) { + closeLoginDialog(true); + } + }); + }, + + // Give up trying to login and clear the retry queue + cancelLogin: function() { + closeLoginDialog(false); + redirect(); + }, + + // Logout the current user and redirect + logout: function(redirectTo) { + $http.post('/logout').then(function() { + service.currentUser = null; + redirect(redirectTo); + }); + }, + + // Ask the backend to see if a user is already authenticated - this may be from a previous session. + requestCurrentUser: function() { + if ( service.isAuthenticated() ) { + return $q.when(service.currentUser); + } else { + return $http.get('/current-user').then(function(response) { + service.currentUser = response.data.user; + return service.currentUser; + }); + } + }, + + // Information about the current user + currentUser: null, + + // Is the current user authenticated? + isAuthenticated: function(){ + return !!service.currentUser; + }, + + // Is the current user an adminstrator? + isAdmin: function() { + return !!(service.currentUser && service.currentUser.admin); + } + }; + + return service; +}]); \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/common/services/scriptloader.service.js b/src/Umbraco.Web.UI.Client/src/common/services/scriptloader.service.js new file mode 100644 index 0000000000..6e4f04364b --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/common/services/scriptloader.service.js @@ -0,0 +1,19 @@ +//script loader wrapping around 3rd party loader +angular.module('umbraco.services') +.factory('scriptLoader', function ($q) { + + return { + load: function (pathArray) { + var deferred = $q.defer(); + + yepnope({ + load: pathArray, + complete: function () { + deferred.resolve(true); + } + }); + + return deferred.promise; + } + }; +}); \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/common/services/scripts.js b/src/Umbraco.Web.UI.Client/src/common/services/scripts.js deleted file mode 100644 index e4300f8a80..0000000000 --- a/src/Umbraco.Web.UI.Client/src/common/services/scripts.js +++ /dev/null @@ -1 +0,0 @@ -//script loader wrapping around 3rd party loader \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/common/services/utill.service.js b/src/Umbraco.Web.UI.Client/src/common/services/utill.service.js index d6391f0c9d..741d00d55f 100644 --- a/src/Umbraco.Web.UI.Client/src/common/services/utill.service.js +++ b/src/Umbraco.Web.UI.Client/src/common/services/utill.service.js @@ -12,9 +12,9 @@ function umbImageHelper() { if (!options && !options.imageModel && !options.scope) { throw "The options objet does not contain the required parameters: imageModel, scope"; } - if (options.imageModel.contentTypeAlias.toLowerCase() == "image") { + if (options.imageModel.contentTypeAlias.toLowerCase() === "image") { var imageProp = _.find(options.imageModel.properties, function (item) { - return item.alias == 'umbracoFile'; + return item.alias === 'umbracoFile'; }); var imageVal; //Legacy images will be saved as a string, not an array so we will convert the legacy values @@ -40,7 +40,7 @@ function umbImageHelper() { } var imagePropVal = this.getImagePropertyVaue(options); - if (imagePropVal != "") { + if (imagePropVal !== "") { return this.getThumbnailFromPath(imagePropVal); } return ""; diff --git a/src/Umbraco.Web.UI.Client/src/index.html b/src/Umbraco.Web.UI.Client/src/index.html index d08d84172e..3d8f30376a 100644 --- a/src/Umbraco.Web.UI.Client/src/index.html +++ b/src/Umbraco.Web.UI.Client/src/index.html @@ -146,7 +146,12 @@ + + + + diff --git a/src/Umbraco.Web.UI.Client/src/loader.js b/src/Umbraco.Web.UI.Client/src/loader.js new file mode 100644 index 0000000000..6875f70a4d --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/loader.js @@ -0,0 +1,28 @@ +yepnope({ + + load: [ + 'lib/jquery/jquery-1.8.2.min.js', + 'lib/jquery/jquery.cookie.js', + 'lib/angular/angular.min.js', + 'lib/bootstrap/js/bootstrap.js', + 'lib/underscore/underscore.js', + 'lib/umbraco/Extensions.js', + + 'js/app_dev.js', + + 'js/umbraco.mocks.js', + 'js/umbraco.directives.js', + 'js/umbraco.filters.js', + 'js/umbraco.services.js', + 'js/umbraco.security.js', + 'js/umbraco.controllers.js', + 'js/routes.js' + ], + + complete: function () { + jQuery(document).ready(function () { + angular.bootstrap(document, ['umbraco']); + }); + + } +}); \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/main.js b/src/Umbraco.Web.UI.Client/src/main.js index 72184dcc30..738ea45873 100644 --- a/src/Umbraco.Web.UI.Client/src/main.js +++ b/src/Umbraco.Web.UI.Client/src/main.js @@ -9,6 +9,8 @@ require.config({ angular: '../lib/angular/angular.min', angularResource: '../lib/angular/angular-resource', + app: 'app_dev', + codemirror: '../lib/codemirror/js/lib/codemirror', codemirrorJs: '../lib/codemirror/js/mode/javascript/javascript', codemirrorCss: '../lib/codemirror/js/mode/css/css', @@ -47,7 +49,7 @@ require.config({ require( [ 'angular', - 'app_dev', + 'app', 'jquery', 'jqueryCookie', 'bootstrap', @@ -56,6 +58,7 @@ require( [ 'umbraco.directives', 'umbraco.filters', 'umbraco.services', + 'umbraco.security', 'umbraco.controllers', 'routes' ], function(angular, app, jQuery) { @@ -67,4 +70,5 @@ require( [ jQuery(document).ready(function () { angular.bootstrap(document, ['umbraco']); }); + }); diff --git a/src/Umbraco.Web.UI.Client/src/routes.js b/src/Umbraco.Web.UI.Client/src/routes.js index cbe793390c..92ff159370 100644 --- a/src/Umbraco.Web.UI.Client/src/routes.js +++ b/src/Umbraco.Web.UI.Client/src/routes.js @@ -1,8 +1,4 @@ -define([ - 'app' - ], function(app) { - - return app.config(function ($routeProvider) { +app.config(function ($routeProvider) { $routeProvider .when('/:section', { templateUrl: "views/common/dashboard.html" @@ -27,6 +23,4 @@ define([ }).config(function ($locationProvider) { //$locationProvider.html5Mode(false).hashPrefix('!'); //turn html5 mode off // $locationProvider.html5Mode(true); //turn html5 mode on -}); - -}); +}); \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/views/common/application.controller.js b/src/Umbraco.Web.UI.Client/src/views/common/application.controller.js index 697bcbf35b..84795dcb70 100644 --- a/src/Umbraco.Web.UI.Client/src/views/common/application.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/common/application.controller.js @@ -67,8 +67,30 @@ angular.module('umbraco').controller("SearchController", function ($scope, searc }); -angular.module('umbraco').controller("DashboardController", function ($scope, $routeParams) { +angular.module('umbraco').controller("DashboardController", function ($scope, $routeParams, scriptLoader) { $scope.name = $routeParams.section; + + scriptLoader.load(['http://www.google.com/jsapi']) + .then(function(){ + google.load("maps", "3", + { + callback: function () { + + //Google maps is available and all components are ready to use. + var mapOptions = { + zoom: 8, + center: new google.maps.LatLng(-34.397, 150.644), + mapTypeId: google.maps.MapTypeId.ROADMAP + }; + + var mapDiv = document.getElementById('test_map'); + var map = new google.maps.Map(mapDiv, mapOptions); + + }, + other_params: "sensor=false" + }); + }); + }); diff --git a/src/Umbraco.Web.UI.Client/src/views/common/dashboard.html b/src/Umbraco.Web.UI.Client/src/views/common/dashboard.html index 2ea0896e96..dd2aaa3a5e 100644 --- a/src/Umbraco.Web.UI.Client/src/views/common/dashboard.html +++ b/src/Umbraco.Web.UI.Client/src/views/common/dashboard.html @@ -9,7 +9,7 @@
- +
diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/umbraco/datepicker/datepicker.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/umbraco/datepicker/datepicker.controller.js index 6437f8ea36..40cd27d601 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/umbraco/datepicker/datepicker.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/umbraco/datepicker/datepicker.controller.js @@ -1,10 +1,10 @@ -angular.module("umbraco").controller("Umbraco.Editors.DatepickerController", - function ($scope, notificationsService) { - require( - [ +angular.module("umbraco").controller("Umbraco.Editors.DatepickerController", + function ($scope, notificationsService, scriptLoader) { + + scriptLoader.load([ 'views/propertyeditors/umbraco/datepicker/bootstrap.datepicker.js', 'css!/belle/views/propertyeditors/umbraco/datepicker/bootstrap.datepicker.css' - ], + ]).then( function () { //The Datepicker js and css files are available and all components are ready to use. @@ -19,6 +19,5 @@ angular.module("umbraco").controller("Umbraco.Editors.DatepickerController", // When a date is clicked the date is stored in model.value as a ISO 8601 date $scope.model.value = e.date.toISOString(); }); - } - ); + }); }); diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/umbraco/googlemaps/googlemaps.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/umbraco/googlemaps/googlemaps.controller.js index fdde4d2a7e..ed6ab974f5 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/umbraco/googlemaps/googlemaps.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/umbraco/googlemaps/googlemaps.controller.js @@ -1,75 +1,76 @@ angular.module("umbraco") -.controller("Umbraco.Editors.GoogleMapsController", - function ($rootScope, $scope, notificationsService, dialogService, $log, $timeout) { - require( - [ - 'async!http://maps.google.com/maps/api/js?sensor=false' - ], - function () { - //Google maps is available and all components are ready to use. - var valueArray = $scope.model.value.split(','); - var latLng = new google.maps.LatLng(valueArray[0], valueArray[1]); - - var mapDiv = document.getElementById($scope.model.alias + '_map'); - var mapOptions = { - zoom: $scope.model.config.zoom, - center: latLng, - mapTypeId: google.maps.MapTypeId[$scope.model.config.mapType] - }; - var geocoder = new google.maps.Geocoder(); - var map = new google.maps.Map(mapDiv, mapOptions); +.controller("Umbraco.Editors.GoogleMapsController", + function ($rootScope, $scope, notificationsService, dialogService, scriptLoader, $log, $timeout) { + + scriptLoader.load(['http://www.google.com/jsapi']) + .then(function(){ + google.load("maps", "3", + { + callback: initMap, + other_params: "sensor=false" + }); + }); - var marker = new google.maps.Marker({ - map: map, - position: latLng, - draggable: true + function initMap(){ + //Google maps is available and all components are ready to use. + var valueArray = $scope.model.value.split(','); + var latLng = new google.maps.LatLng(valueArray[0], valueArray[1]); + var mapDiv = document.getElementById($scope.model.alias + '_map'); + var mapOptions = { + zoom: $scope.model.config.zoom, + center: latLng, + mapTypeId: google.maps.MapTypeId[$scope.model.config.mapType] + }; + var geocoder = new google.maps.Geocoder(); + var map = new google.maps.Map(mapDiv, mapOptions); + + var marker = new google.maps.Marker({ + map: map, + position: latLng, + draggable: true + }); + + google.maps.event.addListener(map, 'click', function(event) { + + dialogService.mediaPicker({scope: $scope, callback: function(data){ + var image = data.selection[0].src; + + var latLng = event.latLng; + var marker = new google.maps.Marker({ + map: map, + icon: image, + position: latLng, + draggable: true + }); + + google.maps.event.addListener(marker, "dragend", function(e){ + var newLat = marker.getPosition().lat(); + var newLng = marker.getPosition().lng(); + + codeLatLng(marker.getPosition(), geocoder); + + //set the model value + $scope.model.value = newLat + "," + newLng; + + }); + + }}); + }); + + $('a[data-toggle="tab"]').on('shown', function (e) { + google.maps.event.trigger(map, 'resize'); + }); + } + + function codeLatLng(latLng, geocoder) { + geocoder.geocode({'latLng': latLng}, + function(results, status) { + if (status == google.maps.GeocoderStatus.OK) { + var location = results[0].formatted_address; + $rootScope.$apply(function () { + notificationsService.success("Peter just went to: ", location); + }); + } }); - - google.maps.event.addListener(map, 'click', function(event) { - - dialogService.mediaPicker({scope: $scope, callback: function(data){ - var image = data.selection[0].src; - - var latLng = event.latLng; - var marker = new google.maps.Marker({ - map: map, - icon: image, - position: latLng, - draggable: true - }); - - google.maps.event.addListener(marker, "dragend", function(e){ - var newLat = marker.getPosition().lat(); - var newLng = marker.getPosition().lng(); - - codeLatLng(marker.getPosition()); - - //set the model value - $scope.model.value = newLat + "," + newLng; - - }); - - }}); - }); - - - function codeLatLng(latLng) { - geocoder.geocode({'latLng': latLng}, - function(results, status) { - if (status == google.maps.GeocoderStatus.OK) { - var location = results[0].formatted_address; - $rootScope.$apply(function () { - notificationsService.success("Peter just went to: ", location); - }); - } - }); - } - - //hack to hook into tab switching for map resizing - $('a[data-toggle="tab"]').on('shown', function (e) { - google.maps.event.trigger(map, 'resize'); - }); - - } - ); + } }); \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/umbraco/rte/rte.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/umbraco/rte/rte.controller.js index db87d14c9d..3d330a758f 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/umbraco/rte/rte.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/umbraco/rte/rte.controller.js @@ -1,82 +1,65 @@ angular.module("umbraco") - .controller("Umbraco.Editors.RTEController", - function($rootScope, $scope, dialogService, $log, umbImageHelper){ - require( - [ - 'tinymce' - ], - function (tinymce) { + .controller("Umbraco.Editors.RTEController", + function($rootScope, $scope, dialogService, $log, umbImageHelper, scriptLoader){ - tinymce.DOM.events.domLoaded = true; - tinymce.init({ - selector: "#" + $scope.model.alias + "_rte", - skin: "umbraco", - menubar : false, - statusbar: false, - height: 340, - toolbar: "bold italic | styleselect | alignleft aligncenter alignright | bullist numlist | outdent indent | link image mediapicker", - setup : function(editor) { - - editor.on('blur', function(e) { - $scope.$apply(function() { - //$scope.model.value = e.getBody().innerHTML; - $scope.model.value = editor.getContent(); - }); + scriptLoader.load(["lib/tinymce/tinymce.min.js"]).then(function(){ + + tinymce.DOM.events.domLoaded = true; + tinymce.init({ + selector: "#" + $scope.model.alias + "_rte", + skin: "umbraco", + menubar : false, + statusbar: false, + height: 340, + toolbar: "bold italic | styleselect | alignleft aligncenter alignright | bullist numlist | outdent indent | link image mediapicker", + setup : function(editor) { + + editor.on('blur', function(e) { + $scope.$apply(function() { + //$scope.model.value = e.getBody().innerHTML; + $scope.model.value = editor.getContent(); }); + }); - editor.addButton('mediapicker', { - icon: 'media', - tooltip: 'Media Picker', - onclick: function(){ - dialogService.mediaPicker({scope: $scope, callback: function(data){ - - //really simple example on how to intergrate a service with tinyMCE - $(data.selection).each(function (i, img) { - - var imagePropVal = umbImageHelper.getImagePropertyVaue({imageModel: img, scope: $scope}); - - var data = { - src: (imagePropVal != null && imagePropVal != "") - ? imagePropVal - : "nothing.jpg", - style: 'width: 100px; height: 100px', - id: '__mcenew' - }; - - editor.insertContent(editor.dom.createHTML('img', data)); - var imgElm = editor.dom.get('__mcenew'); - editor.dom.setAttrib(imgElm, 'id', null); - }); - + editor.addButton('mediapicker', { + icon: 'media', + tooltip: 'Media Picker', + onclick: function(){ + dialogService.mediaPicker({scope: $scope, callback: function(data){ + + //really simple example on how to intergrate a service with tinyMCE + $(data.selection).each(function (i, img) { - }}); - } - }); + var imagePropVal = umbImageHelper.getImagePropertyVaue({imageModel: img, scope: $scope}); - - } - }); - - - $scope.openMediaPicker =function(value){ - var d = dialog.mediaPicker({scope: $scope, callback: populate}); - }; - - function bindValue(inst){ - $log.log("woot"); - - $scope.$apply(function() { - $scope.model.value = inst.getBody().innerHTML; - }); - } - - function myHandleEvent(e){ - $log.log(e); - } - - function populate(data){ - $scope.model.value = data.selection; - } + var data = { + src: (imagePropVal != null && imagePropVal != "") + ? imagePropVal + : "nothing.jpg", + style: 'width: 100px; height: 100px', + id: '__mcenew' + }; + + editor.insertContent(editor.dom.createHTML('img', data)); + var imgElm = editor.dom.get('__mcenew'); + editor.dom.setAttrib(imgElm, 'id', null); + }); + + }}); + } + }); + } }); + + + $scope.openMediaPicker =function(value){ + var d = dialog.mediaPicker({scope: $scope, callback: populate}); + }; + + function populate(data){ + $scope.model.value = data.selection; + } + + }); }); \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/umbraco/tags/tags.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/umbraco/tags/tags.controller.js index 08110be59c..5cfbe4149d 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/umbraco/tags/tags.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/umbraco/tags/tags.controller.js @@ -1,11 +1,12 @@ angular.module("umbraco") .controller("Umbraco.Editors.TagsController", - function($rootScope, $scope, $log, tagsResource) { - require( + function($rootScope, $scope, $log, tagsResource, scriptLoader) { + + scriptLoader.load( [ - '/belle/views/propertyeditors/umbraco/tags/bootstrap-tags.custom.js', - 'css!/belle/views/propertyeditors/umbraco/tags/bootstrap-tags.custom.css' - ],function(){ + 'views/propertyeditors/umbraco/tags/bootstrap-tags.custom.js', + 'css!views/propertyeditors/umbraco/tags/bootstrap-tags.custom.css' + ]).then(function(){ // Get data from tagsFactory $scope.tags = tagsResource.getTags("group"); diff --git a/src/Umbraco.Web.UI.Client/test/config/unit.js b/src/Umbraco.Web.UI.Client/test/config/unit.js index 8d58b44b0f..2ed8b63752 100644 --- a/src/Umbraco.Web.UI.Client/test/config/unit.js +++ b/src/Umbraco.Web.UI.Client/test/config/unit.js @@ -9,8 +9,12 @@ files = [ 'lib/jquery/jquery-1.8.2.min.js', 'lib/angular/angular.min.js', 'test/lib/angular/angular-mocks.js', - 'src/app.js', - 'src/common/**/*.js', + 'src/app_dev.js', + 'src/common/directives/*.js', + 'src/common/filters/*.js', + 'src/common/services/*.js', + 'src/common/security/*.js', + 'src/common/mocks/**/*.js', 'src/views/**/*.controller.js', 'test/unit/**/*.spec.js' ]; diff --git a/src/Umbraco.Web.UI.Client/test/unit/app/content/editContentController.spec.js b/src/Umbraco.Web.UI.Client/test/unit/app/content/editContentController.def.js similarity index 100% rename from src/Umbraco.Web.UI.Client/test/unit/app/content/editContentController.spec.js rename to src/Umbraco.Web.UI.Client/test/unit/app/content/editContentController.def.js diff --git a/src/Umbraco.Web.UI.Client/test/unit/common/services/contentFactory.spec.js b/src/Umbraco.Web.UI.Client/test/unit/common/services/contentFactory.spec.js index 3c220e05c7..15b3a73c2b 100644 --- a/src/Umbraco.Web.UI.Client/test/unit/common/services/contentFactory.spec.js +++ b/src/Umbraco.Web.UI.Client/test/unit/common/services/contentFactory.spec.js @@ -11,10 +11,10 @@ describe('content factory tests', function () { describe('global content factory crud', function () { it('should return a content object, given an id', function () { - var doc1 = contentFactory.getContent(1234); - - expect(doc1).toNotBe(undefined); - expect(doc1.id).toBe(1234); + var doc1 = contentFactory.getById(1234).then(function(doc1){ + expect(doc1).toNotBe(undefined); + expect(doc1.id).toBe(1234); + }); }); it('should return a content children collection given an id', function () { diff --git a/src/Umbraco.Web.UI/App_Plugins/GoogleMaps/PropertyEditors/Js/googlemaps.controller.js b/src/Umbraco.Web.UI/App_Plugins/GoogleMaps/PropertyEditors/Js/googlemaps.controller.js index 707e084840..b0ba78a111 100644 --- a/src/Umbraco.Web.UI/App_Plugins/GoogleMaps/PropertyEditors/Js/googlemaps.controller.js +++ b/src/Umbraco.Web.UI/App_Plugins/GoogleMaps/PropertyEditors/Js/googlemaps.controller.js @@ -2,7 +2,7 @@ define(['app', 'angular'], function (app, angular) { angular.module("umbraco") .controller("Umbraco.Editors.GoogleMapsController", - function ($rootScope, $scope, notificationsService, dialogService, $log, $timeout) { + function ($rootScope, $scope, notificationsService, dialogService) { require( [ @@ -10,25 +10,29 @@ angular.module("umbraco") ], function () { - //Google maps is available and all components are ready to use. - //var valueArray = $scope.model.value.split(','); - var latLng = new google.maps.LatLng(-34.397, 150.644); + //Google maps is available and all components are ready to use. + var geocoder = new google.maps.Geocoder(); + var latLng = new google.maps.LatLng(-34.397, 150.644); var mapDiv = document.getElementById($scope.model.alias + '_map'); var mapOptions = { - zoom: 4, + zoom: 2, center: latLng, mapTypeId: google.maps.MapTypeId.ROADMAP }; - var geocoder = new google.maps.Geocoder(); + //lets load the map var map = new google.maps.Map(mapDiv, mapOptions); + + + + //lets add a picture on click google.maps.event.addListener(map, 'click', function(event) { - + + //opens the media dialog dialogService.mediaPicker({scope: $scope, callback: function(data){ - var image = data.selection[0].src; - + var image = data.selection[0].thumbnail; var latLng = event.latLng; var marker = new google.maps.Marker({ map: map, @@ -41,34 +45,39 @@ angular.module("umbraco") var newLat = marker.getPosition().lat(); var newLng = marker.getPosition().lng(); + //find the location codeLatLng(marker.getPosition()); //set the model value $scope.model.value = newLat + "," + newLng; - }); }}); }); - - + + + + function codeLatLng(latLng) { geocoder.geocode({'latLng': latLng}, function(results, status) { if (status == google.maps.GeocoderStatus.OK) { var location = results[0].formatted_address; $rootScope.$apply(function () { - notificationsService.success("Peter just went to: ", location); + + //alert(location); + + notificationsService.success("Pete just went to: ", location); }); } }); } - //hack to hook into tab switching for map resizing + + $('a[data-toggle="tab"]').on('shown', function (e) { google.maps.event.trigger(map, 'resize'); }); - } ); }); diff --git a/src/Umbraco.Web.UI/App_Plugins/SimpleEditor/PropertyEditors/Views/simpleeditor.html b/src/Umbraco.Web.UI/App_Plugins/SimpleEditor/PropertyEditors/Views/simpleeditor.html new file mode 100644 index 0000000000..7224ff2629 --- /dev/null +++ b/src/Umbraco.Web.UI/App_Plugins/SimpleEditor/PropertyEditors/Views/simpleeditor.html @@ -0,0 +1,29 @@ +
+ + +

{{content.name}}

+http://localhost/{{content.name}} +

{{tab.properties[1].value}}

+
+ + diff --git a/src/Umbraco.Web.UI/App_Plugins/SimpleEditor/PropertyEditors/js/simpleeditor.js b/src/Umbraco.Web.UI/App_Plugins/SimpleEditor/PropertyEditors/js/simpleeditor.js new file mode 100644 index 0000000000..e14b592388 --- /dev/null +++ b/src/Umbraco.Web.UI/App_Plugins/SimpleEditor/PropertyEditors/js/simpleeditor.js @@ -0,0 +1,10 @@ +define(['app', 'angular'], function (app, angular) { + +angular.module("umbraco") +.controller("Umbraco.Editors.SimpleEditorController", + function ($rootScope, $scope, notificationsService, dialogService) { + alert("wat"); + }); + + return angular; +}); \ No newline at end of file diff --git a/src/Umbraco.Web.UI/App_Plugins/SimpleEditor/package.manifest b/src/Umbraco.Web.UI/App_Plugins/SimpleEditor/package.manifest new file mode 100644 index 0000000000..5e812ab1a4 --- /dev/null +++ b/src/Umbraco.Web.UI/App_Plugins/SimpleEditor/package.manifest @@ -0,0 +1,19 @@ +{ + propertyEditors: [ + { + id: "0BA0F832-D759-4526-9B3E-95BBFC98F82E", + name: "My Simple Editor", + editor: { + view: "~/App_Plugins/SimpleEditor/PropertyEditors/Views/simpleeditor.html" + } + } + ], + config: { + paths: { + 'simpleController': '~/App_Plugins/SimpleEditor/PropertyEditors/Js/SimpleEditor' + } + }, + init: [ + 'simpleController' + ] +} \ No newline at end of file diff --git a/src/Umbraco.Web.UI/umbraco/Views/Default.cshtml b/src/Umbraco.Web.UI/umbraco/Views/Default.cshtml index 8e684b7729..15f1a0796f 100644 --- a/src/Umbraco.Web.UI/umbraco/Views/Default.cshtml +++ b/src/Umbraco.Web.UI/umbraco/Views/Default.cshtml @@ -63,7 +63,6 @@ -