Compare commits

...

232 Commits

Author SHA1 Message Date
Per Ploug fcaa4ad8d6 JsDocs comments on listviewhelper (U4-7185) 2016-04-14 11:36:24 +02:00
Sebastiaan Janssen bf70e208ad U4-8325 XSLT macro rendering logs too much in Info mode (after upgrade 7.1.4 => 7.4.0) 2016-04-14 09:34:53 +02:00
Shannon Deminick 26f705b129 Merge pull request #1224 from 0xc0dec/dev-v7
Fixed logger context class
2016-04-13 20:18:21 +02:00
Aleksey Fedotov 9e3941e8e1 Fixed logger context class 2016-04-13 22:14:21 +05:00
Stephan 7886b7814d U4-8312 - models generation false error (#1222) 2016-04-13 15:57:27 +02:00
Claus cf7756a96d Merge pull request #1217 from umbraco/temp-U4-8298
Fixes: U4-8298 CacheRefresher authorization logic reversed - traditio…
2016-04-12 13:19:59 +02:00
Claus 20347c1ccd Fixing typo. 2016-04-12 13:17:41 +02:00
Shannon 36255709e6 U4-8297 Custom MembershipProvider search doesn't work in the listview 2016-04-07 18:16:03 +02:00
Shannon 506ed9f866 U4-8286 Add OWIN startup events to the UmbracoDefaultOwinStartup class 2016-04-07 17:51:09 +02:00
Shannon f87bec398d U4-8239 DisableBrowserCacheAttribute causing YSOD when a previous exceptions is thrown before the filter kicks in 2016-04-07 16:44:45 +02:00
Shannon 1e5b6a6a0f Fixes: U4-8298 CacheRefresher authorization logic reversed - traditional load balancing will not work 2016-04-07 15:42:51 +02:00
Warren Buckley a2f8e92098 Merge pull request #1087 from bjarnef/dev-v7-U4-6425
U4-6425 - Maximum property for Related Links
2016-04-07 08:47:01 +01:00
bjarnef 9d5af4ad5e Merge branch 'dev-v7' of git://github.com/umbraco/Umbraco-CMS into dev-v7-U4-6425
Conflicts:
	src/Umbraco.Web.UI.Client/src/views/propertyeditors/relatedlinks/relatedlinks.controller.js
	src/Umbraco.Web.UI.Client/src/views/propertyeditors/relatedlinks/relatedlinks.html
2016-04-06 20:20:22 +02:00
bjarnef ae154885e4 Ensure icon has a value. 2016-04-06 19:52:21 +02:00
bjarnef 2c29e422bc Add icons for internal links. 2016-04-06 19:47:05 +02:00
bjarnef 2d6b8712d5 Limit this to listview, so it doesn't affect other property editors. 2016-04-06 19:44:09 +02:00
Warren Buckley 81aad6fc64 Merge pull request #1205 from bjarnef/dev-v7-U4-8248
U4-8248 - Add tooltip for listview layout + cursor style for listview table row
2016-04-06 15:45:31 +01:00
Claus 58280e7d63 Merge pull request #1209 from greystate/fix-U4-8260
Fix for U4-8260
2016-04-06 11:12:43 +02:00
Sebastiaan Janssen c856795cb7 Fix hilariously wrong copy/pasted TODO comments.. 2016-04-05 08:03:47 +02:00
madden-tom 2d514ac09e Added check for publish permissions to remove option for Publish At a…
U4-287 "Publish at" circumvents "Send for approval/publishing"
2016-04-05 08:01:05 +02:00
Sebastiaan Janssen 8e8b8bdea1 Revert "Removes old obsoleted ping.aspx"
This reverts commit 453efc02a5.

Conflicts:
	src/Umbraco.Web.UI/Umbraco.Web.UI.csproj

U4-8274 '/umbraco/ping.aspx' is missing
2016-04-04 09:20:59 +02:00
Sebastiaan Janssen d8c781f97f Make the file exclusion filter more readable 2016-04-03 13:39:05 +02:00
Sebastiaan Janssen 6502470708 U4-8265 Listview list and listview grid does not handle acceptedFileTypes in same way 2016-04-03 12:08:25 +02:00
Sebastiaan Janssen 680396daab Localize server-side error message for disallowed file uploads 2016-04-03 12:08:23 +02:00
Asbjørn Riis-Knudsen 4e4ea59433 * Only restrict to image files when onlyImages is active* Handle disallowed filetypes as per other upload controls
* Only restrict to image files when onlyImages is active
* Handle disallowed filetypes as per other upload controls
2016-04-02 19:07:35 +02:00
bjarnef 40f7e87e04 Fix issues when using custom font icons in backoffice. 2016-04-02 13:36:55 +02:00
Warren Buckley fbce20d0c3 Merge pull request #1158 from umbraco/temp-U4-8016
Fixes: U4-8016 Pick only images from media
2016-04-01 13:54:37 +01:00
Shannon Deminick 982fa26b7e Merge pull request #1210 from umbraco/temp-U4-8103
U4-8103
2016-03-31 18:26:09 +02:00
Stephan c3055ca43f U4-8103 - fix DisableBrowserCacheAttribute to handle exceptions 2016-03-31 16:37:16 +02:00
Stephan 4cca364511 U4-8103 - refactor YSOD overlay to display inner exceptions 2016-03-31 16:36:36 +02:00
Stephan 9e0ed94d77 Fix typo in lang xml files 2016-03-31 12:56:24 +02:00
Warren Buckley 374147a1a0 Merge pull request #1208 from umbraco/temp-U4-2954
U4-2954 - refresh domain cache when emptying recycle bin
2016-03-31 10:28:31 +01:00
Chriztian Steinmeier 5f0fe69c82 Update links to https 2016-03-30 21:11:29 +02:00
Chriztian Steinmeier e325e06efc Update link to Our on Backoffice sections 2016-03-30 21:10:41 +02:00
Chriztian Steinmeier 5e7db1047b Add the missing 't' 2016-03-30 21:09:14 +02:00
Stephan 61fe0a4a93 U4-2954 - refresh domain cache when emptying recycle bin 2016-03-30 17:56:34 +02:00
Warren Buckley aa1aabef3a Merge pull request #1204 from umbraco/temp-U4-7862
U4-7862 Brackets cause issues in the stylesheet editor
2016-03-30 16:11:15 +01:00
bjarnef d1c865480f Add tooltip for listview layout + cursor style for listview table row. 2016-03-29 23:22:42 +02:00
Claus c427c51053 U4-7862 Brackets cause issues in the stylesheet editor 2016-03-29 14:29:27 +02:00
paulsterling 08070e319a Update number of sites running 2016-03-28 16:46:31 -07:00
Warren Buckley ac2ebc4071 Merge pull request #1193 from umbraco/temp-U4-8220
U4-8220 ModelState and ViewData is not carried through when using the…
2016-03-23 12:10:05 +00:00
Shannon d4c79a0915 Fixes tests, adds more asserts 2016-03-23 11:02:27 +01:00
Shannon 61f9845db0 bumps version 2016-03-23 10:06:53 +01:00
Shannon 43e23829ae updates EnsurePartialViewMacroViewContextFilterAttribute to check for child actions 2016-03-23 10:06:13 +01:00
Stephan 5774ce68c7 GitIgnore Umbraco.Tests/media 2016-03-22 14:37:22 +01:00
Shannon b9af6f631a U4-8220 ModelState and ViewData is not carried through when using the obsolete Content.GetGridHtml method 2016-03-22 11:23:09 +01:00
Shannon cd401f5e37 U4-8216 Hijacked controller actions fail with custom RenderModel subclass due to ModelBinding error 2016-03-21 16:12:34 +01:00
Sebastiaan Janssen 75c2b07ad3 Update ModelsBuilder dependency for the NuGet package 2016-03-18 16:32:05 +01:00
Sebastiaan Janssen 969fe30f6e Merge pull request #1186 from umbraco/temp-U4-8043
U4-8043 - reboot app when PureLive models go wrong
2016-03-18 16:26:52 +01:00
Stephan 0f90d357cf U4-8043 - reboot application when PureLive models go wrong 2016-03-18 16:14:06 +01:00
Stephan d955daab0f Upgrade ModelsBuilder to 3.0.2 2016-03-18 16:13:19 +01:00
Shannon 617b17ca9e puts back in the current node permission check - since we use this for Create 2016-03-18 15:43:14 +01:00
Shannon 9e3d7a1cce updates default pipeline marker stage for the preview middleware, updates MembershipHelper to not throw an exception if the Role manager is disabled. 2016-03-18 11:05:39 +01:00
Warren Buckley f04071d7c7 Merge pull request #1180 from umbraco/temp-U4-8165
U4-8165 Ensure browsers are not caching service requests
2016-03-18 09:53:12 +00:00
Shannon Deminick 2cce9395da Merge pull request #1181 from mittonp/dev-v7
French translations for Grid.
2016-03-18 10:15:50 +01:00
Mitton 6ad56863d4 Grid translation - French 2016-03-18 06:15:37 +02:00
Mitton 2703fa7ea2 Grid translation - French 2016-03-18 06:12:44 +02:00
Shannon b3c6654d41 bumps version 2016-03-17 17:31:36 +01:00
Shannon 0071651621 fixes keyboard shortcut after refactor 2016-03-17 16:36:13 +01:00
Shannon Deminick 4dbc27f1fe Merge pull request #1178 from bjarnef/dev-U4-8163
U4-8163 - Don't set dirty on form for examine dashboard search
2016-03-17 11:31:36 +01:00
Shannon 3f8bbc2f02 Merge branch 'pynej-view-save-restore-cursor' into dev-v7 2016-03-17 11:29:29 +01:00
Shannon 999be9c578 Merge branch 'view-save-restore-cursor' of https://github.com/pynej/Umbraco-CMS into pynej-view-save-restore-cursor 2016-03-17 11:26:09 +01:00
Claus b36b1693dd Fixes broken regex. 2016-03-17 10:33:04 +01:00
Simon Busborg 99b2192ab7 Fixes U4-8181 It is not possible to scroll in an overlay in Chrome 49 on a Retina Mac
By removing animated -half-second fadeIn it resolves the issue where it's not possible to scroll in dialogs on a retina screen ¯\_(ツ)_/¯
2016-03-17 09:58:57 +01:00
Shannon 5230f55f44 moves attribute 2016-03-16 14:52:40 +01:00
Shannon f93fee28dd U4-8165 Ensure browsers are not caching service requests 2016-03-16 14:51:04 +01:00
Shannon Deminick fc7cfea4ad Merge pull request #1179 from umbraco/temp-U4-8175
U4-8175 - fix PropertyType.PropertyGroupId inconsistencies
2016-03-16 14:18:03 +01:00
Stephan bc5f651c64 U4-8154 - bugfix test 2016-03-16 13:46:51 +01:00
Stephan ecdca378c6 U4-8175 - fix PropertyType.PropertyGroupId inconsistencies 2016-03-16 13:41:58 +01:00
Stephan 4628c1f858 U4-8154 - bugfix test 2016-03-16 13:16:56 +01:00
Shannon Deminick 5af4d02f44 Merge pull request #1177 from umbraco/temp-U4-7109
U4-7109 - could not change language in Culture and Hostnames
2016-03-16 10:48:35 +01:00
Shannon 2f9b526465 Only apply preview auth if Umbraco is fully configured 2016-03-16 10:41:33 +01:00
Stephan 800e02bccf Bugfix model mapper for PropertyTypeDisplay 2016-03-16 10:19:06 +01:00
Shannon Deminick 693b0dba24 Merge pull request #1161 from umbraco/temp-U4-4219
U4-4219 Can't Preview protected pages
2016-03-16 10:18:06 +01:00
Stephan 2004f6a51e U4-8154 - bugfix 2016-03-16 10:10:31 +01:00
Claus f650b6238c Merge branch 'arknu-U4-8026' into dev-v7 2016-03-16 07:57:59 +01:00
Claus 7c179a7868 U4-8026 Fixes up unit tests 2016-03-16 07:56:41 +01:00
bjarnef 7a7e0edfa7 Don't set dirty on form for examine dashboard search 2016-03-15 23:59:11 +01:00
bjarnef 69adec1d68 Merge branch 'dev-v7' of https://github.com/bjarnef/Umbraco-CMS into dev-v7 2016-03-15 20:23:58 +01:00
Stephan 0cf6548f86 U4-7109 - could not change language in Culture and Hostnames 2016-03-15 17:26:05 +01:00
Sebastiaan Janssen 111ee66b60 Update ModelsBuilder dependency for the NuGet package 2016-03-15 17:15:39 +01:00
Stephan fedcd6f970 Merge pull request #1176 from umbraco/temp-U4-8168
U4-8168 Cannot re-order/move locked property types - such as the lock…
2016-03-15 16:29:57 +01:00
Stephan 8e82ff5450 Merge pull request #1173 from umbraco/temp-U4-8012
U4-8012 Generic properties tab disappears on the edit Member Type win…
2016-03-15 16:24:21 +01:00
Stephan 81459c3659 Merge pull request #1174 from umbraco/temp-U4-8065
U4-8065 Inherited from is empty - reverts 10617d1bd52bdac57534a7d7b8…
2016-03-15 16:08:26 +01:00
Rune Hem Strand 8907c9855b Merge pull request #1172 from umbraco/temp-U4-7185
Temp u4 7185
2016-03-15 16:02:47 +01:00
Stephan e1bf30ec26 Merge pull request #1175 from umbraco/temp-U4-8106
U4-8106 Content type inheritance can be broken by compositions
2016-03-15 15:53:37 +01:00
Shannon 6bb9c5b81c U4-8168 Cannot re-order/move locked property types - such as the locked/system member type properties 2016-03-15 15:43:21 +01:00
Shannon 6aafbfb245 U4-8106 Content type inheritance can be broken by compositions 2016-03-15 15:25:05 +01:00
Shannon d5fe8c11c8 U4-8065 Inherited from is empty - reverts 10617d1bd5, turns out this is why we needed that property value 2016-03-15 15:08:53 +01:00
Shannon 3fdb122e91 U4-8012 Generic properties tab disappears on the edit Member Type window after upgrade to 7.4 2016-03-15 14:44:03 +01:00
Shannon Deminick 710dda164f Merge pull request #1166 from umbraco/temp-U4-7708
U4-7708 Using a RTE Macro Partial Form (SurfaceController) & Doctype …
2016-03-15 13:57:27 +01:00
Claus 07d0d82bd1 Merge branch 'U4-8026' of git://github.com/arknu/Umbraco-CMS into arknu-U4-8026 2016-03-15 13:47:10 +01:00
Claus 91eb3ea59e Merge pull request #1152 from AndyButland/u4-7888
Fixed U4-7888 - Cannot change default template for document type
2016-03-15 13:43:07 +01:00
Rune Strand 096f1b6ff9 add selected state to umbFolderGrid 2016-03-15 13:18:48 +01:00
Rune Strand f24c0d3e7a Update umbBreadcrumb to use custom controller 2016-03-15 13:18:48 +01:00
Rune Hem Strand 104338c817 A little bit of foldergrid+ 2016-03-15 13:18:48 +01:00
Mads Rasmussen 568f098445 umbOverlay first draft 2016-03-15 13:18:48 +01:00
Mads Rasmussen f46d595f00 fix example on umbStickyBar 2016-03-15 13:18:48 +01:00
Mads Rasmussen 46826ad590 add docs for umbPagination 2016-03-15 13:18:48 +01:00
Mads Rasmussen a8bd34b77e add docs for umbMediaGrid 2016-03-15 13:18:48 +01:00
Mads Rasmussen 40774cfff2 rename umbContentGrid controller 2016-03-15 13:18:48 +01:00
Mads Rasmussen 5dde898205 change controller name on umbGenerateAlias 2016-03-15 13:18:48 +01:00
Mads Rasmussen 249287e101 fix umbKeyboardShortcutsOverview example 2016-03-15 13:18:48 +01:00
Mads Rasmussen 3e458e2ba6 add documentation for umbEmptyState 2016-03-15 13:18:48 +01:00
Mads Rasmussen 4f293a8be1 fix umbTooltip example 2016-03-15 13:18:48 +01:00
Mads Rasmussen 3b9d9ab8c4 change umbChildSelector controller name 2016-03-15 13:18:48 +01:00
Mads Rasmussen 83f875dadd fix umbConfirmAction example 2016-03-15 13:18:48 +01:00
Mads Rasmussen 89df81d3df update umbButtonGroup example to match newest code 2016-03-15 13:18:48 +01:00
Mads Rasmussen 2e4ee42c90 fix small issue with umbButton example 2016-03-15 13:18:48 +01:00
Mads Rasmussen a03858a726 fix examples in umbEditorHeader 2016-03-15 13:18:48 +01:00
Mads Rasmussen 253174d4b3 umbEditorSubHeader: move some example pieces to other directive examples to make it less overwhelming 2016-03-15 13:18:48 +01:00
Mads Rasmussen 947889fae6 update umbFooterContent directives example with a form element 2016-03-15 13:18:48 +01:00
Mads Rasmussen 7ee0b582dd update umbEditorFooter example with a form element 2016-03-15 13:18:48 +01:00
Mads Rasmussen 7bec4efc60 update umbEditorView with a better example 2016-03-15 13:18:48 +01:00
Mads Rasmussen 571d8086c8 update umbContentGrid docs to match latest directive changes 2016-03-15 13:18:48 +01:00
Rune Strand 8abeefe6bb Fix merge conflict 2016-03-15 13:18:48 +01:00
Mads Rasmussen 0aaf3eea02 added documentation for umbChildSelector 2016-03-15 13:18:48 +01:00
Mads Rasmussen 8fc84f9b09 added documentation to umbLockedField 2016-03-15 13:18:48 +01:00
Mads Rasmussen 493b98a771 added documentation to umbGenerateAlias 2016-03-15 13:18:48 +01:00
Mads Rasmussen 114a9b4d33 added documentation for umbFolderGrid 2016-03-15 13:18:48 +01:00
Mads Rasmussen 824b1e7c08 added documentation for umbContentGrid 2016-03-15 13:18:48 +01:00
Mads Rasmussen dfa9b297db added documentation for umbStickyBar 2016-03-15 13:18:48 +01:00
Mads Rasmussen adceb24651 added documentation for umbConfirmAction 2016-03-15 13:18:48 +01:00
Mads Rasmussen c7f1a1419a added documentation for umbTooltip 2016-03-15 13:18:48 +01:00
Mads Rasmussen 8878b5e21c added documentation for umbButtonGroup 2016-03-15 13:18:48 +01:00
Mads Rasmussen 6ebb1d1b4b added documentation for umbButton 2016-03-15 13:18:48 +01:00
Mads Rasmussen 583cd2d1e9 added documentation for sub header directives 2016-03-15 13:18:48 +01:00
Mads Rasmussen 86c6b01e73 added documentation for editor directives 2016-03-15 13:18:48 +01:00
Mads Rasmussen 1170e222e3 added umbBreadcrumbs documentation - first draft 2016-03-15 13:18:48 +01:00
Mads Rasmussen fe004db7d5 added umbLoadIndicator documentation - first draft 2016-03-15 13:18:48 +01:00
Mads Rasmussen 9e75ffb332 added umbKeyboardShortcutsOverview documentation - first draft 2016-03-15 13:18:48 +01:00
Mads Rasmussen d0bb6b7aa4 fix broken directives overview + set marker on deprecated directives 2016-03-15 13:18:48 +01:00
Claus c306f94a6a Merge pull request #1154 from pynej/fix-stylesheet-tree-sync
Fix for issue causing the entire stylesheets tree to reload when …
2016-03-15 12:46:59 +01:00
Claus 11b2ec89fd Merge pull request #1167 from umbraco/temp-U4-8154
U4-8154 - bugfix Sql query expressions parsing
2016-03-15 12:36:52 +01:00
Claus 89596f00f1 Merge pull request #1151 from arknu/icon-transparency
Fix transparency for image icons in the tray
2016-03-15 09:54:36 +01:00
Claus 4fa6e70e72 Merge pull request #1140 from jamescoxhead/U4-7746
U4-7746 - use flat icon in partial views tree
2016-03-15 09:22:18 +01:00
Warren Buckley a5a0a84d46 Merge pull request #1163 from umbraco/temp-U4-7767
U4-7767 List View Filter needs debounce - many requests to handler me…
2016-03-14 16:12:19 +00:00
Warren Buckley 839431e6fa Merge pull request #1170 from umbraco/temp-U4-8157
U4-8157 Right-click on root node returns console error when it doesn'…
2016-03-14 14:28:39 +00:00
Stephan 5369a6fc56 Upgrade ModelsBuilder to 3.0.1 2016-03-14 13:37:49 +01:00
Claus 8a078e258f U4-8157 Right-click on root node returns console error when it doesn't has any actions
Ensured we don't use throw to stop the program flow if no menuUrl is defined on the node. It is a likely scenario that some root node don't have right click actions so its better to handle this.
2016-03-14 12:15:15 +01:00
Sebastiaan Janssen fb42574c34 Revert "U4-5334 Richtext editor inserts extra p - tags to html output" - apparently it does just as much harm as it does good
This reverts commit 9ad3b6a337.
2016-03-12 21:02:05 +01:00
Sebastiaan Janssen 9ad3b6a337 U4-5334 Richtext editor inserts extra p - tags to html output
#U4-5334 Fixed
2016-03-12 12:58:53 +01:00
Jeremy Pyne 91da14b0c6 Second fix for partial views. 2016-03-11 14:56:55 -05:00
Jeremy Pyne f361e286ed This minor fix will restore the editors cursor in CoreArea editor boxes when they save the item. There is a check included to prevent this behavior is the server level code changes the file for some reason as then the cursor location could act unpredictably, so instead we just let it reset to the beginning of the file. 2016-03-11 14:44:21 -05:00
Stephan 65b16fbfe5 U4-8154 - bugfix Sql query expressions parsing 2016-03-11 14:18:08 +01:00
Stephan 6ad2853bce Merge pull request #1165 from umbraco/temp-U4-7949
U4-7949 The task runner has completed YSOD when using the Umbraco Pac…
2016-03-10 18:29:08 +01:00
Shannon e60e4e52fc U4-7708 Using a RTE Macro Partial Form (SurfaceController) & Doctype Hijack Controller causes problem with submissions 2016-03-10 18:00:14 +01:00
Sebastiaan Janssen b2407eab98 Merge pull request #1107 from bjarnef/dev-v7-tinymce-font-icons
Change icons for richtext editor config
2016-03-10 17:47:46 +01:00
Shannon 778c7a836b Merge branch 'dev-v7' of https://github.com/umbraco/Umbraco-CMS into dev-v7 2016-03-10 15:52:43 +01:00
Shannon 11f9cdead0 U4-6366 Issue assigning member roles on MemberService.Saved event 2016-03-10 15:52:34 +01:00
Sebastiaan Janssen a1076d5443 Merge pull request #1160 from umbraco/temp-U4-6438
U4-6438 - fix dynamic extension methods when type loading goes bad
2016-03-10 15:49:15 +01:00
Shannon 4a11bf68f3 U4-7949 The task runner has completed YSOD when using the Umbraco Package installer 2016-03-10 15:23:52 +01:00
Sebastiaan Janssen fa64e73a43 Merge pull request #1164 from umbraco/temp-U4-5797
U4-5797 - fix PublishedContentType cache refresh for compositions
2016-03-10 14:04:46 +01:00
Stephan adf3e2dfe0 U4-5797 - fix PublishedContentType cache refresh for compositions 2016-03-10 13:59:50 +01:00
Shannon c4c86cf5ce U4-7767 List View Filter needs debounce - many requests to handler method 2016-03-10 13:02:20 +01:00
Sebastiaan Janssen 479aba8e1d Fixes unit test.. in the correct branch this time 2016-03-10 11:47:51 +01:00
Sebastiaan Janssen effe7c1669 Fixes unit test 2016-03-10 11:20:44 +01:00
Shannon 0c474e2aba U4-7670 True/false fields on Macro Picker don't save their setting nor read existing setting. - another null check required. 2016-03-10 10:06:20 +01:00
Shannon Deminick 4f5b34cdfe Merge pull request #1162 from pynej/codemirror-js-error
Fix for missing doc.setLine() function breaking code mirror editor.
2016-03-10 09:58:16 +01:00
Warren Buckley 0cb7f220ea Merge pull request #1149 from umbraco/temp-U4-4700
U4-4700 List View Doesn't Respect User Permissions
2016-03-10 08:52:38 +00:00
Jeremy Pyne 0995b2cb5a Fix for missing doc.setLine() function breaking code mirror editor. 2016-03-09 14:55:15 -05:00
Shannon af1fe425a2 udpates ext method to specify an explicit marker stage, updates UmbracoDefaultOwinStartup to be more flexible with the methods to override. 2016-03-09 19:37:37 +01:00
Shannon 22385d40db U4-4219 Can't Preview protected pages 2016-03-09 17:35:50 +01:00
Stephan 1b37475144 U4-6438 - fix dynamic extension methods when type loading goes bad 2016-03-09 15:55:41 +01:00
Mads Rasmussen 87667ec2d1 Fixes: U4-8016 Pick only images from media 2016-03-08 20:56:24 +01:00
Shannon be0bacd895 Ensures all angular views are cache busted so browser cache is not an issue after upgrading. 2016-03-08 17:23:54 +01:00
Shannon a2564bd0c3 ensures that requests are only made for ids that haven't already been queried. 2016-03-08 16:18:33 +01:00
Shannon 402a5c9d56 fixes bool check 2016-03-08 15:57:59 +01:00
Shannon 2a2f22c7d9 fixes js null issue with boolean.controller 2016-03-08 15:53:45 +01:00
Shannon 372a768dca U4-4700 List view doesn't respect user permissions - makes the buttons show/hide based on the selected items instead of the current item. 2016-03-08 15:53:22 +01:00
Sebastiaan Janssen f6e48243a6 U4-8088 NuGet upgrade of UmbracoCms pacakage doesn't add ModelsBuilder keys to web.config 2016-03-08 13:39:35 +01:00
Warren Buckley 94ea677ec0 Merge pull request #1146 from umbraco/temp-U4-7641
U4-7641 - enable content type copy
2016-03-08 09:38:16 +00:00
Sebastiaan Janssen 55e7159f7d Forgot to remove them from the nuspec files 2016-03-08 10:35:57 +01:00
Sebastiaan Janssen 390a94e323 U4-8054 Issue with NuGet Uninstall.ps1 (running on updates)
#U4-8054 Fixed
2016-03-08 10:34:19 +01:00
Shannon Deminick 19fb920aa1 Merge pull request #1150 from umbraco/temp-U4-7823
U4-7823 - stop flooding the log with errors getting media 0
2016-03-07 17:58:49 +01:00
Shannon Deminick f35e1604ca Merge pull request #1141 from umbraco/temp-U4-8030
U4-8030 - Fix RenderModelBinder issue with surface
2016-03-07 17:53:31 +01:00
Shannon b9765c3bec fixes RenderModelBinder to use base implementation,adds unit tests 2016-03-07 17:52:28 +01:00
Shannon d5a57c505c adds RenderModelBinderTests 2016-03-07 16:53:57 +01:00
Shannon 5f365241a8 updates RenderModelBinder to simply check for IPublishedContent or IRenderModel 2016-03-07 16:29:40 +01:00
Shannon 9c121f0044 Fixes RenderModelBinder to inherit from DefaultModelBinder and use the default logic if the model in the route values is not IRenderModel 2016-03-07 16:26:30 +01:00
Shannon f13bc07ddc Merge branch 'dev-v7' of https://github.com/umbraco/Umbraco-CMS into dev-v7 2016-03-07 15:13:41 +01:00
Shannon a707d23692 Allows for specifying explicit product names by overriding the property in MigrationStartupHander 2016-03-07 15:13:31 +01:00
Simon Busborg 0929b7d42c Fixes U4-8113 Styling for property labels affect package meta data labels 2016-03-07 14:55:18 +01:00
Simon Busborg 35a9272b68 Fixes U4-8036 Umbraco.MultiNodeTreePicker checkbox doesn't appear after selecting something from list view 2016-03-07 14:45:30 +01:00
Shannon Deminick 112453a032 Merge pull request #1144 from umbraco/temp-U4-8077
U4-8077 - ensure product name in migration event handlers
2016-03-07 14:09:29 +01:00
Simon Busborg bba7367ba6 Fixes U4-8058 Labels are changed to block-level elements 2016-03-07 12:12:35 +01:00
bjarnef 367073e02e Merge remote-tracking branch 'refs/remotes/umbraco/dev-v7' into dev-v7 2016-03-03 17:58:36 +01:00
Jeremy Pyne 83e679ba5e Fix for issue causing the entire stylesheets tree to reload when selecting a item. 2016-03-02 16:00:33 -05:00
AndyButland 1a4322eb48 Fix issue with database field check that led to default template for content type not being set 2016-02-29 09:04:50 +00:00
Asbjørn Riis-Knudsen 4d950fb4d4 Fix transparency for image icons in the tray 2016-02-28 17:40:58 +01:00
Stephan 0d191fb8bd U4-7823 - stop flooding the log with errors getting media 0 2016-02-26 11:35:24 +01:00
Warren Buckley c7a3efadb1 Remove debug JSON in the view 2016-02-25 21:09:12 +00:00
Warren Buckley 956425dfbf Now updated so the create button hides if we do not have the Create permission 'C' 2016-02-25 21:06:25 +00:00
Warren Buckley c616354522 After reading src code for contentEditorHelper.configureContentEditorButtons it makes the same assumption that if the publish action 'U' is present then the user can also unpublish aka 'Z' 2016-02-25 20:49:56 +00:00
Stephan 36246b96d4 Fix bug with permissions cache refresh 2016-02-25 17:39:34 +01:00
Stephan 7d8791ec86 Fix ActionButtonsResolver (need review) 2016-02-25 17:05:44 +01:00
Stephan f349a9ae3e U4-7641 - bugfix 2016-02-25 16:26:20 +01:00
Warren Buckley 2719e2c231 WIP - ListView that grabs the current nodes permission from the editorState & use a neater object to return to the view rather than the lovely Magic String CHARs. Need help understanding that I don't get all the permissions to be expected 2016-02-25 15:19:42 +00:00
Stephan dafde545b0 U4-7641 - bugfix + implement for media types 2016-02-25 16:02:04 +01:00
Stephan 610538261e U4-7641 - enable content type copy 2016-02-25 15:26:03 +01:00
Asbjørn Riis-Knudsen e8f84cfec0 Add parens around all BinaryExpressions to make sure that errors such U4-8026 do not happen 2016-02-25 12:20:58 +01:00
Stephan 9f7b82e20f U4-8077 - ensure product name in migration event handlers 2016-02-24 13:59:15 +01:00
Stephan 04b3532e9d U4-8030 - Fix RenderModelBinder issue with surface 2016-02-22 18:38:06 +01:00
James Coxhead 01bcd3b623 Changed partial views icon to icon-article 2016-02-22 16:15:31 +00:00
James Coxhead 64fd95bd22 Updated tree icons for partial views and partial view macros 2016-02-22 16:13:25 +00:00
bjarnef 6effcdfce9 Merge remote-tracking branch 'refs/remotes/umbraco/dev-v7' into dev-v7 2016-02-15 18:52:30 +01:00
bjarnef 5176b68935 Merge remote-tracking branch 'refs/remotes/umbraco/dev-v7' into dev-v7-tinymce-font-icons 2016-02-08 15:07:36 +01:00
bjarnef 0bfc5f1272 Change icons in tinymce config 2016-02-08 15:07:16 +01:00
bjarnef 39c18d4201 Merge branch 'dev-v7' of https://github.com/bjarnef/Umbraco-CMS into dev-v7 2016-02-05 15:54:48 +01:00
bjarnef 66ea8ae604 Merge remote-tracking branch 'refs/remotes/umbraco/dev-v7' into dev-v7 2016-02-05 14:55:53 +01:00
bjarnef 6fc794ca2e Merge branch 'dev-v7' of https://github.com/bjarnef/Umbraco-CMS into dev-v7 2016-02-03 14:42:14 +01:00
bjarnef 4bcee1df71 Change property to maximum 2016-02-03 02:42:47 +01:00
bjarnef 8e2716d300 Merge remote-tracking branch 'refs/remotes/umbraco/dev-v7' into dev-v7-U4-6425 2016-02-03 02:29:30 +01:00
bjarnef b8c7b09d25 Update styles + adjust sort of table row 2016-02-03 02:29:21 +01:00
bjarnef 741057b7d6 Merge remote-tracking branch 'refs/remotes/umbraco/dev-v7' into dev-v7-U4-6425 2016-02-02 15:21:34 +01:00
bjarnef 769b74afef Merge remote-tracking branch 'refs/remotes/umbraco/dev-v7' into dev-v7-U4-6425 2016-02-02 15:15:49 +01:00
bjarnef 6d4364a8b9 Modify sortable table row 2016-02-02 03:47:10 +01:00
bjarnef efb7bc7689 Merge remote-tracking branch 'refs/remotes/umbraco/dev-v7' into dev-v7-U4-6425 2016-02-01 22:02:42 +01:00
bjarnef 6536286ffa Merge remote-tracking branch 'refs/remotes/umbraco/dev-v7' into dev-v7-U4-6425 2016-02-01 13:34:22 +01:00
bjarnef 6f07898979 Max config adjustments 2016-02-01 02:13:05 +01:00
bjarnef 7cf4c33d15 Fix max number in config and other adjustments 2016-02-01 01:52:51 +01:00
bjarnef d75ebed53d Merge remote-tracking branch 'refs/remotes/umbraco/dev-v7' into dev-v7-U4-6425 2016-01-31 14:57:08 +01:00
bjarnef 3136981043 Merge remote-tracking branch 'refs/remotes/umbraco/dev-v7' into dev-v7-U4-6425 2016-01-28 20:05:33 +01:00
bjarnef 893ca14859 Config for max items 2016-01-28 01:01:06 +01:00
bjarnef df958223b0 Merge remote-tracking branch 'refs/remotes/umbraco/dev-v7' into dev-v7 2016-01-26 18:17:00 +01:00
bjarnef 1217d9f0b3 Merge remote-tracking branch 'refs/remotes/umbraco/dev-v7' into dev-v7 2016-01-24 23:25:29 +01:00
bjarnef 1301897f39 Merge remote-tracking branch 'refs/remotes/umbraco/dev-v7' into dev-v7 2016-01-22 22:02:51 +01:00
bjarnef 6d34fe416d Merge remote-tracking branch 'refs/remotes/umbraco/dev-v7' into dev-v7 2016-01-21 20:38:52 +01:00
bjarnef a884ece8b1 Merge remote-tracking branch 'refs/remotes/umbraco/dev-v7' into dev-v7 2016-01-21 18:15:50 +01:00
bjarnef 0ffcc9b889 Merge remote-tracking branch 'refs/remotes/umbraco/dev-v7' into dev-v7 2016-01-20 19:21:58 +01:00
bjarnef ee3131b63d Merge remote-tracking branch 'refs/remotes/umbraco/dev-v7' into dev-v7 2016-01-19 21:03:42 +01:00
bjarnef 4fd7182388 Merge remote-tracking branch 'refs/remotes/umbraco/dev-v7' into dev-v7 2016-01-19 20:56:36 +01:00
213 changed files with 6126 additions and 1739 deletions
+135 -134
View File
@@ -1,134 +1,135 @@
*.obj
*.pdb
*.user
*.aps
*.pch
*.vspscc
.DS_Store
._.DS_Store
[Bb]in
[Db]ebug*/
obj/
[Rr]elease*/
_ReSharper*/
_NCrunch_*/
*.ncrunchsolution
*.ncrunchsolution.user
*.ncrunchproject
*.crunchsolution.cache
[Tt]est[Rr]esult*
[Bb]uild[Ll]og.*
*.[Pp]ublish.xml
*.suo
[sS]ource
[sS]andbox
umbraco.config
*.vs10x
App_Data/TEMP/*
[Uu]mbraco/[Pp]resentation/[Uu]mbraco/[Pp]lugins/*
[Uu]mbraco/[Pp]resentation/[Uu]ser[Cc]ontrols/*
[Uu]mbraco/[Pp]resentation/[Ss]cripts/*
[Uu]mbraco/[Pp]resentation/[Ff]onts/*
[Uu]mbraco/[Pp]resentation/[Cc]ss/*
src/Umbraco.Web.UI/[Cc]ss/*
src/Umbraco.Web.UI/App_Code/*
src/Umbraco.Web.UI/App_Data/*
src/Umbraco.Tests/App_Data/*
src/Umbraco.Web.UI/[Mm]edia/*
src/Umbraco.Web.UI/[Mm]aster[Pp]ages/*
src/Umbraco.Web.UI/[Mm]acro[Ss]cripts/*
!src/Umbraco.Web.UI/[Mm]acro[Ss]cripts/[Ww]eb.[Cc]onfig
src/Umbraco.Web.UI/[Xx]slt/*
src/Umbraco.Web.UI/[Ii]mages/*
src/Umbraco.Web.UI/[Ss]cripts/*
src/Umbraco.Web.UI/Web.*.config.transformed
umbraco/presentation/umbraco/plugins/uComponents/uComponentsInstaller.ascx
umbraco/presentation/packages/uComponents/MultiNodePicker/CustomTreeService.asmx
_BuildOutput/*
*.ncrunchsolution
build/UmbracoCms.AllBinaries*zip
build/UmbracoCms.WebPI*zip
build/UmbracoCms*zip
build/UmbracoExamine.PDF*zip
build/*.nupkg
src/Umbraco.Tests/config/applications.config
src/Umbraco.Tests/config/trees.config
src/Umbraco.Web.UI/web.config
*.orig
src/Umbraco.Tests/config/404handlers.config
src/Umbraco.Web.UI/[Vv]iews/*.cshtml
src/Umbraco.Web.UI/[Vv]iews/*.vbhtml
src/Umbraco.Tests/[Cc]onfig/umbracoSettings.config
src/Umbraco.Web.UI/[Vv]iews/*
src/packages/
src/packages/repositories.config
src/Umbraco.Web.UI/[Ww]eb.config
*.transformed
webpihash.txt
node_modules
src/Umbraco.Web.UI/[Uu]mbraco/[Ll]ib/*
src/Umbraco.Web.UI/[Uu]mbraco/[Jj]s/umbraco.*
src/Umbraco.Web.UI/[Uu]mbraco/[Jj]s/routes.js
src/Umbraco.Web.UI/[Uu]mbraco/[Jj]s/app.dev.js
src/Umbraco.Web.UI/[Uu]mbraco/[Jj]s/loader.js
src/Umbraco.Web.UI/[Uu]mbraco/[Jj]s/loader.dev.js
src/Umbraco.Web.UI/[Uu]mbraco/[Jj]s/main.js
src/Umbraco.Web.UI/[Uu]mbraco/[Jj]s/app.js
src/Umbraco.Web.UI/[Uu]mbraco/[Jj]s/tuning.panel.js
src/Umbraco.Web.UI/[Uu]mbraco/[Jj]s/tuning.palettes.js
src/Umbraco.Web.UI/[Uu]mbraco/[Jj]s/tuning.loader.js
src/Umbraco.Web.UI/[Uu]mbraco/[Jj]s/tuning.front.js
src/Umbraco.Web.UI/[Uu]mbraco/[Jj]s/tuning.config.js
src/Umbraco.Web.UI/[Uu]mbraco/[Vv]iews/
src/Umbraco.Web.UI/[Uu]mbraco/[Vv]iews/**/*.js
src/Umbraco.Web.UI/[Uu]mbraco/[Vv]iews/**/*.css
src/Umbraco.Web.UI/[Uu]mbraco/[Vv]iews/**/*.html
src/Umbraco.Web.UI/[Uu]mbraco/[Aa]ssets/*
src/Umbraco.Web.UI.Client/[Bb]uild/*
src/Umbraco.Web.UI.Client/[Bb]uild/[Bb]elle/
src/Umbraco.Web.UI/[Uu]ser[Cc]ontrols/
build/_BuildOutput/
src/Umbraco.Web.UI.Client/src/[Ll]ess/*.css
tools/NDepend/
src/Umbraco.Web.UI/App_Plugins/*
src/*.psess
src/*.vspx
src/Umbraco.Web.UI/[Uu]mbraco/[Jj]s/routes.js.*
NDependOut/*
*.ndproj
QueryResult.htm
*.ndproj
src/Umbraco.Web.UI/[Uu]mbraco/[Aa]ssets/*
src/Umbraco.Web.UI/[Uu]mbraco/[Ll]ib/*
src/Umbraco.Web.UI/[Uu]mbraco/[Vv]iews/**/*.html
src/Umbraco.Web.UI/[Uu]mbraco/[Vv]iews/**/*.js
src/Umbraco.Web.UI/[Cc]onfig/appSettings.config
src/Umbraco.Web.UI/[Cc]onfig/connectionStrings.config
src/Umbraco.Web.UI/umbraco/plugins/*
src/Umbraco.Web.UI/umbraco/js/init.js
build/ApiDocs/*
build/ApiDocs/Output/*
src/Umbraco.Web.UI.Client/bower_components/*
/src/Umbraco.Web.UI/Umbraco/preview
#Ignore Rule for output of generated documentation files from Grunt docserve
src/Umbraco.Web.UI.Client/docs/api
src/*.boltdata/
/src/Umbraco.Web.UI/Umbraco/Js/canvasdesigner.loader.js
/src/Umbraco.Web.UI/Umbraco/Js/canvasdesigner.palettes.js
/src/Umbraco.Web.UI/Umbraco/Js/canvasdesigner.panel.js
/src/Umbraco.Web.UI/Umbraco/Js/canvasdesigner.config.js
/src/Umbraco.Web.UI/Umbraco/Js/canvasdesigner.front.js
src/umbraco.sln.ide/*
build/UmbracoCms.*/
src/.vs/
src/Umbraco.Web.UI/umbraco/js/install.loader.js
*.obj
*.pdb
*.user
*.aps
*.pch
*.vspscc
.DS_Store
._.DS_Store
[Bb]in
[Db]ebug*/
obj/
[Rr]elease*/
_ReSharper*/
_NCrunch_*/
*.ncrunchsolution
*.ncrunchsolution.user
*.ncrunchproject
*.crunchsolution.cache
[Tt]est[Rr]esult*
[Bb]uild[Ll]og.*
*.[Pp]ublish.xml
*.suo
[sS]ource
[sS]andbox
umbraco.config
*.vs10x
App_Data/TEMP/*
[Uu]mbraco/[Pp]resentation/[Uu]mbraco/[Pp]lugins/*
[Uu]mbraco/[Pp]resentation/[Uu]ser[Cc]ontrols/*
[Uu]mbraco/[Pp]resentation/[Ss]cripts/*
[Uu]mbraco/[Pp]resentation/[Ff]onts/*
[Uu]mbraco/[Pp]resentation/[Cc]ss/*
src/Umbraco.Web.UI/[Cc]ss/*
src/Umbraco.Web.UI/App_Code/*
src/Umbraco.Web.UI/App_Data/*
src/Umbraco.Tests/App_Data/*
src/Umbraco.Web.UI/[Mm]edia/*
src/Umbraco.Web.UI/[Mm]aster[Pp]ages/*
src/Umbraco.Web.UI/[Mm]acro[Ss]cripts/*
!src/Umbraco.Web.UI/[Mm]acro[Ss]cripts/[Ww]eb.[Cc]onfig
src/Umbraco.Web.UI/[Xx]slt/*
src/Umbraco.Web.UI/[Ii]mages/*
src/Umbraco.Web.UI/[Ss]cripts/*
src/Umbraco.Web.UI/Web.*.config.transformed
umbraco/presentation/umbraco/plugins/uComponents/uComponentsInstaller.ascx
umbraco/presentation/packages/uComponents/MultiNodePicker/CustomTreeService.asmx
_BuildOutput/*
*.ncrunchsolution
build/UmbracoCms.AllBinaries*zip
build/UmbracoCms.WebPI*zip
build/UmbracoCms*zip
build/UmbracoExamine.PDF*zip
build/*.nupkg
src/Umbraco.Tests/config/applications.config
src/Umbraco.Tests/config/trees.config
src/Umbraco.Web.UI/web.config
*.orig
src/Umbraco.Tests/config/404handlers.config
src/Umbraco.Web.UI/[Vv]iews/*.cshtml
src/Umbraco.Web.UI/[Vv]iews/*.vbhtml
src/Umbraco.Tests/[Cc]onfig/umbracoSettings.config
src/Umbraco.Web.UI/[Vv]iews/*
src/packages/
src/packages/repositories.config
src/Umbraco.Web.UI/[Ww]eb.config
*.transformed
webpihash.txt
node_modules
src/Umbraco.Web.UI/[Uu]mbraco/[Ll]ib/*
src/Umbraco.Web.UI/[Uu]mbraco/[Jj]s/umbraco.*
src/Umbraco.Web.UI/[Uu]mbraco/[Jj]s/routes.js
src/Umbraco.Web.UI/[Uu]mbraco/[Jj]s/app.dev.js
src/Umbraco.Web.UI/[Uu]mbraco/[Jj]s/loader.js
src/Umbraco.Web.UI/[Uu]mbraco/[Jj]s/loader.dev.js
src/Umbraco.Web.UI/[Uu]mbraco/[Jj]s/main.js
src/Umbraco.Web.UI/[Uu]mbraco/[Jj]s/app.js
src/Umbraco.Web.UI/[Uu]mbraco/[Jj]s/tuning.panel.js
src/Umbraco.Web.UI/[Uu]mbraco/[Jj]s/tuning.palettes.js
src/Umbraco.Web.UI/[Uu]mbraco/[Jj]s/tuning.loader.js
src/Umbraco.Web.UI/[Uu]mbraco/[Jj]s/tuning.front.js
src/Umbraco.Web.UI/[Uu]mbraco/[Jj]s/tuning.config.js
src/Umbraco.Web.UI/[Uu]mbraco/[Vv]iews/
src/Umbraco.Web.UI/[Uu]mbraco/[Vv]iews/**/*.js
src/Umbraco.Web.UI/[Uu]mbraco/[Vv]iews/**/*.css
src/Umbraco.Web.UI/[Uu]mbraco/[Vv]iews/**/*.html
src/Umbraco.Web.UI/[Uu]mbraco/[Aa]ssets/*
src/Umbraco.Web.UI.Client/[Bb]uild/*
src/Umbraco.Web.UI.Client/[Bb]uild/[Bb]elle/
src/Umbraco.Web.UI/[Uu]ser[Cc]ontrols/
build/_BuildOutput/
src/Umbraco.Web.UI.Client/src/[Ll]ess/*.css
tools/NDepend/
src/Umbraco.Web.UI/App_Plugins/*
src/*.psess
src/*.vspx
src/Umbraco.Web.UI/[Uu]mbraco/[Jj]s/routes.js.*
NDependOut/*
*.ndproj
QueryResult.htm
*.ndproj
src/Umbraco.Web.UI/[Uu]mbraco/[Aa]ssets/*
src/Umbraco.Web.UI/[Uu]mbraco/[Ll]ib/*
src/Umbraco.Web.UI/[Uu]mbraco/[Vv]iews/**/*.html
src/Umbraco.Web.UI/[Uu]mbraco/[Vv]iews/**/*.js
src/Umbraco.Web.UI/[Cc]onfig/appSettings.config
src/Umbraco.Web.UI/[Cc]onfig/connectionStrings.config
src/Umbraco.Web.UI/umbraco/plugins/*
src/Umbraco.Web.UI/umbraco/js/init.js
build/ApiDocs/*
build/ApiDocs/Output/*
src/Umbraco.Web.UI.Client/bower_components/*
/src/Umbraco.Web.UI/Umbraco/preview
#Ignore Rule for output of generated documentation files from Grunt docserve
src/Umbraco.Web.UI.Client/docs/api
src/*.boltdata/
/src/Umbraco.Web.UI/Umbraco/Js/canvasdesigner.loader.js
/src/Umbraco.Web.UI/Umbraco/Js/canvasdesigner.palettes.js
/src/Umbraco.Web.UI/Umbraco/Js/canvasdesigner.panel.js
/src/Umbraco.Web.UI/Umbraco/Js/canvasdesigner.config.js
/src/Umbraco.Web.UI/Umbraco/Js/canvasdesigner.front.js
src/umbraco.sln.ide/*
build/UmbracoCms.*/
src/.vs/
src/Umbraco.Web.UI/umbraco/js/install.loader.js
src/Umbraco.Tests/media
+2 -2
View File
@@ -13,11 +13,11 @@ If you're interested in making changes to Belle make sure to read the [Belle Rea
## Umbraco - the simple, flexible and friendly ASP.NET CMS ##
**More than 177,000 sites trust Umbraco**
**More than 350,000 sites trust Umbraco**
For the first time on the Microsoft platform, there is a free user and developer friendly CMS that makes it quick and easy to create websites - or a breeze to build complex web applications. Umbraco has award-winning integration capabilities and supports ASP.NET MVC or Web Forms, including User and Custom Controls, out of the box. It's a developer's dream and your users will love it too.
Used by more than 177,000 active websites including [http://daviscup.com](http://daviscup.com), [http://heinz.com](http://heinz.com), [http://peugeot.com](http://peugeot.com), [http://www.hersheys.com/](http://www.hersheys.com/) and **The Official ASP.NET and IIS.NET website from Microsoft** ([http://asp.net](http://asp.net) / [http://iis.net](http://iis.net)), you can be sure that the technology is proven, stable and scales.
Used by more than 350,000 active websites including [http://daviscup.com](http://daviscup.com), [http://heinz.com](http://heinz.com), [http://peugeot.com](http://peugeot.com), [http://www.hersheys.com/](http://www.hersheys.com/) and **The Official ASP.NET and IIS.NET website from Microsoft** ([http://asp.net](http://asp.net) / [http://iis.net](http://iis.net)), you can be sure that the technology is proven, stable and scales.
To view more examples, please visit [http://umbraco.com/why-umbraco/#caseStudies](http://umbraco.com/why-umbraco/#caseStudies)
-1
View File
@@ -72,7 +72,6 @@
<file src="..\_BuildOutput\WebApp\bin\UmbracoExamine.dll" target="lib\UmbracoExamine.dll" />
<file src="..\_BuildOutput\WebApp\bin\UmbracoExamine.xml" target="lib\UmbracoExamine.xml" />
<file src="tools\install.core.ps1" target="tools\install.ps1" />
<file src="tools\uninstall.core.ps1" target="tools\uninstall.ps1" />
<!-- Added to be able to produce a symbols package -->
<file src="..\_BuildOutput\bin\SQLCE4Umbraco.pdb" target="lib" />
+1 -2
View File
@@ -17,7 +17,7 @@
<dependencies>
<dependency id="UmbracoCms.Core" version="[$version$]" />
<dependency id="Newtonsoft.Json" version="[6.0.8, 9.0.0)" />
<dependency id="Umbraco.ModelsBuilder" version="[3.0.0, 4.0.0)" />
<dependency id="Umbraco.ModelsBuilder" version="[3.0.2, 4.0.0)" />
</dependencies>
</metadata>
<files>
@@ -33,7 +33,6 @@
<file src="..\_BuildOutput\WebApp\umbraco\**" target="UmbracoFiles\umbraco" />
<file src="..\_BuildOutput\WebApp\umbraco_client\**" target="UmbracoFiles\umbraco_client" />
<file src="tools\install.ps1" target="tools\install.ps1" />
<file src="tools\uninstall.ps1" target="tools\uninstall.ps1" />
<file src="tools\Readme.txt" target="tools\Readme.txt" />
<file src="tools\ReadmeUpgrade.txt" target="tools\ReadmeUpgrade.txt" />
<file src="tools\Web.config.install.xdt" target="Content\Web.config.install.xdt" />
@@ -21,6 +21,8 @@
<appSettings xdt:Transform="InsertIfMissing" />
<appSettings>
<add key="owin:appStartup" value="UmbracoDefaultOwinStartup" xdt:Locator="Match(key)" xdt:Transform="InsertIfMissing" />
<add key="Umbraco.ModelsBuilder.Enable" value="false" xdt:Locator="Match(key)" xdt:Transform="InsertIfMissing" />
<add key="Umbraco.ModelsBuilder.ModelsMode" value="Nothing" xdt:Locator="Match(key)" xdt:Transform="InsertIfMissing" />
</appSettings>
<umbracoConfiguration xdt:Transform="InsertIfMissing">
-48
View File
@@ -1,48 +0,0 @@
param($installPath, $toolsPath, $package, $project)
Write-Host "installPath:" "${installPath}"
Write-Host "toolsPath:" "${toolsPath}"
Write-Host " "
if ($project) {
# Create paths and list them
$projectPath = (Get-Item $project.Properties.Item("FullPath").Value).FullName
Write-Host "projectPath:" "${projectPath}"
$backupPath = Join-Path $projectPath "App_Data\NuGetBackup"
Write-Host "backupPath:" "${backupPath}"
$umbracoBinFolder = Join-Path $projectPath "bin"
Write-Host "umbracoBinFolder:" "${umbracoBinFolder}"
# Remove backups
Write-Host "removing backups:" "${backupPath}"
if(Test-Path $backupPath) { Remove-Item -Recurse -Force $backupPath -Confirm:$false }
# Delete files Umbraco ships with
Write-Host "removing dlls:" "${umbracoBinFolder}"
if(Test-Path $umbracoBinFolder\businesslogic.dll) { Remove-Item $umbracoBinFolder\businesslogic.dll -Force -Confirm:$false }
if(Test-Path $umbracoBinFolder\cms.dll) { Remove-Item $umbracoBinFolder\cms.dll -Force -Confirm:$false }
if(Test-Path $umbracoBinFolder\controls.dll) { Remove-Item $umbracoBinFolder\controls.dll -Force -Confirm:$false }
if(Test-Path $umbracoBinFolder\interfaces.dll) { Remove-Item $umbracoBinFolder\interfaces.dll -Force -Confirm:$false }
if(Test-Path $umbracoBinFolder\log4net.dll) { Remove-Item $umbracoBinFolder\log4net.dll -Force -Confirm:$false }
if(Test-Path $umbracoBinFolder\Microsoft.ApplicationBlocks.Data.dll) { Remove-Item $umbracoBinFolder\Microsoft.ApplicationBlocks.Data.dll -Force -Confirm:$false }
if(Test-Path $umbracoBinFolder\SQLCE4Umbraco.dll) { Remove-Item $umbracoBinFolder\SQLCE4Umbraco.dll -Force -Confirm:$false }
if(Test-Path $umbracoBinFolder\System.Data.SqlServerCe.dll) { Remove-Item $umbracoBinFolder\System.Data.SqlServerCe.dll -Force -Confirm:$false }
if(Test-Path $umbracoBinFolder\System.Data.SqlServerCe.Entity.dll) { Remove-Item $umbracoBinFolder\System.Data.SqlServerCe.Entity.dll -Force -Confirm:$false }
if(Test-Path $umbracoBinFolder\TidyNet.dll) { Remove-Item $umbracoBinFolder\TidyNet.dll -Force -Confirm:$false }
if(Test-Path $umbracoBinFolder\umbraco.dll) { Remove-Item $umbracoBinFolder\umbraco.dll -Force -Confirm:$false }
if(Test-Path $umbracoBinFolder\Umbraco.Core.dll) { Remove-Item $umbracoBinFolder\Umbraco.Core.dll -Force -Confirm:$false }
if(Test-Path $umbracoBinFolder\umbraco.DataLayer.dll) { Remove-Item $umbracoBinFolder\umbraco.DataLayer.dll -Force -Confirm:$false }
if(Test-Path $umbracoBinFolder\umbraco.editorControls.dll) { Remove-Item $umbracoBinFolder\umbraco.editorControls.dll -Force -Confirm:$false }
if(Test-Path $umbracoBinFolder\umbraco.MacroEngines.dll) { Remove-Item $umbracoBinFolder\umbraco.MacroEngines.dll -Force -Confirm:$false }
if(Test-Path $umbracoBinFolder\umbraco.providers.dll) { Remove-Item $umbracoBinFolder\umbraco.providers.dll -Force -Confirm:$false }
if(Test-Path $umbracoBinFolder\Umbraco.Web.UI.dll) { Remove-Item $umbracoBinFolder\Umbraco.Web.UI.dll -Force -Confirm:$false }
if(Test-Path $umbracoBinFolder\UmbracoExamine.dll) { Remove-Item $umbracoBinFolder\UmbracoExamine.dll -Force -Confirm:$false }
$amd64Folder = Join-Path $umbracoBinFolder "amd64"
if(Test-Path $amd64Folder) { Remove-Item $amd64Folder -Force -Recurse -Confirm:$false }
$x86Folder = Join-Path $umbracoBinFolder "x86"
if(Test-Path $x86Folder) { Remove-Item $x86Folder -Force -Recurse -Confirm:$false }
}
-39
View File
@@ -1,39 +0,0 @@
param($installPath, $toolsPath, $package, $project)
Write-Host "installPath:" "${installPath}"
Write-Host "toolsPath:" "${toolsPath}"
Write-Host " "
if ($project) {
# Create paths and list them
$projectPath = (Get-Item $project.Properties.Item("FullPath").Value).FullName
Write-Host "projectPath:" "${projectPath}"
$backupPath = Join-Path $projectPath "App_Data\NuGetBackup"
Write-Host "backupPath:" "${backupPath}"
$appBrowsers = Join-Path $projectPath "App_Browsers"
Write-Host "appBrowsers:" "${appBrowsers}"
$appData = Join-Path $projectPath "App_Data"
Write-Host "appData:" "${appData}"
# Remove backups
Write-Host "removing backups:" "${backupPath}"
if(Test-Path $backupPath) { Remove-Item -Recurse -Force $backupPath -Confirm:$false }
# Remove app_data files
Write-Host "removing app_data files:" "${appData}"
if(Test-Path $appData\packages) { Remove-Item $appData\packages -Recurse -Force -Confirm:$false }
Write-Host "removing app_browsers:" "${appBrowsers}"
if(Test-Path $appBrowsers\Form.browser) { Remove-Item $appBrowsers\Form.browser -Force -Confirm:$false }
if(Test-Path $appBrowsers\w3cvalidator.browser) { Remove-Item $appBrowsers\w3cvalidator.browser -Force -Confirm:$false }
# Remove umbraco and umbraco_files
$umbracoFolder = Join-Path $projectPath "Umbraco"
Write-Host "removing umbraco folder:" "${umbracoFolder}"
if(Test-Path $umbracoFolder) { Remove-Item $umbracoFolder -Recurse -Force -Confirm:$false }
$umbracoClientFolder = Join-Path $projectPath "Umbraco_Client"
Write-Host "removing umbraco client folder:" "${umbracoClientFolder}"
if(Test-Path $umbracoClientFolder) { Remove-Item $umbracoClientFolder -Recurse -Force -Confirm:$false }
}
+1 -1
View File
@@ -1,2 +1,2 @@
# Usage: on line 2 put the release version, on line 3 put the version comment (example: beta)
7.4.1
7.4.3
+2 -2
View File
@@ -11,5 +11,5 @@ using System.Resources;
[assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyFileVersion("7.4.1")]
[assembly: AssemblyInformationalVersion("7.4.1")]
[assembly: AssemblyFileVersion("7.4.3")]
[assembly: AssemblyInformationalVersion("7.4.3")]
@@ -6,7 +6,7 @@ namespace Umbraco.Core.Configuration
{
public class UmbracoVersion
{
private static readonly Version Version = new Version("7.4.1");
private static readonly Version Version = new Version("7.4.3");
/// <summary>
/// Gets the current version of Umbraco.
@@ -5,8 +5,10 @@ using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Linq.Expressions;
using System.Text;
using System.Web.Services.Description;
using Umbraco.Core.Cache;
using Umbraco.Core.Logging;
namespace Umbraco.Core.Dynamics
{
@@ -20,6 +22,20 @@ namespace Umbraco.Core.Dynamics
/// </summary>
private static readonly ConcurrentDictionary<Tuple<Type, string, int>, MethodInfo[]> MethodCache = new ConcurrentDictionary<Tuple<Type, string, int>, MethodInfo[]>();
private static IEnumerable<Type> GetTypes(Assembly a)
{
try
{
return TypeFinder.GetTypesWithFormattedException(a);
}
catch (ReflectionTypeLoadException ex)
{
// is this going to flood the log?
LogHelper.Error(typeof (ExtensionMethodFinder), "Failed to get types.", ex);
return Enumerable.Empty<Type>();
}
}
/// <summary>
/// Returns the enumerable of all extension method info's in the app domain = USE SPARINGLY!!!
/// </summary>
@@ -36,7 +52,7 @@ namespace Umbraco.Core.Dynamics
// assemblies that contain extension methods
.Where(a => a.IsDefined(typeof (ExtensionAttribute), false))
// types that contain extension methods
.SelectMany(a => a.GetTypes()
.SelectMany(a => GetTypes(a)
.Where(t => t.IsDefined(typeof (ExtensionAttribute), false) && t.IsSealed && t.IsGenericType == false && t.IsNested == false))
// actual extension methods
.SelectMany(t => t.GetMethods(BindingFlags.Static | BindingFlags.Public)
@@ -45,9 +61,9 @@ namespace Umbraco.Core.Dynamics
.Concat(typeof (Enumerable).GetMethods(BindingFlags.Static | BindingFlags.Public))
//If we don't do this then we'll be scanning all assemblies each time!
.ToArray(),
//only cache for 5 minutes
timeout: TimeSpan.FromMinutes(5),
timeout: TimeSpan.FromMinutes(5),
//each time this is accessed it will be for 5 minutes longer
isSliding:true);
@@ -57,7 +73,7 @@ namespace Umbraco.Core.Dynamics
/// Returns all extension methods found matching the definition
/// </summary>
/// <param name="runtimeCache">
/// The runtime cache is used to temporarily cache all extension methods found in the app domain so that
/// The runtime cache is used to temporarily cache all extension methods found in the app domain so that
/// while we search for individual extension methods, the process will be reasonably 'quick'. We then statically
/// cache the MethodInfo's that we are looking for and then the runtime cache will expire and give back all that memory.
/// </param>
@@ -78,7 +94,7 @@ namespace Umbraco.Core.Dynamics
{
var candidates = GetAllExtensionMethodsInAppDomain(runtimeCache);
// filter by name
// filter by name
var filtr1 = candidates.Where(m => m.Name == name);
// filter by args count
@@ -102,7 +118,7 @@ namespace Umbraco.Core.Dynamics
return filtr3.ToArray();
});
}
private static MethodInfo DetermineMethodFromParams(IEnumerable<MethodInfo> methods, Type genericType, IEnumerable<object> args)
@@ -123,12 +139,12 @@ namespace Umbraco.Core.Dynamics
types = method.GetParameters().Select(pi => pi.ParameterType).Skip(1)
});
//This type comparer will check
//This type comparer will check
var typeComparer = new DelegateEqualityComparer<Type>(
//Checks if the argument type passed in can be assigned from the parameter type in the method. For
//Checks if the argument type passed in can be assigned from the parameter type in the method. For
// example, if the argument type is HtmlHelper<MyModel> but the method parameter type is HtmlHelper then
// it will match because the argument is assignable to that parameter type and will be able to execute
TypeHelper.IsTypeAssignableFrom,
TypeHelper.IsTypeAssignableFrom,
//This will not ever execute but if it does we need to get the hash code of the string because the hash
// code of a type is random
type => type.FullName.GetHashCode());
@@ -159,7 +175,7 @@ namespace Umbraco.Core.Dynamics
.ToArray();
var methods = GetAllExtensionMethods(runtimeCache, thisType, name, args.Length).ToArray();
return DetermineMethodFromParams(methods, genericType, args);
}
}
+63 -24
View File
@@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.ComponentModel;
using Semver;
using Umbraco.Core.Configuration;
using Umbraco.Core.Persistence.Migrations;
namespace Umbraco.Core.Events
@@ -13,23 +14,49 @@ namespace Umbraco.Core.Events
/// </summary>
/// <param name="eventObject"></param>
/// <param name="targetVersion"></param>
/// <param name="productName"></param>
/// <param name="canCancel"></param>
/// <param name="configuredVersion"></param>
public MigrationEventArgs(IList<IMigration> eventObject, SemVersion configuredVersion, SemVersion targetVersion, bool canCancel)
: base(eventObject, canCancel)
{
ConfiguredSemVersion = configuredVersion;
TargetSemVersion = targetVersion;
}
public MigrationEventArgs(IList<IMigration> eventObject, SemVersion configuredVersion, SemVersion targetVersion, string productName, bool canCancel)
: this(eventObject, null, configuredVersion, targetVersion, productName, canCancel)
{ }
[Obsolete("Use constructor accepting UmbracoVersion instances instead")]
/// <summary>
/// Constructor accepting multiple migrations that are used in the migration runner
/// </summary>
/// <param name="eventObject"></param>
/// <param name="targetVersion"></param>
/// <param name="canCancel"></param>
/// <param name="configuredVersion"></param>
[Obsolete("Use constructor accepting a product name instead.")]
[EditorBrowsable(EditorBrowsableState.Never)]
public MigrationEventArgs(IList<IMigration> eventObject, SemVersion configuredVersion, SemVersion targetVersion, bool canCancel)
: this(eventObject, null, configuredVersion, targetVersion, GlobalSettings.UmbracoMigrationName, canCancel)
{ }
[Obsolete("Use constructor accepting SemVersion instances and a product name instead.")]
[EditorBrowsable(EditorBrowsableState.Never)]
public MigrationEventArgs(IList<IMigration> eventObject, Version configuredVersion, Version targetVersion, bool canCancel)
: base(eventObject, canCancel)
{
ConfiguredSemVersion = new SemVersion(configuredVersion);
TargetSemVersion = new SemVersion(targetVersion);
}
: this(eventObject, null, new SemVersion(configuredVersion), new SemVersion(targetVersion), GlobalSettings.UmbracoMigrationName, canCancel)
{ }
/// <summary>
/// Constructor accepting multiple migrations that are used in the migration runner
/// </summary>
/// <param name="eventObject"></param>
/// <param name="migrationContext"></param>
/// <param name="targetVersion"></param>
/// <param name="productName"></param>
/// <param name="canCancel"></param>
/// <param name="configuredVersion"></param>
internal MigrationEventArgs(IList<IMigration> eventObject, MigrationContext migrationContext, SemVersion configuredVersion, SemVersion targetVersion, string productName, bool canCancel)
: base(eventObject, canCancel)
{
MigrationContext = migrationContext;
ConfiguredSemVersion = configuredVersion;
TargetSemVersion = targetVersion;
ProductName = productName;
}
/// <summary>
/// Constructor accepting multiple migrations that are used in the migration runner
@@ -39,12 +66,15 @@ namespace Umbraco.Core.Events
/// <param name="targetVersion"></param>
/// <param name="canCancel"></param>
/// <param name="configuredVersion"></param>
[Obsolete("Use constructor accepting a product name instead.")]
[EditorBrowsable(EditorBrowsableState.Never)]
internal MigrationEventArgs(IList<IMigration> eventObject, MigrationContext migrationContext, SemVersion configuredVersion, SemVersion targetVersion, bool canCancel)
: base(eventObject, canCancel)
{
MigrationContext = migrationContext;
ConfiguredSemVersion = configuredVersion;
TargetSemVersion = targetVersion;
ProductName = GlobalSettings.UmbracoMigrationName;
}
/// <summary>
@@ -53,21 +83,28 @@ namespace Umbraco.Core.Events
/// <param name="eventObject"></param>
/// <param name="configuredVersion"></param>
/// <param name="targetVersion"></param>
public MigrationEventArgs(IList<IMigration> eventObject, SemVersion configuredVersion, SemVersion targetVersion)
: base(eventObject)
{
ConfiguredSemVersion = configuredVersion;
TargetSemVersion = targetVersion;
}
/// <param name="productName"></param>
public MigrationEventArgs(IList<IMigration> eventObject, SemVersion configuredVersion, SemVersion targetVersion, string productName)
: this(eventObject, null, configuredVersion, targetVersion, productName, false)
{ }
[Obsolete("Use constructor accepting UmbracoVersion instances instead")]
/// <summary>
/// Constructor accepting multiple migrations that are used in the migration runner
/// </summary>
/// <param name="eventObject"></param>
/// <param name="configuredVersion"></param>
/// <param name="targetVersion"></param>
[Obsolete("Use constructor accepting a product name instead.")]
[EditorBrowsable(EditorBrowsableState.Never)]
public MigrationEventArgs(IList<IMigration> eventObject, SemVersion configuredVersion, SemVersion targetVersion)
: this(eventObject, null, configuredVersion, targetVersion, GlobalSettings.UmbracoMigrationName, false)
{ }
[Obsolete("Use constructor accepting SemVersion instances and a product name instead.")]
[EditorBrowsable(EditorBrowsableState.Never)]
public MigrationEventArgs(IList<IMigration> eventObject, Version configuredVersion, Version targetVersion)
: base(eventObject)
{
ConfiguredSemVersion = new SemVersion(configuredVersion);
TargetSemVersion = new SemVersion(targetVersion);
}
: this(eventObject, null, new SemVersion(configuredVersion), new SemVersion(targetVersion), GlobalSettings.UmbracoMigrationName, false)
{ }
/// <summary>
/// Returns all migrations that were used in the migration runner
@@ -95,6 +132,8 @@ namespace Umbraco.Core.Events
public SemVersion TargetSemVersion { get; private set; }
public string ProductName { get; private set; }
internal MigrationContext MigrationContext { get; private set; }
}
}
+3 -6
View File
@@ -487,11 +487,8 @@ namespace Umbraco.Core.Models
var oldPropertyGroup = PropertyGroups.FirstOrDefault(x =>
x.PropertyTypes.Any(y => y.Alias == propertyTypeAlias));
// reset PropertyGroupId, which will be re-evaluated when the content type
// is saved - what is important is group.PropertyTypes - see code in
// ContentTypeBaseRepository.PersistUpdatedBaseContentType
propertyType.PropertyGroupId = new Lazy<int>(() => default(int));
propertyType.ResetDirtyProperties(); // PropertyGroupId must not be dirty
// set new group
propertyType.PropertyGroupId = newPropertyGroup == null ? null : new Lazy<int>(() => newPropertyGroup.Id, false);
// remove from old group, if any - add to new group, if any
if (oldPropertyGroup != null)
@@ -540,7 +537,7 @@ namespace Umbraco.Core.Models
// re-assign the group's properties to no group
foreach (var property in group.PropertyTypes)
{
property.PropertyGroupId = new Lazy<int>(() => 0);
property.PropertyGroupId = null;
_propertyTypes.Add(property);
}
+7 -1
View File
@@ -7,6 +7,12 @@ namespace Umbraco.Core.Models
/// </summary
public interface IMediaType : IContentTypeComposition
{
/// <summary>
/// Creates a deep clone of the current entity with its identity/alias and it's property identities reset
/// </summary>
/// <param name="newAlias"></param>
/// <returns></returns>
IMediaType DeepCloneWithResetIdentities(string newAlias);
}
}
+25
View File
@@ -38,5 +38,30 @@ namespace Umbraco.Core.Models
: base(parent, alias)
{
}
/// <summary>
/// Creates a deep clone of the current entity with its identity/alias and it's property identities reset
/// </summary>
/// <returns></returns>
public IMediaType DeepCloneWithResetIdentities(string alias)
{
var clone = (MediaType)DeepClone();
clone.Alias = alias;
clone.Key = Guid.Empty;
foreach (var propertyGroup in clone.PropertyGroups)
{
propertyGroup.ResetIdentity();
propertyGroup.ResetDirtyProperties(false);
}
foreach (var propertyType in clone.PropertyTypes)
{
propertyType.ResetIdentity();
propertyType.ResetDirtyProperties(false);
}
clone.ResetIdentity();
clone.ResetDirtyProperties(false);
return clone;
}
}
}
+2 -1
View File
@@ -221,8 +221,9 @@ namespace Umbraco.Core.Models
}
/// <summary>
/// Gets or Sets the PropertyGroup's Id for which this PropertyType belongs
/// Gets or sets the identifier of the PropertyGroup this PropertyType belongs to.
/// </summary>
/// <remarks>For generic properties, the value is <c>null</c>.</remarks>
[DataMember]
internal Lazy<int> PropertyGroupId
{
@@ -114,10 +114,25 @@ namespace Umbraco.Core.Models.PublishedContent
internal static void ClearContentType(int id)
{
Logging.LogHelper.Debug<PublishedContentType>("Clear content type w/id {0}.", () => id);
// requires a predicate because the key does not contain the ID
// faster than key strings comparisons anyway
// we don't support "get all" at the moment - so, cheating
var all = ApplicationContext.Current.ApplicationCache.StaticCache.GetCacheItemsByKeySearch<PublishedContentType>("PublishedContentType_").ToArray();
// the one we want to clear
var clr = all.FirstOrDefault(x => x.Id == id);
if (clr == null) return;
// those that have that one in their composition aliases
// note: CompositionAliases contains all recursive aliases
var oth = all.Where(x => x.CompositionAliases.InvariantContains(clr.Alias)).Select(x => x.Id);
// merge ids
var ids = oth.Concat(new[] { clr.Id }).ToArray();
// clear them all at once
// we don't support "clear many at once" at the moment - so, cheating
ApplicationContext.Current.ApplicationCache.StaticCache.ClearCacheObjectTypes<PublishedContentType>(
(key, value) => value.Id == id);
(key, value) => ids.Contains(value.Id));
}
internal static void ClearDataType(int id)
@@ -164,7 +164,7 @@ namespace Umbraco.Core.Persistence.Factories
Name = typeDto.Name,
SortOrder = typeDto.SortOrder,
ValidationRegExp = typeDto.ValidationRegExp,
PropertyGroupId = new Lazy<int>(() => default(int)),
PropertyGroupId = null,
CreateDate = dto.CreateDate,
UpdateDate = dto.CreateDate
};
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Text;
@@ -27,18 +28,21 @@ namespace Umbraco.Core.Persistence.Migrations
private readonly IMigration[] _migrations;
[Obsolete("Use the ctor that specifies all dependencies instead")]
[EditorBrowsable(EditorBrowsableState.Never)]
public MigrationRunner(Version currentVersion, Version targetVersion, string productName)
: this(LoggerResolver.Current.Logger, currentVersion, targetVersion, productName)
{
}
[Obsolete("Use the ctor that specifies all dependencies instead")]
[EditorBrowsable(EditorBrowsableState.Never)]
public MigrationRunner(ILogger logger, Version currentVersion, Version targetVersion, string productName)
: this(logger, currentVersion, targetVersion, productName, null)
{
}
[Obsolete("Use the ctor that specifies all dependencies instead")]
[EditorBrowsable(EditorBrowsableState.Never)]
public MigrationRunner(ILogger logger, Version currentVersion, Version targetVersion, string productName, params IMigration[] migrations)
: this(ApplicationContext.Current.Services.MigrationEntryService, logger, new SemVersion(currentVersion), new SemVersion(targetVersion), productName, migrations)
{
@@ -92,7 +96,7 @@ namespace Umbraco.Core.Persistence.Migrations
: OrderedDowngradeMigrations(foundMigrations).ToList();
if (Migrating.IsRaisedEventCancelled(new MigrationEventArgs(migrations, _currentVersion, _targetVersion, true), this))
if (Migrating.IsRaisedEventCancelled(new MigrationEventArgs(migrations, _currentVersion, _targetVersion, _productName, true), this))
{
_logger.Warn<MigrationRunner>("Migration was cancelled by an event");
return false;
@@ -121,7 +125,7 @@ namespace Umbraco.Core.Persistence.Migrations
throw;
}
Migrated.RaiseEvent(new MigrationEventArgs(migrations, migrationContext, _currentVersion, _targetVersion, false), this);
Migrated.RaiseEvent(new MigrationEventArgs(migrations, migrationContext, _currentVersion, _targetVersion, _productName, false), this);
return true;
}
@@ -128,6 +128,34 @@ namespace Umbraco.Core.Persistence.Querying
right = Visit(b.Right);
}
}
else if (operand == "=")
{
// deal with (x == true|false) - most common
var constRight = b.Right as ConstantExpression;
if (constRight != null && constRight.Type == typeof (bool))
return ((bool) constRight.Value) ? VisitNotNot(b.Left) : VisitNot(b.Left);
right = Visit(b.Right);
// deal with (true|false == x) - why not
var constLeft = b.Left as ConstantExpression;
if (constLeft != null && constLeft.Type == typeof (bool))
return ((bool) constLeft.Value) ? VisitNotNot(b.Right) : VisitNot(b.Right);
left = Visit(b.Left);
}
else if (operand == "<>")
{
// deal with (x != true|false) - most common
var constRight = b.Right as ConstantExpression;
if (constRight != null && constRight.Type == typeof(bool))
return ((bool) constRight.Value) ? VisitNot(b.Left) : VisitNotNot(b.Left);
right = Visit(b.Right);
// deal with (true|false != x) - why not
var constLeft = b.Left as ConstantExpression;
if (constLeft != null && constLeft.Type == typeof(bool))
return ((bool) constLeft.Value) ? VisitNot(b.Right) : VisitNotNot(b.Right);
left = Visit(b.Left);
}
else
{
left = Visit(b.Left);
@@ -152,7 +180,7 @@ namespace Umbraco.Core.Persistence.Querying
case "COALESCE":
return string.Format("{0}({1},{2})", operand, left, right);
default:
return left + " " + operand + " " + right;
return "(" + left + " " + operand + " " + right + ")";
}
}
@@ -231,25 +259,47 @@ namespace Umbraco.Core.Persistence.Querying
switch (u.NodeType)
{
case ExpressionType.Not:
var o = Visit(u.Operand);
//use a Not equal operator instead of <> since we don't know that <> works in all sql servers
switch (u.Operand.NodeType)
{
case ExpressionType.MemberAccess:
//In this case it wil be a false property , i.e. x => !Trashed
SqlParameters.Add(true);
return string.Format("NOT ({0} = @0)", o);
default:
//In this case it could be anything else, such as: x => !x.Path.StartsWith("-20")
return string.Format("NOT ({0})", o);
}
return VisitNot(u.Operand);
default:
return Visit(u.Operand);
}
}
private string VisitNot(Expression exp)
{
var o = Visit(exp);
// use a "NOT (...)" syntax instead of "<>" since we don't know whether "<>" works in all sql servers
// also, x.StartsWith(...) translates to "x LIKE '...%'" which we cannot "<>" and have to "NOT (...")
switch (exp.NodeType)
{
case ExpressionType.MemberAccess:
// false property , i.e. x => !Trashed
SqlParameters.Add(true);
return string.Format("NOT ({0} = @{1})", o, SqlParameters.Count - 1);
default:
// could be anything else, such as: x => !x.Path.StartsWith("-20")
return "NOT (" + o + ")";
}
}
private string VisitNotNot(Expression exp)
{
var o = Visit(exp);
switch (exp.NodeType)
{
case ExpressionType.MemberAccess:
// true property, i.e. x => Trashed
SqlParameters.Add(true);
return string.Format("({0} = @{1})", o, SqlParameters.Count - 1);
default:
// could be anything else, such as: x => x.Path.StartsWith("-20")
return o;
}
}
protected virtual string VisitNewArray(NewArrayExpression na)
{
@@ -914,7 +914,7 @@ AND umbracoNode.id <> @id",
//check for default templates
bool? isDefaultTemplate = Convert.ToBoolean(ct.dtIsDefault);
int? templateId = ct.dtTemplateId;
if (currDefaultTemplate == -1 && isDefaultTemplate.HasValue && templateId.HasValue)
if (currDefaultTemplate == -1 && isDefaultTemplate.HasValue && isDefaultTemplate.Value && templateId.HasValue)
{
currDefaultTemplate = templateId.Value;
}
@@ -1212,5 +1212,19 @@ AND umbracoNode.id <> @id",
{
return PerformExists(id);
}
public string GetUniqueAlias(string alias)
{
// alias is unique accross ALL content types!
var aliasColumn = SqlSyntax.GetQuotedColumnName("alias");
var aliases = Database.Fetch<string>(@"SELECT cmsContentType." + aliasColumn + @" FROM cmsContentType
INNER JOIN umbracoNode ON cmsContentType.nodeId = umbracoNode.id
WHERE cmsContentType." + aliasColumn + @" LIKE @pattern",
new { pattern = alias + "%", objectType = NodeObjectTypeId });
var i = 1;
string test;
while (aliases.Contains(test = alias + i)) i++;
return test;
}
}
}
@@ -32,5 +32,13 @@ namespace Umbraco.Core.Persistence.Repositories
/// </param>
/// <returns></returns>
IEnumerable<string> GetAllContentTypeAliases(params Guid[] objectTypes);
/// <summary>
/// Derives a unique alias from an existing alias.
/// </summary>
/// <param name="alias">The original alias.</param>
/// <returns>The original alias with a number appended to it, so that it is unique.</returns>
/// /// <remarks>Unique accross all content, media and member types.</remarks>
string GetUniqueAlias(string alias);
}
}
@@ -15,5 +15,13 @@ namespace Umbraco.Core.Persistence.Repositories
IEnumerable<IMediaType> GetByQuery(IQuery<PropertyType> query);
IEnumerable<MoveEventInfo<IMediaType>> Move(IMediaType toMove, EntityContainer container);
/// <summary>
/// Derives a unique alias from an existing alias.
/// </summary>
/// <param name="alias">The original alias.</param>
/// <returns>The original alias with a number appended to it, so that it is unique.</returns>
/// <remarks>Unique accross all content, media and member types.</remarks>
string GetUniqueAlias(string alias);
}
}
@@ -103,10 +103,18 @@ namespace Umbraco.Core.Security
var backOfficeIdentity = http.User.Identity as UmbracoBackOfficeIdentity;
if (backOfficeIdentity != null) return backOfficeIdentity;
//Check if there's more than one identity assigned and see if it's a UmbracoBackOfficeIdentity and use that
var claimsPrincipal = http.User as ClaimsPrincipal;
if (claimsPrincipal != null)
{
backOfficeIdentity = claimsPrincipal.Identities.OfType<UmbracoBackOfficeIdentity>().FirstOrDefault();
if (backOfficeIdentity != null) return backOfficeIdentity;
}
//Otherwise convert to a UmbracoBackOfficeIdentity if it's auth'd and has the back office session
var claimsIdentity = http.User.Identity as ClaimsIdentity;
if (claimsIdentity != null && claimsIdentity.IsAuthenticated)
{
{
try
{
return UmbracoBackOfficeIdentity.FromClaimsIdentity(claimsIdentity);
@@ -794,7 +794,7 @@ namespace Umbraco.Core.Services
//TODO: This needs to change, if we are deleting a content type, we should just delete the data,
// this method will recursively go lookup every content item, check if any of it's descendants are
// of a different type, move them to the recycle bin, then permanently delete the content items.
// of a different type, move them to the recycle bin, then permanently delete the content items.
// The main problem with this is that for every content item being deleted, events are raised...
// which we need for many things like keeping caches in sync, but we can surely do this MUCH better.
@@ -1067,6 +1067,92 @@ namespace Umbraco.Core.Services
new OperationStatus<MoveOperationStatusType>(MoveOperationStatusType.Success, evtMsgs));
}
public Attempt<OperationStatus<IMediaType, MoveOperationStatusType>> CopyMediaType(IMediaType toCopy, int containerId)
{
var evtMsgs = EventMessagesFactory.Get();
IMediaType copy;
var uow = UowProvider.GetUnitOfWork();
using (var containerRepository = RepositoryFactory.CreateEntityContainerRepository(uow, Constants.ObjectTypes.MediaTypeContainerGuid))
using (var repository = RepositoryFactory.CreateMediaTypeRepository(uow))
{
try
{
if (containerId > 0)
{
var container = containerRepository.Get(containerId);
if (container == null)
throw new DataOperationException<MoveOperationStatusType>(MoveOperationStatusType.FailedParentNotFound);
}
var alias = repository.GetUniqueAlias(toCopy.Alias);
copy = toCopy.DeepCloneWithResetIdentities(alias);
copy.Name = copy.Name + " (copy)"; // might not be unique
// if it has a parent, and the parent is a content type, unplug composition
// all other compositions remain in place in the copied content type
if (copy.ParentId > 0)
{
var parent = repository.Get(copy.ParentId);
if (parent != null)
copy.RemoveContentType(parent.Alias);
}
copy.ParentId = containerId;
repository.AddOrUpdate(copy);
}
catch (DataOperationException<MoveOperationStatusType> ex)
{
return Attempt.Fail(new OperationStatus<IMediaType, MoveOperationStatusType>(null, ex.Operation, evtMsgs));
}
uow.Commit();
}
return Attempt.Succeed(new OperationStatus<IMediaType, MoveOperationStatusType>(copy, MoveOperationStatusType.Success, evtMsgs));
}
public Attempt<OperationStatus<IContentType, MoveOperationStatusType>> CopyContentType(IContentType toCopy, int containerId)
{
var evtMsgs = EventMessagesFactory.Get();
IContentType copy;
var uow = UowProvider.GetUnitOfWork();
using (var containerRepository = RepositoryFactory.CreateEntityContainerRepository(uow, Constants.ObjectTypes.DocumentTypeContainerGuid))
using (var repository = RepositoryFactory.CreateContentTypeRepository(uow))
{
try
{
if (containerId > 0)
{
var container = containerRepository.Get(containerId);
if (container == null)
throw new DataOperationException<MoveOperationStatusType>(MoveOperationStatusType.FailedParentNotFound);
}
var alias = repository.GetUniqueAlias(toCopy.Alias);
copy = toCopy.DeepCloneWithResetIdentities(alias);
copy.Name = copy.Name + " (copy)"; // might not be unique
// if it has a parent, and the parent is a content type, unplug composition
// all other compositions remain in place in the copied content type
if (copy.ParentId > 0)
{
var parent = repository.Get(copy.ParentId);
if (parent != null)
copy.RemoveContentType(parent.Alias);
}
copy.ParentId = containerId;
repository.AddOrUpdate(copy);
}
catch (DataOperationException<MoveOperationStatusType> ex)
{
return Attempt.Fail(new OperationStatus<IContentType, MoveOperationStatusType>(null, ex.Operation, evtMsgs));
}
uow.Commit();
}
return Attempt.Succeed(new OperationStatus<IContentType, MoveOperationStatusType>(copy, MoveOperationStatusType.Success, evtMsgs));
}
/// <summary>
/// Saves a single <see cref="IMediaType"/> object
/// </summary>
@@ -267,11 +267,15 @@ namespace Umbraco.Core.Services
structure.Add(new XElement("MediaType", allowedType.Alias));
}
var genericProperties = new XElement("GenericProperties");
var genericProperties = new XElement("GenericProperties"); // actually, all of them
foreach (var propertyType in mediaType.PropertyTypes)
{
var definition = dataTypeService.GetDataTypeDefinitionById(propertyType.DataTypeDefinitionId);
var propertyGroup = mediaType.PropertyGroups.FirstOrDefault(x => x.Id == propertyType.PropertyGroupId.Value);
var propertyGroup = propertyType.PropertyGroupId == null // true generic property
? null
: mediaType.PropertyGroups.FirstOrDefault(x => x.Id == propertyType.PropertyGroupId.Value);
var genericProperty = new XElement("GenericProperty",
new XElement("Name", propertyType.Name),
new XElement("Alias", propertyType.Alias),
@@ -381,14 +385,14 @@ namespace Umbraco.Core.Services
structure.Add(new XElement("DocumentType", allowedType.Alias));
}
var genericProperties = new XElement("GenericProperties");
var genericProperties = new XElement("GenericProperties"); // actually, all of them
foreach (var propertyType in contentType.PropertyTypes)
{
var definition = dataTypeService.GetDataTypeDefinitionById(propertyType.DataTypeDefinitionId);
var propertyGroup = propertyType.PropertyGroupId == null
? null
: contentType.PropertyGroups.FirstOrDefault(x => x.Id == propertyType.PropertyGroupId.Value);
var propertyGroup = propertyType.PropertyGroupId == null // true generic property
? null
: contentType.PropertyGroups.FirstOrDefault(x => x.Id == propertyType.PropertyGroupId.Value);
var genericProperty = new XElement("GenericProperty",
new XElement("Name", propertyType.Name),
@@ -291,5 +291,7 @@ namespace Umbraco.Core.Services
Attempt<OperationStatus<MoveOperationStatusType>> MoveMediaType(IMediaType toMove, int containerId);
Attempt<OperationStatus<MoveOperationStatusType>> MoveContentType(IContentType toMove, int containerId);
Attempt<OperationStatus<IMediaType, MoveOperationStatusType>> CopyMediaType(IMediaType toCopy, int containerId);
Attempt<OperationStatus<IContentType, MoveOperationStatusType>> CopyContentType(IContentType toCopy, int containerId);
}
}
+24
View File
@@ -1380,6 +1380,30 @@ namespace Umbraco.Core
*/
}
public static string EscapeRegexSpecialCharacters(this string text)
{
var regexSpecialCharacters = new Dictionary<string, string>
{
{".", @"\."},
{"(", @"\("},
{")", @"\)"},
{"]", @"\]"},
{"[", @"\["},
{"{", @"\{"},
{"}", @"\}"},
{"?", @"\?"},
{"!", @"\!"},
{"$", @"\$"},
{"^", @"\^"},
{"+", @"\+"},
{"*", @"\*"},
{"|", @"\|"},
{"<", @"\<"},
{">", @"\>"}
};
return ReplaceMany(text, regexSpecialCharacters);
}
public static bool ContainsAny(this string haystack, IEnumerable<string> needles, StringComparison comparison = StringComparison.CurrentCulture)
{
if (haystack == null) throw new ArgumentNullException("haystack");
@@ -39,7 +39,7 @@ namespace Umbraco.Core.Strings.Css
public static string ReplaceRule(string input, string oldRuleName, StylesheetRule rule)
{
var contents = input;
var ruleRegex = new Regex(string.Format(RuleRegexFormat, oldRuleName), RegexOptions.IgnoreCase | RegexOptions.Singleline);
var ruleRegex = new Regex(string.Format(RuleRegexFormat, oldRuleName.EscapeRegexSpecialCharacters()), RegexOptions.IgnoreCase | RegexOptions.Singleline);
contents = ruleRegex.Replace(contents, rule != null ? rule.ToString() : "");
return contents;
}
+59 -28
View File
@@ -22,7 +22,7 @@ namespace Umbraco.Core
/// <summary>
/// A utility class to find all classes of a certain type by reflection in the current bin folder
/// of the web application.
/// of the web application.
/// </summary>
public static class TypeFinder
{
@@ -34,7 +34,7 @@ namespace Umbraco.Core
/// This is a modified version of: http://www.dominicpettifer.co.uk/Blog/44/how-to-get-a-reference-to-all-assemblies-in-the--bin-folder
/// </summary>
/// <remarks>
/// We do this because we cannot use AppDomain.Current.GetAssemblies() as this will return only assemblies that have been
/// We do this because we cannot use AppDomain.Current.GetAssemblies() as this will return only assemblies that have been
/// loaded in the CLR, not all assemblies.
/// See these threads:
/// http://issues.umbraco.org/issue/U5-198
@@ -136,7 +136,7 @@ namespace Umbraco.Core
});
/// <summary>
/// Return a list of found local Assemblies excluding the known assemblies we don't want to scan
/// Return a list of found local Assemblies excluding the known assemblies we don't want to scan
/// and exluding the ones passed in and excluding the exclusion list filter, the results of this are
/// cached for perforance reasons.
/// </summary>
@@ -190,6 +190,7 @@ namespace Umbraco.Core
/// </summary>
/// <remarks>
/// NOTE the comma vs period... comma delimits the name in an Assembly FullName property so if it ends with comma then its an exact name match
/// NOTE this means that "foo." will NOT exclude "foo.dll" but only "foo.*.dll"
/// </remarks>
internal static readonly string[] KnownAssemblyExclusionFilter = new[]
{
@@ -214,7 +215,7 @@ namespace Umbraco.Core
"RouteDebugger,",
"SqlCE4Umbraco,",
"umbraco.datalayer,",
"umbraco.interfaces,",
"umbraco.interfaces,",
//"umbraco.providers,",
//"Umbraco.Web.UI,",
"umbraco.webservices",
@@ -230,9 +231,9 @@ namespace Umbraco.Core
"AutoMapper,",
"AutoMapper.",
"AzureDirectory,",
"itextsharp,",
"itextsharp,",
"UrlRewritingNet.",
"HtmlAgilityPack,",
"HtmlAgilityPack,",
"MiniProfiler,",
"Moq,",
"nunit.framework,",
@@ -371,7 +372,7 @@ namespace Umbraco.Core
var assemblyList = assemblies.ToArray();
//find all assembly references that are referencing the attribute type's assembly since we
//find all assembly references that are referencing the attribute type's assembly since we
//should only be scanning those assemblies because any other assembly will definitely not
//contain a class that has this attribute.
var referencedAssemblies = TypeHelper.GetReferencedAssemblies(attributeType, assemblyList);
@@ -418,7 +419,7 @@ namespace Umbraco.Core
foreach (var subTypesInAssembly in allAttributeTypes.GroupBy(x => x.Assembly))
{
//So that we are not scanning too much, we need to group the sub types:
//So that we are not scanning too much, we need to group the sub types:
// * if there is more than 1 sub type in the same assembly then we should only search on the 'lowest base' type.
// * We should also not search for sub types if the type is sealed since you cannot inherit from a sealed class
// * We should not search for sub types if the type is static since you cannot inherit from them.
@@ -489,7 +490,7 @@ namespace Umbraco.Core
/// <summary>
/// Finds types that are assignable from the assignTypeFrom parameter and will scan for these types in the assembly
/// list passed in, however we will only scan assemblies that have a reference to the assignTypeFrom Type or any type
/// list passed in, however we will only scan assemblies that have a reference to the assignTypeFrom Type or any type
/// deriving from the base type.
/// </summary>
/// <param name="assignTypeFrom"></param>
@@ -513,7 +514,7 @@ namespace Umbraco.Core
var assemblyList = assemblies.ToArray();
//find all assembly references that are referencing the current type's assembly since we
//find all assembly references that are referencing the current type's assembly since we
//should only be scanning those assemblies because any other assembly will definitely not
//contain sub type's of the one we're currently looking for
var referencedAssemblies = TypeHelper.GetReferencedAssemblies(assignTypeFrom, assemblyList);
@@ -560,7 +561,7 @@ namespace Umbraco.Core
foreach (var subTypesInAssembly in allSubTypes.GroupBy(x => x.Assembly))
{
//So that we are not scanning too much, we need to group the sub types:
//So that we are not scanning too much, we need to group the sub types:
// * if there is more than 1 sub type in the same assembly then we should only search on the 'lowest base' type.
// * We should also not search for sub types if the type is sealed since you cannot inherit from a sealed class
// * We should not search for sub types if the type is static since you cannot inherit from them.
@@ -602,39 +603,69 @@ namespace Umbraco.Core
return foundAssignableTypes;
}
private static IEnumerable<Type> GetTypesWithFormattedException(Assembly a)
internal static IEnumerable<Type> GetTypesWithFormattedException(Assembly a)
{
//if the assembly is dynamic, do not try to scan it
if (a.IsDynamic)
return Enumerable.Empty<Type>();
var getAll = a.GetCustomAttribute<AllowPartiallyTrustedCallersAttribute>() == null;
try
{
//we need to detect if an assembly is partially trusted, if so we cannot go interrogating all of it's types
//only its exported types, otherwise we'll get exceptions.
if (a.GetCustomAttribute<AllowPartiallyTrustedCallersAttribute>() == null)
{
return a.GetTypes();
}
else
{
return a.GetExportedTypes();
}
return getAll ? a.GetTypes() : a.GetExportedTypes();
}
catch (ReflectionTypeLoadException ex)
catch (TypeLoadException ex) // GetExportedTypes *can* throw TypeLoadException!
{
var sb = new StringBuilder();
sb.AppendLine("Could not load types from assembly " + a.FullName + ", errors:");
foreach (var loaderException in ex.LoaderExceptions.WhereNotNull())
{
sb.AppendLine("Exception: " + loaderException);
}
throw new ReflectionTypeLoadException(ex.Types, ex.LoaderExceptions, sb.ToString());
AppendCouldNotLoad(sb, a, getAll);
AppendLoaderException(sb, ex);
// rethrow as ReflectionTypeLoadException (for consistency) with new message
throw new ReflectionTypeLoadException(new Type[0], new Exception[] { ex }, sb.ToString());
}
catch (ReflectionTypeLoadException rex) // GetTypes throws ReflectionTypeLoadException
{
var sb = new StringBuilder();
AppendCouldNotLoad(sb, a, getAll);
foreach (var loaderException in rex.LoaderExceptions.WhereNotNull())
AppendLoaderException(sb, loaderException);
// rethrow with new message
throw new ReflectionTypeLoadException(rex.Types, rex.LoaderExceptions, sb.ToString());
}
}
private static void AppendCouldNotLoad(StringBuilder sb, Assembly a, bool getAll)
{
sb.Append("Could not load ");
sb.Append(getAll ? "all" : "exported");
sb.Append(" types from \"");
sb.Append(a.FullName);
sb.AppendLine("\" due to LoaderExceptions, skipping:");
}
private static void AppendLoaderException(StringBuilder sb, Exception loaderException)
{
sb.Append(". ");
sb.Append(loaderException.GetType().FullName);
var tloadex = loaderException as TypeLoadException;
if (tloadex != null)
{
sb.Append(" on ");
sb.Append(tloadex.TypeName);
}
sb.Append(": ");
sb.Append(loaderException.Message);
sb.AppendLine();
}
#endregion
public static Type GetTypeByName(string typeName)
{
@@ -72,6 +72,11 @@ namespace Umbraco.Core
/// <summary>
/// Override init and raise the event
/// </summary>
/// <remarks>
/// DID YOU KNOW? The Global.asax Init call is the thing that initializes all of the httpmodules, ties up a bunch of stuff with IIS, etc...
/// Therefore, since OWIN is an HttpModule when running in IIS/ASP.Net the OWIN startup is not executed until this method fires and by that
/// time, Umbraco has performed it's bootup sequence.
/// </remarks>
public override void Init()
{
base.Init();
@@ -0,0 +1,100 @@
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Moq;
using NUnit.Framework;
using Semver;
using Umbraco.Core;
using Umbraco.Core.Events;
using Umbraco.Core.Logging;
using Umbraco.Core.Persistence;
using Umbraco.Core.Persistence.Migrations;
using Umbraco.Core.Profiling;
using Umbraco.Core.Services;
using Umbraco.Web.Strategies.Migrations;
namespace Umbraco.Tests.Persistence.Migrations
{
[TestFixture]
public class MigrationStartupHandlerTests
{
[Test]
public void Executes_For_Any_Product_Name_When_Not_Specified()
{
var changed1 = new Args { CountExecuted = 0 };
var testHandler1 = new TestMigrationHandler(changed1);
testHandler1.OnApplicationStarting(Mock.Of<UmbracoApplicationBase>(), new ApplicationContext(CacheHelper.CreateDisabledCacheHelper(), new ProfilingLogger(Mock.Of<ILogger>(), Mock.Of<IProfiler>())));
var conn = new Mock<IDbConnection>();
conn.Setup(x => x.BeginTransaction(It.IsAny<IsolationLevel>())).Returns(Mock.Of<IDbTransaction>());
var db = new Mock<Database>(conn.Object);
var runner1 = new MigrationRunner(Mock.Of<IMigrationEntryService>(), Mock.Of<ILogger>(), new SemVersion(1), new SemVersion(2), "Test1",
new IMigration[] { Mock.Of<IMigration>() });
var result1 = runner1.Execute(db.Object, DatabaseProviders.SqlServerCE, false);
Assert.AreEqual(1, changed1.CountExecuted);
}
[Test]
public void Executes_Only_For_Specified_Product_Name()
{
var changed1 = new Args { CountExecuted = 0};
var testHandler1 = new TestMigrationHandler("Test1", changed1);
testHandler1.OnApplicationStarting(Mock.Of<UmbracoApplicationBase>(), new ApplicationContext(CacheHelper.CreateDisabledCacheHelper(), new ProfilingLogger(Mock.Of<ILogger>(), Mock.Of<IProfiler>())));
var changed2 = new Args { CountExecuted = 0 };
var testHandler2 = new TestMigrationHandler("Test2", changed2);
testHandler2.OnApplicationStarting(Mock.Of<UmbracoApplicationBase>(), new ApplicationContext(CacheHelper.CreateDisabledCacheHelper(), new ProfilingLogger(Mock.Of<ILogger>(), Mock.Of<IProfiler>())));
var conn = new Mock<IDbConnection>();
conn.Setup(x => x.BeginTransaction(It.IsAny<IsolationLevel>())).Returns(Mock.Of<IDbTransaction>());
var db = new Mock<Database>(conn.Object);
var runner1 = new MigrationRunner(Mock.Of<IMigrationEntryService>(), Mock.Of<ILogger>(), new SemVersion(1), new SemVersion(2), "Test1",
new IMigration[] { Mock.Of<IMigration>()});
var result1 = runner1.Execute(db.Object, DatabaseProviders.SqlServerCE, false);
Assert.AreEqual(1, changed1.CountExecuted);
Assert.AreEqual(0, changed2.CountExecuted);
var runner2 = new MigrationRunner(Mock.Of<IMigrationEntryService>(), Mock.Of<ILogger>(), new SemVersion(1), new SemVersion(2), "Test2",
new IMigration[] { Mock.Of<IMigration>() });
var result2 = runner2.Execute(db.Object, DatabaseProviders.SqlServerCE, false);
Assert.AreEqual(1, changed1.CountExecuted);
Assert.AreEqual(1, changed2.CountExecuted);
}
public class Args
{
public int CountExecuted { get; set; }
}
public class TestMigrationHandler : MigrationStartupHander
{
private readonly string _prodName;
private readonly Args _changed;
public TestMigrationHandler(Args changed)
{
_changed = changed;
}
public TestMigrationHandler(string prodName, Args changed)
{
_prodName = prodName;
_changed = changed;
}
protected override void AfterMigration(MigrationRunner sender, MigrationEventArgs e)
{
_changed.CountExecuted++;
}
public override string[] TargetProductNames
{
get { return _prodName.IsNullOrWhiteSpace() ? new string[] {} : new[] {_prodName}; }
}
}
}
}
@@ -21,7 +21,7 @@ namespace Umbraco.Tests.Persistence.Querying
.InnerJoin("[cmsContentVersion]").On("[cmsDocument].[versionId] = [cmsContentVersion].[VersionId]")
.InnerJoin("[cmsContent]").On("[cmsContentVersion].[ContentId] = [cmsContent].[nodeId]")
.InnerJoin("[umbracoNode]").On("[cmsContent].[nodeId] = [umbracoNode].[id]")
.Where("[umbracoNode].[nodeObjectType] = @0", new Guid("c66ba18e-eaf3-4cff-8a22-41b16d66a972"));
.Where("([umbracoNode].[nodeObjectType] = @0)", new Guid("c66ba18e-eaf3-4cff-8a22-41b16d66a972"));
var sql = new Sql();
sql.Select("*")
@@ -56,8 +56,8 @@ namespace Umbraco.Tests.Persistence.Querying
.InnerJoin("[cmsContentVersion]").On("[cmsDocument].[versionId] = [cmsContentVersion].[VersionId]")
.InnerJoin("[cmsContent]").On("[cmsContentVersion].[ContentId] = [cmsContent].[nodeId]")
.InnerJoin("[umbracoNode]").On("[cmsContent].[nodeId] = [umbracoNode].[id]")
.Where("[umbracoNode].[nodeObjectType] = @0", new Guid("c66ba18e-eaf3-4cff-8a22-41b16d66a972"))
.Where("[umbracoNode].[id] = @0", 1050);
.Where("([umbracoNode].[nodeObjectType] = @0)", new Guid("c66ba18e-eaf3-4cff-8a22-41b16d66a972"))
.Where("([umbracoNode].[id] = @0)", 1050);
var sql = new Sql();
sql.Select("*")
@@ -94,9 +94,9 @@ namespace Umbraco.Tests.Persistence.Querying
.InnerJoin("[cmsContentVersion]").On("[cmsDocument].[versionId] = [cmsContentVersion].[VersionId]")
.InnerJoin("[cmsContent]").On("[cmsContentVersion].[ContentId] = [cmsContent].[nodeId]")
.InnerJoin("[umbracoNode]").On("[cmsContent].[nodeId] = [umbracoNode].[id]")
.Where("[umbracoNode].[nodeObjectType] = @0", new Guid("c66ba18e-eaf3-4cff-8a22-41b16d66a972"))
.Where("[umbracoNode].[id] = @0", 1050)
.Where("[cmsContentVersion].[VersionId] = @0", new Guid("2b543516-a944-4ee6-88c6-8813da7aaa07"))
.Where("([umbracoNode].[nodeObjectType] = @0)", new Guid("c66ba18e-eaf3-4cff-8a22-41b16d66a972"))
.Where("([umbracoNode].[id] = @0)", 1050)
.Where("([cmsContentVersion].[VersionId] = @0)", new Guid("2b543516-a944-4ee6-88c6-8813da7aaa07"))
.OrderBy("[cmsContentVersion].[VersionDate] DESC");
var sql = new Sql();
@@ -133,8 +133,8 @@ namespace Umbraco.Tests.Persistence.Querying
expected.Select("*");
expected.From("[cmsPropertyData]");
expected.InnerJoin("[cmsPropertyType]").On("[cmsPropertyData].[propertytypeid] = [cmsPropertyType].[id]");
expected.Where("[cmsPropertyData].[contentNodeId] = @0", 1050);
expected.Where("[cmsPropertyData].[versionId] = @0", new Guid("2b543516-a944-4ee6-88c6-8813da7aaa07"));
expected.Where("([cmsPropertyData].[contentNodeId] = @0)", 1050);
expected.Where("([cmsPropertyData].[versionId] = @0)", new Guid("2b543516-a944-4ee6-88c6-8813da7aaa07"));
var sql = new Sql();
sql.Select("*")
@@ -22,8 +22,8 @@ namespace Umbraco.Tests.Persistence.Querying
.On("[cmsContentType].[nodeId] = [cmsDocumentType].[contentTypeNodeId]")
.InnerJoin("[umbracoNode]")
.On("[cmsContentType].[nodeId] = [umbracoNode].[id]")
.Where("[umbracoNode].[nodeObjectType] = @0", new Guid("a2cb7800-f571-4787-9638-bc48539a0efb"))
.Where("[cmsDocumentType].[IsDefault] = @0", true);
.Where("([umbracoNode].[nodeObjectType] = @0)", new Guid("a2cb7800-f571-4787-9638-bc48539a0efb"))
.Where("([cmsDocumentType].[IsDefault] = @0)", true);
var sql = new Sql();
sql.Select("*")
@@ -58,9 +58,9 @@ namespace Umbraco.Tests.Persistence.Querying
.On("[cmsContentType].[nodeId] = [cmsDocumentType].[contentTypeNodeId]")
.InnerJoin("[umbracoNode]")
.On("[cmsContentType].[nodeId] = [umbracoNode].[id]")
.Where("[umbracoNode].[nodeObjectType] = @0", new Guid("a2cb7800-f571-4787-9638-bc48539a0efb"))
.Where("([umbracoNode].[nodeObjectType] = @0)", new Guid("a2cb7800-f571-4787-9638-bc48539a0efb"))
.Where("[cmsDocumentType].[IsDefault] = @0", true)
.Where("[umbracoNode].[id] = @0", 1050);
.Where("([umbracoNode].[id] = @0)", 1050);
var sql = new Sql();
sql.Select("*")
@@ -112,7 +112,7 @@ namespace Umbraco.Tests.Persistence.Querying
var expected = new Sql();
expected.Select("*")
.From("[cmsContentTypeAllowedContentType]")
.Where("[cmsContentTypeAllowedContentType].[Id] = @0", 1050);
.Where("([cmsContentTypeAllowedContentType].[Id] = @0)", 1050);
var sql = new Sql();
sql.Select("*")
@@ -138,7 +138,7 @@ namespace Umbraco.Tests.Persistence.Querying
.From("[cmsPropertyTypeGroup]")
.RightJoin("[cmsPropertyType]").On("[cmsPropertyTypeGroup].[id] = [cmsPropertyType].[propertyTypeGroupId]")
.InnerJoin("[cmsDataType]").On("[cmsPropertyType].[dataTypeId] = [cmsDataType].[nodeId]")
.Where("[cmsPropertyType].[contentTypeId] = @0", 1050);
.Where("([cmsPropertyType].[contentTypeId] = @0)", 1050);
var sql = new Sql();
sql.Select("*")
@@ -19,7 +19,7 @@ namespace Umbraco.Tests.Persistence.Querying
expected.Select("*")
.From("[cmsDataType]")
.InnerJoin("[umbracoNode]").On("[cmsDataType].[nodeId] = [umbracoNode].[id]")
.Where("[umbracoNode].[nodeObjectType] = @0", new Guid("30a2a501-1978-4ddb-a57b-f7efed43ba3c"));
.Where("([umbracoNode].[nodeObjectType] = @0)", new Guid("30a2a501-1978-4ddb-a57b-f7efed43ba3c"));
var sql = new Sql();
sql.Select("*")
@@ -53,7 +53,7 @@ namespace Umbraco.Tests.Persistence.Querying
Console.WriteLine("Model to Sql ExpressionHelper: \n" + result);
Assert.AreEqual("[umbracoNode].[parentID] = @0", result);
Assert.AreEqual("([umbracoNode].[parentID] = @0)", result);
Assert.AreEqual(-1, modelToSqlExpressionHelper.GetSqlParameters()[0]);
}
@@ -66,7 +66,7 @@ namespace Umbraco.Tests.Persistence.Querying
Console.WriteLine("Model to Sql ExpressionHelper: \n" + result);
Assert.AreEqual("[umbracoUser].[userLogin] = @0", result);
Assert.AreEqual("([umbracoUser].[userLogin] = @0)", result);
Assert.AreEqual("hello@world.com", modelToSqlExpressionHelper.GetSqlParameters()[0]);
}
@@ -20,7 +20,7 @@ namespace Umbraco.Tests.Persistence.Querying
.From("[cmsContentVersion]")
.InnerJoin("[cmsContent]").On("[cmsContentVersion].[ContentId] = [cmsContent].[nodeId]")
.InnerJoin("[umbracoNode]").On("[cmsContent].[nodeId] = [umbracoNode].[id]")
.Where("[umbracoNode].[nodeObjectType] = @0", new Guid("b796f64c-1f99-4ffb-b886-4bf4bc011a9c"));
.Where("([umbracoNode].[nodeObjectType] = @0)", new Guid("b796f64c-1f99-4ffb-b886-4bf4bc011a9c"));
var sql = new Sql();
sql.Select("*")
@@ -19,7 +19,7 @@ namespace Umbraco.Tests.Persistence.Querying
expected.Select("*")
.From("[cmsContentType]")
.InnerJoin("[umbracoNode]").On("[cmsContentType].[nodeId] = [umbracoNode].[id]")
.Where("[umbracoNode].[nodeObjectType] = @0", new Guid("4ea4382b-2f5a-4c2b-9587-ae9b3cf3602e"));
.Where("([umbracoNode].[nodeObjectType] = @0)", new Guid("4ea4382b-2f5a-4c2b-9587-ae9b3cf3602e"));
var sql = new Sql();
sql.Select("*")
@@ -33,7 +33,7 @@ namespace Umbraco.Tests.Persistence.Querying
var content = new NodeDto() {NodeId = 123, Path = "-1,123"};
var sql = new Sql("SELECT *").From<NodeDto>().Where<NodeDto>(x => x.Path.StartsWith(content.Path) && x.NodeId != content.NodeId);
Assert.AreEqual("SELECT * FROM [umbracoNode] WHERE (upper([umbracoNode].[path]) LIKE upper(@0) AND [umbracoNode].[id] <> @1)", sql.SQL.Replace("\n", " "));
Assert.AreEqual("SELECT * FROM [umbracoNode] WHERE ((upper([umbracoNode].[path]) LIKE upper(@0) AND ([umbracoNode].[id] <> @1)))", sql.SQL.Replace("\n", " "));
Assert.AreEqual(2, sql.Arguments.Length);
Assert.AreEqual(content.Path + "%", sql.Arguments[0]);
Assert.AreEqual(content.NodeId, sql.Arguments[1]);
@@ -45,7 +45,19 @@ namespace Umbraco.Tests.Persistence.Querying
var level = 1;
var sql = new Sql("SELECT *").From<NodeDto>().Where<NodeDto>(x => x.Level == level && !x.Path.StartsWith("-20"));
Assert.AreEqual("SELECT * FROM [umbracoNode] WHERE ([umbracoNode].[level] = @0 AND NOT (upper([umbracoNode].[path]) LIKE upper(@1)))", sql.SQL.Replace("\n", " "));
Assert.AreEqual("SELECT * FROM [umbracoNode] WHERE ((([umbracoNode].[level] = @0) AND NOT (upper([umbracoNode].[path]) LIKE upper(@1))))", sql.SQL.Replace("\n", " "));
Assert.AreEqual(2, sql.Arguments.Length);
Assert.AreEqual(level, sql.Arguments[0]);
Assert.AreEqual("-20%", sql.Arguments[1]);
}
[Test]
public void Where_Clause_With_EqualsFalse_Starts_With()
{
var level = 1;
var sql = new Sql("SELECT *").From<NodeDto>().Where<NodeDto>(x => x.Level == level && x.Path.StartsWith("-20") == false);
Assert.AreEqual("SELECT * FROM [umbracoNode] WHERE ((([umbracoNode].[level] = @0) AND NOT (upper([umbracoNode].[path]) LIKE upper(@1))))", sql.SQL.Replace("\n", " "));
Assert.AreEqual(2, sql.Arguments.Length);
Assert.AreEqual(level, sql.Arguments[0]);
Assert.AreEqual("-20%", sql.Arguments[1]);
@@ -71,6 +83,16 @@ namespace Umbraco.Tests.Persistence.Querying
Assert.AreEqual(true, sql.Arguments[0]);
}
[Test]
public void Where_Clause_With_EqualsFalse_Boolean()
{
var sql = new Sql("SELECT *").From<NodeDto>().Where<NodeDto>(x => x.Trashed == false);
Assert.AreEqual("SELECT * FROM [umbracoNode] WHERE (NOT ([umbracoNode].[trashed] = @0))", sql.SQL.Replace("\n", " "));
Assert.AreEqual(1, sql.Arguments.Length);
Assert.AreEqual(true, sql.Arguments[0]);
}
[Test]
public void Where_Clause_With_Boolean()
{
@@ -86,7 +108,7 @@ namespace Umbraco.Tests.Persistence.Querying
{
var sql = new Sql("SELECT *").From<NodeDto>().Where<NodeDto>(x => x.Text.ToUpper() == "hello".ToUpper());
Assert.AreEqual("SELECT * FROM [umbracoNode] WHERE (upper([umbracoNode].[text]) = upper(@0))", sql.SQL.Replace("\n", " "));
Assert.AreEqual("SELECT * FROM [umbracoNode] WHERE ((upper([umbracoNode].[text]) = upper(@0)))", sql.SQL.Replace("\n", " "));
Assert.AreEqual(1, sql.Arguments.Length);
Assert.AreEqual("hello", sql.Arguments[0]);
}
@@ -96,7 +118,7 @@ namespace Umbraco.Tests.Persistence.Querying
{
var sql = new Sql("SELECT *").From<NodeDto>().Where<NodeDto>(x => x.Text == 1.ToString());
Assert.AreEqual("SELECT * FROM [umbracoNode] WHERE ([umbracoNode].[text] = @0)", sql.SQL.Replace("\n", " "));
Assert.AreEqual("SELECT * FROM [umbracoNode] WHERE (([umbracoNode].[text] = @0))", sql.SQL.Replace("\n", " "));
Assert.AreEqual(1, sql.Arguments.Length);
Assert.AreEqual("1", sql.Arguments[0]);
}
@@ -116,7 +138,7 @@ namespace Umbraco.Tests.Persistence.Querying
{
var sql = new Sql("SELECT *").From<NodeDto>().Where<NodeDto>(x => x.NodeId == 2);
Assert.AreEqual("SELECT * FROM [umbracoNode] WHERE ([umbracoNode].[id] = @0)", sql.SQL.Replace("\n", " "));
Assert.AreEqual("SELECT * FROM [umbracoNode] WHERE (([umbracoNode].[id] = @0))", sql.SQL.Replace("\n", " "));
Assert.AreEqual(1, sql.Arguments.Length);
Assert.AreEqual(2, sql.Arguments[0]);
}
@@ -126,7 +148,7 @@ namespace Umbraco.Tests.Persistence.Querying
{
var sql = new Sql("SELECT *").From<NodeDto>().Where<NodeDto>(x => x.NodeId != 2 && x.NodeId != 3);
Assert.AreEqual("SELECT * FROM [umbracoNode] WHERE ([umbracoNode].[id] <> @0 AND [umbracoNode].[id] <> @1)", sql.SQL.Replace("\n", " "));
Assert.AreEqual("SELECT * FROM [umbracoNode] WHERE ((([umbracoNode].[id] <> @0) AND ([umbracoNode].[id] <> @1)))", sql.SQL.Replace("\n", " "));
Assert.AreEqual(2, sql.Arguments.Length);
Assert.AreEqual(2, sql.Arguments[0]);
Assert.AreEqual(3, sql.Arguments[1]);
@@ -137,7 +159,7 @@ namespace Umbraco.Tests.Persistence.Querying
{
var sql = new Sql("SELECT *").From<NodeDto>().Where<NodeDto>(x => x.Text == "hello" || x.NodeId == 3);
Assert.AreEqual("SELECT * FROM [umbracoNode] WHERE ([umbracoNode].[text] = @0 OR [umbracoNode].[id] = @1)", sql.SQL.Replace("\n", " "));
Assert.AreEqual("SELECT * FROM [umbracoNode] WHERE ((([umbracoNode].[text] = @0) OR ([umbracoNode].[id] = @1)))", sql.SQL.Replace("\n", " "));
Assert.AreEqual(2, sql.Arguments.Length);
Assert.AreEqual("hello", sql.Arguments[0]);
Assert.AreEqual(3, sql.Arguments[1]);
@@ -208,7 +230,7 @@ namespace Umbraco.Tests.Persistence.Querying
public void Can_Use_Where_Predicate()
{
var expected = new Sql();
expected.Select("*").From("[cmsContent]").Where("[cmsContent].[nodeId] = @0", 1045);
expected.Select("*").From("[cmsContent]").Where("([cmsContent].[nodeId] = @0)", 1045);
var sql = new Sql();
sql.Select("*").From<ContentDto>().Where<ContentDto>(x => x.NodeId == 1045);
@@ -224,8 +246,8 @@ namespace Umbraco.Tests.Persistence.Querying
var expected = new Sql();
expected.Select("*")
.From("[cmsContent]")
.Where("[cmsContent].[nodeId] = @0", 1045)
.Where("[cmsContent].[contentType] = @0", 1050);
.Where("([cmsContent].[nodeId] = @0)", 1045)
.Where("([cmsContent].[contentType] = @0)", 1050);
var sql = new Sql();
sql.Select("*")
@@ -56,7 +56,7 @@ namespace Umbraco.Tests.Persistence.Querying
var result = translator.Translate();
var strResult = result.SQL;
string expectedResult = "SELECT *\nFROM umbracoNode\nWHERE ([umbracoNode].[parentID] = @0)";
string expectedResult = "SELECT *\nFROM umbracoNode\nWHERE (([umbracoNode].[parentID] = @0))";
// Assert
Assert.That(strResult, Is.Not.Empty);
@@ -83,7 +83,7 @@ namespace Umbraco.Tests.Persistence.Querying
var result = translator.Translate();
var strResult = result.SQL;
string expectedResult = "SELECT *\nFROM umbracoNode\nWHERE ([cmsContentType].[alias] = @0)";
string expectedResult = "SELECT *\nFROM umbracoNode\nWHERE (([cmsContentType].[alias] = @0))";
// Assert
Assert.That(strResult, Is.Not.Empty);
@@ -90,7 +90,7 @@ namespace Umbraco.Tests.Persistence.Repositories
templateRepo.AddOrUpdate(template);
}
unitOfWork.Commit();
var contentType = MockedContentTypes.CreateSimpleContentType();
contentType.AllowedTemplates = new[] {templates[0], templates[1]};
contentType.SetDefaultTemplate(templates[0]);
@@ -127,7 +127,7 @@ namespace Umbraco.Tests.Persistence.Repositories
repository.AddOrUpdate(contentType);
unitOfWork.Commit();
//create a
//create a
var contentType2 = (IContentType)new ContentType(contentType, "hello")
{
Name = "Blahasdfsadf"
@@ -293,7 +293,9 @@ namespace Umbraco.Tests.Persistence.Repositories
using (var repository = CreateRepository(unitOfWork))
{
// Act
var contentType = (IContentType)MockedContentTypes.CreateSimpleContentType("test", "Test", propertyGroupName: "testGroup");
var contentType = (IContentType)MockedContentTypes.CreateSimpleContentType2("test", "Test", propertyGroupName: "testGroup");
Assert.AreEqual(4, contentType.PropertyTypes.Count());
// there is NO mapping from display to contentType, but only from save
// to contentType, so if we want to test, let's to it properly!
@@ -301,12 +303,18 @@ namespace Umbraco.Tests.Persistence.Repositories
var save = MapToContentTypeSave(display);
var mapped = Mapper.Map<IContentType>(save);
Assert.AreEqual(4, mapped.PropertyTypes.Count());
repository.AddOrUpdate(mapped);
unitOfWork.Commit();
Assert.AreEqual(4, mapped.PropertyTypes.Count());
//re-get
contentType = repository.Get(mapped.Id);
Assert.AreEqual(4, contentType.PropertyTypes.Count());
// Assert
Assert.That(contentType.HasIdentity, Is.True);
Assert.That(contentType.PropertyGroups.All(x => x.HasIdentity), Is.True);
@@ -316,7 +324,11 @@ namespace Umbraco.Tests.Persistence.Repositories
Assert.That(contentType.PropertyGroups.ElementAt(0).Name == "testGroup", Is.True);
var groupId = contentType.PropertyGroups.ElementAt(0).Id;
Assert.That(contentType.PropertyTypes.All(x => x.PropertyGroupId.Value == groupId), Is.True);
var propertyTypes = contentType.PropertyTypes.ToArray();
Assert.AreEqual("gen", propertyTypes[0].Alias); // just to be sure
Assert.IsNull(propertyTypes[0].PropertyGroupId);
Assert.IsTrue(propertyTypes.Skip(1).All((x => x.PropertyGroupId.Value == groupId)));
}
}
@@ -353,7 +365,7 @@ namespace Umbraco.Tests.Persistence.Repositories
Assert.That(contentType.PropertyTypes.Any(x => x.Alias == "subtitle"), Is.True);
}
}
// this is for tests only because it makes no sense at all to have such a
@@ -491,16 +503,16 @@ namespace Umbraco.Tests.Persistence.Repositories
var provider = new PetaPocoUnitOfWorkProvider(Logger);
var unitOfWork = provider.GetUnitOfWork();
using (var repository = CreateRepository(unitOfWork))
{
{
var ctMain = MockedContentTypes.CreateSimpleContentType();
var ctChild1 = MockedContentTypes.CreateSimpleContentType("child1", "Child 1", ctMain, true);
var ctChild2 = MockedContentTypes.CreateSimpleContentType("child2", "Child 2", ctChild1, true);
repository.AddOrUpdate(ctMain);
repository.AddOrUpdate(ctChild1);
repository.AddOrUpdate(ctChild2);
repository.AddOrUpdate(ctChild2);
unitOfWork.Commit();
// Act
var resolvedParent = repository.Get(ctMain.Id);
@@ -528,7 +540,7 @@ namespace Umbraco.Tests.Persistence.Repositories
var child3 = MockedContentTypes.CreateSimpleContentType("zyx", "zyx", contentType, randomizeAliases: true);
repository.AddOrUpdate(child3);
var child2 = MockedContentTypes.CreateSimpleContentType("a123", "a123", contentType, randomizeAliases: true);
repository.AddOrUpdate(child2);
repository.AddOrUpdate(child2);
unitOfWork.Commit();
// Act
@@ -540,7 +552,7 @@ namespace Umbraco.Tests.Persistence.Repositories
Assert.AreEqual("aabc", contentTypes.ElementAt(1).Name);
Assert.AreEqual("zyx", contentTypes.ElementAt(2).Name);
}
}
[Test]
@@ -671,7 +683,7 @@ namespace Umbraco.Tests.Persistence.Repositories
{
var contentType = repository.Get(NodeDto.NodeIdSeed + 1);
// Act
// Act
contentType.PropertyGroups["Meta"].PropertyTypes.Remove("description");
repository.AddOrUpdate(contentType);
unitOfWork.Commit();
@@ -841,7 +853,7 @@ namespace Umbraco.Tests.Persistence.Repositories
Assert.That(contentType.PropertyTypes.Count(), Is.EqualTo(5));
Assert.That(contentType.PropertyTypes.Any(x => x.Alias == "metaAuthor"), Is.True);
}
}
[Test]
@@ -36,7 +36,7 @@ namespace Umbraco.Tests.Persistence.SyntaxProvider
FROM [cmsContentXml]
INNER JOIN [umbracoNode]
ON [cmsContentXml].[nodeId] = [umbracoNode].[id]
WHERE ([umbracoNode].[nodeObjectType] = @0)) x)".Replace(Environment.NewLine, " ").Replace("\n", " ").Replace("\r", " "),
WHERE (([umbracoNode].[nodeObjectType] = @0))) x)".Replace(Environment.NewLine, " ").Replace("\n", " ").Replace("\r", " "),
sqlOutput.SQL.Replace(Environment.NewLine, " ").Replace("\n", " ").Replace("\r", " "));
Assert.AreEqual(1, sqlOutput.Arguments.Length);
+2 -2
View File
@@ -79,8 +79,8 @@ namespace Umbraco.Tests.Plugins
var originalTypesFound = TypeFinderOriginal.FindClassesOfType<IApplicationStartupHandler>(_assemblies);
Assert.AreEqual(originalTypesFound.Count(), typesFound.Count());
Assert.AreEqual(8, typesFound.Count());
Assert.AreEqual(8, originalTypesFound.Count());
Assert.AreEqual(9, typesFound.Count());
Assert.AreEqual(9, originalTypesFound.Count());
}
[Test]
@@ -164,6 +164,24 @@ namespace Umbraco.Tests.TestHelpers.Entities
return contentType;
}
public static ContentType CreateSimpleContentType2(string alias, string name, IContentType parent = null, bool randomizeAliases = false, string propertyGroupName = "Content")
{
var contentType = CreateSimpleContentType(alias, name, parent, randomizeAliases, propertyGroupName);
var propertyType = new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext)
{
Alias = RandomAlias("gen", randomizeAliases),
Name = "Gen",
Description = "",
Mandatory = false,
SortOrder = 1,
DataTypeDefinitionId = -88
};
contentType.AddPropertyType(propertyType);
return contentType;
}
public static ContentType CreateSimpleContentType(string alias, string name, IContentType parent = null, bool randomizeAliases = false, string propertyGroupName = "Content")
{
var contentType = parent == null ? new ContentType(-1) : new ContentType(parent, alias);
+2
View File
@@ -175,6 +175,7 @@
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="Persistence\Migrations\MigrationStartupHandlerTests.cs" />
<Compile Include="Web\AngularIntegration\AngularAntiForgeryTests.cs" />
<Compile Include="Web\AngularIntegration\ContentModelSerializationTests.cs" />
<Compile Include="Web\AngularIntegration\JsInitializationTests.cs" />
@@ -244,6 +245,7 @@
<Compile Include="Models\UmbracoEntityTests.cs" />
<Compile Include="Models\UserTests.cs" />
<Compile Include="Models\UserTypeTests.cs" />
<Compile Include="Web\Mvc\RenderModelBinderTests.cs" />
<Compile Include="Web\Mvc\SurfaceControllerTests.cs" />
<Compile Include="Web\Mvc\UmbracoViewPageTests.cs" />
<Compile Include="BootManagers\CoreBootManagerTests.cs" />
@@ -0,0 +1,171 @@
using System.Collections.Generic;
using System.Globalization;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;
using Moq;
using NUnit.Framework;
using Umbraco.Core.Models;
using Umbraco.Core.Models.PublishedContent;
using Umbraco.Web.Models;
using Umbraco.Web.Mvc;
namespace Umbraco.Tests.Web.Mvc
{
[TestFixture]
public class RenderModelBinderTests
{
[Test]
public void Returns_Binder_For_IPublishedContent_And_IRenderModel()
{
var binder = new RenderModelBinder();
var found = binder.GetBinder(typeof (IPublishedContent));
Assert.IsNotNull(found);
found = binder.GetBinder(typeof(RenderModel));
Assert.IsNotNull(found);
found = binder.GetBinder(typeof(DynamicPublishedContent));
Assert.IsNotNull(found);
found = binder.GetBinder(typeof(MyContent));
Assert.IsNotNull(found);
found = binder.GetBinder(typeof(RenderModel<MyContent>));
Assert.IsNotNull(found);
found = binder.GetBinder(typeof(MyOtherContent));
Assert.IsNull(found);
found = binder.GetBinder(typeof(MyCustomRenderModel));
Assert.IsNull(found);
found = binder.GetBinder(typeof(IRenderModel));
Assert.IsNull(found);
}
[Test]
public void BindModel_Null_Source_Returns_Null()
{
Assert.IsNull(RenderModelBinder.BindModel(null, typeof(MyContent), CultureInfo.CurrentCulture));
}
[Test]
public void BindModel_Returns_If_Same_Type()
{
var content = new MyContent(Mock.Of<IPublishedContent>());
var bound = RenderModelBinder.BindModel(content, typeof (IPublishedContent), CultureInfo.CurrentCulture);
Assert.AreSame(content, bound);
}
[Test]
public void BindModel_RenderModel_To_IPublishedContent()
{
var content = new MyContent(Mock.Of<IPublishedContent>());
var renderModel = new RenderModel(content, CultureInfo.CurrentCulture);
var bound = RenderModelBinder.BindModel(renderModel, typeof(IPublishedContent), CultureInfo.CurrentCulture);
Assert.AreSame(content, bound);
}
[Test]
public void BindModel_IPublishedContent_To_RenderModel()
{
var content = new MyContent(Mock.Of<IPublishedContent>());
var bound = (IRenderModel)RenderModelBinder.BindModel(content, typeof(RenderModel), CultureInfo.CurrentCulture);
Assert.AreSame(content, bound.Content);
}
[Test]
public void BindModel_IPublishedContent_To_Generic_RenderModel()
{
var content = new MyContent(Mock.Of<IPublishedContent>());
var bound = (IRenderModel)RenderModelBinder.BindModel(content, typeof(RenderModel<MyContent>), CultureInfo.CurrentCulture);
Assert.AreSame(content, bound.Content);
}
[Test]
public void No_DataToken_Returns_Null()
{
var binder = new RenderModelBinder();
var routeData = new RouteData();
var result = binder.BindModel(new ControllerContext(Mock.Of<HttpContextBase>(), routeData, Mock.Of<ControllerBase>()),
new ModelBindingContext());
Assert.IsNull(result);
}
[Test]
public void Invalid_DataToken_Model_Type_Returns_Null()
{
var binder = new RenderModelBinder();
var routeData = new RouteData();
routeData.DataTokens[Core.Constants.Web.UmbracoDataToken] = "hello";
//the value provider is the default implementation
var valueProvider = new Mock<IValueProvider>();
//also IUnvalidatedValueProvider
var invalidatedValueProvider = valueProvider.As<IUnvalidatedValueProvider>();
invalidatedValueProvider.Setup(x => x.GetValue(It.IsAny<string>(), It.IsAny<bool>())).Returns(() =>
new ValueProviderResult(null, "", CultureInfo.CurrentCulture));
var controllerCtx = new ControllerContext(
Mock.Of<HttpContextBase>(http => http.Items == new Dictionary<object, object>()),
routeData,
Mock.Of<ControllerBase>());
var result = binder.BindModel(controllerCtx,
new ModelBindingContext
{
ValueProvider = valueProvider.Object,
ModelMetadata = new ModelMetadata(new EmptyModelMetadataProvider(), null, () => null, typeof(IPublishedContent), "content")
});
Assert.IsNull(result);
}
[Test]
public void IPublishedContent_DataToken_Model_Type_Uses_DefaultImplementation()
{
var content = new MyContent(Mock.Of<IPublishedContent>());
var binder = new RenderModelBinder();
var routeData = new RouteData();
routeData.DataTokens[Core.Constants.Web.UmbracoDataToken] = content;
//the value provider is the default implementation
var valueProvider = new Mock<IValueProvider>();
//also IUnvalidatedValueProvider
var invalidatedValueProvider = valueProvider.As<IUnvalidatedValueProvider>();
invalidatedValueProvider.Setup(x => x.GetValue(It.IsAny<string>(), It.IsAny<bool>())).Returns(() =>
new ValueProviderResult(content, "content", CultureInfo.CurrentCulture));
var controllerCtx = new ControllerContext(
Mock.Of<HttpContextBase>(http => http.Items == new Dictionary<object, object>()),
routeData,
Mock.Of<ControllerBase>());
var result = binder.BindModel(controllerCtx,
new ModelBindingContext
{
ValueProvider = valueProvider.Object,
ModelMetadata = new ModelMetadata(new EmptyModelMetadataProvider(), null, () => null, typeof(IPublishedContent), "content")
});
Assert.AreEqual(content, result);
}
public class MyCustomRenderModel : RenderModel
{
public MyCustomRenderModel(IPublishedContent content, CultureInfo culture) : base(content, culture)
{
}
public MyCustomRenderModel(IPublishedContent content) : base(content)
{
}
}
public class MyOtherContent
{
}
public class MyContent : PublishedContentWrapped
{
public MyContent(IPublishedContent content) : base(content)
{
}
}
}
}
@@ -210,7 +210,7 @@ function submit()
if (findDepth(curLineHTML, cc) !== 0) {
// Cursor is inside a <tag>, don't set cursor:
curLineHTML = curLineHTML.replace(cc, '');
doc.setLine(pos.line, curLineHTML);
doc.getLineHandle(pos.line).text = curLineHTML;
}
// Submit HTML to TinyMCE:
+27 -7
View File
@@ -22,15 +22,35 @@ var packages = angular.module("umbraco.packages", []);
//module is initilized.
angular.module("umbraco.views", ["umbraco.viewcache"]);
angular.module("umbraco.viewcache", [])
.run(function($rootScope, $templateCache){
/** For debug mode, always clear template cache to cut down on
.run(function($rootScope, $templateCache) {
/** For debug mode, always clear template cache to cut down on
dev frustration and chrome cache on templates */
if(Umbraco.Sys.ServerVariables.isDebuggingEnabled){
//$rootScope.$on('$viewContentLoaded', function() {
$templateCache.removeAll();
//});
if (Umbraco.Sys.ServerVariables.isDebuggingEnabled) {
$templateCache.removeAll();
}
})
})
.config([
//This ensures that all of our angular views are cache busted, if the path starts with views/ and ends with .html, then
// we will append the cache busting value to it. This way all upgraded sites will not have to worry about browser cache.
"$provide", function($provide) {
return $provide.decorator("$http", [
"$delegate", function($delegate) {
var get = $delegate.get;
$delegate.get = function (url, config) {
if (Umbraco.Sys.ServerVariables.application && url.startsWith("views/") && url.endsWith(".html")) {
var rnd = Umbraco.Sys.ServerVariables.application.version + "." + Umbraco.Sys.ServerVariables.application.cdf;
var _op = (url.indexOf("?") > 0) ? "&" : "?";
url += _op + "umb__rnd=" + rnd;
}
return get(url, config);
};
return $delegate;
}
]);
}
]);
//Call a document callback if defined, this is sort of a dodgy hack to
// be able to configure angular values in the Default.cshtml
@@ -1,20 +1,22 @@
/**
* @ngdoc directive
* @name umbraco.directives.directive:autoScale
* @element div
* @function
*
* @description
* Resize div's automatically to fit to the bottom of the screen, as an optional parameter an y-axis offset can be set
* So if you only want to scale the div to 70 pixels from the bottom you pass "70"
*
* @example
<example module="umbraco.directives">
<file name="index.html">
<div auto-scale="70" class="input-block-level"></div>
</file>
</example>
*/
* @ngdoc directive
* @name umbraco.directives.directive:autoScale
* @element div
* @deprecated
* We plan to remove this directive in the next major version of umbraco (8.0). The directive is not recommended to use.
* @function
* @description
* Resize div's automatically to fit to the bottom of the screen, as an optional parameter an y-axis offset can be set
* So if you only want to scale the div to 70 pixels from the bottom you pass "70"
* @example
* <example module="umbraco.directives">
* <file name="index.html">
* <div auto-scale="70" class="input-block-level"></div>
* </file>
* </example>
**/
angular.module("umbraco.directives")
.directive('autoScale', function ($window) {
return function (scope, el, attrs) {
@@ -35,4 +37,4 @@ angular.module("umbraco.directives")
});
};
});
});
@@ -1,9 +1,12 @@
/**
* @ngdoc directive
* @name umbraco.directives.directive:umbPanel
* @name umbraco.directives.directive:detectFold
* @deprecated
* We plan to remove this directive in the next major version of umbraco (8.0). The directive is not recommended to use.
* @description This is used for the editor buttons to ensure they are displayed correctly if the horizontal overflow of the editor
* exceeds the height of the window
* exceeds the height of the window
**/
angular.module("umbraco.directives.html")
.directive('detectFold', function ($timeout, $log, windowResizeListener) {
return {
@@ -1,11 +1,14 @@
/**
/**
* @ngdoc directive
* @name umbraco.directives.directive:umbItemSorter
* @deprecated
* We plan to remove this directive in the next major version of umbraco (8.0). The directive is not recommended to use.
* @function
* @element ANY
* @restrict E
* @description A re-usable directive for sorting items
**/
function umbItemSorter(angularHelper) {
return {
scope: {
@@ -1,11 +1,14 @@
/**
* @ngdoc directive
* @name umbraco.directives.directive:umbContentName
* @deprecated
* We plan to remove this directive in the next major version of umbraco (8.0). The directive is not recommended to use.
* @restrict E
* @function
* @description
* Used by editors that require naming an entity. Shows a textbox/headline with a required validator within it's own form.
**/
angular.module("umbraco.directives")
.directive('umbContentName', function ($timeout, localizationService) {
return {
@@ -1,11 +1,14 @@
/**
* @ngdoc directive
* @name umbraco.directives.directive:umbHeader
* @deprecated
* We plan to remove this directive in the next major version of umbraco (8.0). The directive is not recommended to use.
* @restrict E
* @function
* @description
* The header on an editor that contains tabs using bootstrap tabs - THIS IS OBSOLETE, use umbTabHeader instead
**/
angular.module("umbraco.directives")
.directive('umbHeader', function ($parse, $timeout) {
return {
@@ -1,10 +1,13 @@
/**
/**
* @ngdoc directive
* @name umbraco.directives.directive:login
* @name umbraco.directives.directive:umbLogin
* @deprecated
* We plan to remove this directive in the next major version of umbraco (8.0). The directive is not recommended to use.
* @function
* @element ANY
* @restrict E
**/
function loginDirective() {
return {
restrict: "E", // restrict to an element
@@ -1,3 +1,13 @@
/**
* @ngdoc directive
* @name umbraco.directives.directive:umbOptionsMenu
* @deprecated
* We plan to remove this directive in the next major version of umbraco (8.0). The directive is not recommended to use.
* @function
* @element ANY
* @restrict E
**/
angular.module("umbraco.directives")
.directive('umbOptionsMenu', function ($injector, treeService, navigationService, umbModelMapper, appState) {
return {
@@ -1,8 +1,11 @@
/**
* @ngdoc directive
* @name umbraco.directives.directive:umbPhotoFolder
* @deprecated
* We plan to remove this directive in the next major version of umbraco (8.0). The directive is not recommended to use.
* @restrict E
**/
angular.module("umbraco.directives.html")
.directive('umbPhotoFolder', function($compile, $log, $timeout, $filter, umbPhotoFolderHelper) {
@@ -1,20 +1,24 @@
/**
* @ngdoc directive
* @name umbraco.directives.directive:umbSort
* @element div
* @function
*
* @description
* Resize div's automatically to fit to the bottom of the screen, as an optional parameter an y-axis offset can be set
* So if you only want to scale the div to 70 pixels from the bottom you pass "70"
*
* @example
<example module="umbraco.directives">
<file name="index.html">
<div umb-sort="70" class="input-block-level"></div>
</file>
</example>
*/
* @ngdoc directive
* @name umbraco.directives.directive:umbSort
* @deprecated
* We plan to remove this directive in the next major version of umbraco (8.0). The directive is not recommended to use.
*
* @element div
* @function
*
* @description
* Resize div's automatically to fit to the bottom of the screen, as an optional parameter an y-axis offset can be set
* So if you only want to scale the div to 70 pixels from the bottom you pass "70"
*
* @example
* <example module="umbraco.directives">
* <file name="index.html">
* <div umb-sort="70" class="input-block-level"></div>
* </file>
* </example>
**/
angular.module("umbraco.directives")
.value('umbSortContextInternal',{})
.directive('umbSort', function($log,umbSortContextInternal) {
@@ -165,4 +169,4 @@ angular.module("umbraco.directives")
}
};
});
});
@@ -1,8 +1,12 @@
/**
* @ngdoc directive
* @name umbraco.directives.directive:umbTabView
* @deprecated
* We plan to remove this directive in the next major version of umbraco (8.0). The directive is not recommended to use.
*
* @restrict E
**/
angular.module("umbraco.directives")
.directive('umbTabView', function($timeout, $log){
return {
@@ -1,8 +1,12 @@
/**
* @ngdoc directive
* @name umbraco.directives.directive:umbUploadDropzone
* @deprecated
* We plan to remove this directive in the next major version of umbraco (8.0). The directive is not recommended to use.
*
* @restrict E
**/
angular.module("umbraco.directives.html")
.directive('umbUploadDropzone', function(){
return {
@@ -17,7 +17,7 @@
if(convert){
element.html("<i class='icon-section " + convert + "'></i>");
}else{
element.html("<img src='images/tray/" + icon + "'>");
element.html("<img class='icon-section' src='images/tray/" + icon + "'>");
}
//it's a file, normally legacy so look in the icon tray images
}
@@ -1,3 +1,71 @@
/**
@ngdoc directive
@name umbraco.directives.directive:umbButton
@restrict E
@scope
@description
Use this directive to render an umbraco button. The directive can be used to generate all types of buttons, set type, style, translation, shortcut and much more.
<h3>Markup example</h3>
<pre>
<div ng-controller="My.Controller as vm">
<umb-button
action="vm.clickButton()"
type="button"
button-style="success"
state="vm.buttonState"
shortcut="ctrl+c"
label="My button"
disabled="vm.buttonState === 'busy'">
</umb-button>
</div>
</pre>
<h3>Controller example</h3>
<pre>
(function () {
"use strict";
function Controller(myService) {
var vm = this;
vm.buttonState = "init";
vm.clickButton = clickButton;
function clickButton() {
vm.buttonState = "busy";
myService.clickButton().then(function() {
vm.buttonState = "success";
}, function() {
vm.buttonState = "error";
});
}
}
angular.module("umbraco").controller("My.Controller", Controller);
})();
</pre>
@param {callback} action The button action which should be performed when the button is clicked.
@param {string=} href Url/Path to navigato to.
@param {string=} type Set the button type ("button" or "submit").
@param {string=} buttonStyle Set the style of the button. The directive uses the default bootstrap styles ("primary", "info", "success", "warning", "danger", "inverse", "link").
@param {string=} state Set a progress state on the button ("init", "busy", "success", "error").
@param {string=} shortcut Set a keyboard shortcut for the button ("ctrl+c").
@param {string=} label Set the button label.
@param {string=} labelKey Set a localization key to make a multi lingual button ("general_buttonText").
@param {string=} icon Set a button icon. Can only be used when buttonStyle is "link".
@param {boolean=} disabled Set to <code>true</code> to disable the button.
**/
(function() {
'use strict';
@@ -1,3 +1,94 @@
/**
@ngdoc directive
@name umbraco.directives.directive:umbButtonGroup
@restrict E
@scope
@description
Use this directive to render a button with a dropdown of alternative actions.
<h3>Markup example</h3>
<pre>
<div ng-controller="My.Controller as vm">
<umb-button-group
ng-if="vm.buttonGroup"
default-button="vm.buttonGroup.defaultButton"
sub-buttons="vm.buttonGroup.subButtons"
direction="down"
float="right">
</umb-button-group>
</div>
</pre>
<h3>Controller example</h3>
<pre>
(function () {
"use strict";
function Controller() {
var vm = this;
vm.buttonGroup = {
defaultButton: {
labelKey: "general_defaultButton",
hotKey: "ctrl+d",
hotKeyWhenHidden: true,
handler: function() {
// do magic here
}
},
subButtons: [
{
labelKey: "general_subButton",
hotKey: "ctrl+b",
hotKeyWhenHidden: true,
handler: function() {
// do magic here
}
}
]
};
}
angular.module("umbraco").controller("My.Controller", Controller);
})();
</pre>
<h3>Button model description</h3>
<ul>
<li>
<strong>labekKey</strong>
<small>(string)</small> -
Set a localization key to make a multi lingual button ("general_buttonText").
</li>
<li>
<strong>hotKey</strong>
<small>(array)</small> -
Set a keyboard shortcut for the button ("ctrl+c").
</li>
<li>
<strong>hotKeyWhenHidden</strong>
<small>(boolean)</small> -
As a default the hotkeys only works on elements visible in the UI. Set to <code>true</code> to set a hotkey on the hidden sub buttons.
</li>
<li>
<strong>handler</strong>
<small>(callback)</small> -
Set a callback to handle button click events.
</li>
</ul>
@param {object} defaultButton The model of the default button.
@param {array} subButtons Array of sub buttons.
@param {string=} state Set a progress state on the button ("init", "busy", "success", "error").
@param {string=} direction Set the direction of the dropdown ("up", "down").
@param {string=} float Set the float of the dropdown. ("left", "right").
**/
(function() {
'use strict';
@@ -1,3 +1,43 @@
/**
@ngdoc directive
@name umbraco.directives.directive:umbEditorSubHeader
@restrict E
@description
Use this directive to construct a sub header in the main editor window.
The sub header is sticky and will follow along down the page when scrolling.
<h3>Markup example</h3>
<pre>
<div ng-controller="MySection.Controller as vm">
<form name="mySectionForm" novalidate>
<umb-editor-view>
<umb-editor-container>
<umb-editor-sub-header>
// sub header content here
</umb-editor-sub-header>
</umb-editor-container>
</umb-editor-view>
</form>
</div>
</pre>
<h3>Use in combination with</h3>
<ul>
<li>{@link umbraco.directives.directive:umbEditorSubHeaderContentLeft umbEditorSubHeaderContentLeft}</li>
<li>{@link umbraco.directives.directive:umbEditorSubHeaderContentRight umbEditorSubHeaderContentRight}</li>
<li>{@link umbraco.directives.directive:umbEditorSubHeaderSection umbEditorSubHeaderSection}</li>
</ul>
**/
(function() {
'use strict';
@@ -1,3 +1,50 @@
/**
@ngdoc directive
@name umbraco.directives.directive:umbEditorSubHeaderContentLeft
@restrict E
@description
Use this directive to left align content in a sub header in the main editor window.
<h3>Markup example</h3>
<pre>
<div ng-controller="MySection.Controller as vm">
<form name="mySectionForm" novalidate>
<umb-editor-view>
<umb-editor-container>
<umb-editor-sub-header>
<umb-editor-sub-header-content-left>
// left content here
</umb-editor-sub-header-content-left>
<umb-editor-sub-header-content-right>
// right content here
</umb-editor-sub-header-content-right>
</umb-editor-sub-header>
</umb-editor-container>
</umb-editor-view>
</form>
</div>
</pre>
<h3>Use in combination with</h3>
<ul>
<li>{@link umbraco.directives.directive:umbEditorSubHeader umbEditorSubHeader}</li>
<li>{@link umbraco.directives.directive:umbEditorSubHeaderContentRight umbEditorSubHeaderContentRight}</li>
<li>{@link umbraco.directives.directive:umbEditorSubHeaderSection umbEditorSubHeaderSection}</li>
</ul>
**/
(function() {
'use strict';
@@ -1,3 +1,50 @@
/**
@ngdoc directive
@name umbraco.directives.directive:umbEditorSubHeaderContentRight
@restrict E
@description
Use this directive to rigt align content in a sub header in the main editor window.
<h3>Markup example</h3>
<pre>
<div ng-controller="MySection.Controller as vm">
<form name="mySectionForm" novalidate>
<umb-editor-view>
<umb-editor-container>
<umb-editor-sub-header>
<umb-editor-sub-header-content-left>
// left content here
</umb-editor-sub-header-content-left>
<umb-editor-sub-header-content-right>
// right content here
</umb-editor-sub-header-content-right>
</umb-editor-sub-header>
</umb-editor-container>
</umb-editor-view>
</form>
</div>
</pre>
<h3>Use in combination with</h3>
<ul>
<li>{@link umbraco.directives.directive:umbEditorSubHeader umbEditorSubHeader}</li>
<li>{@link umbraco.directives.directive:umbEditorSubHeaderContentLeft umbEditorSubHeaderContentLeft}</li>
<li>{@link umbraco.directives.directive:umbEditorSubHeaderSection umbEditorSubHeaderSection}</li>
</ul>
**/
(function() {
'use strict';
@@ -1,3 +1,58 @@
/**
@ngdoc directive
@name umbraco.directives.directive:umbEditorSubHeaderSection
@restrict E
@description
Use this directive to create sections, divided by borders, in a sub header in the main editor window.
<h3>Markup example</h3>
<pre>
<div ng-controller="MySection.Controller as vm">
<form name="mySectionForm" novalidate>
<umb-editor-view>
<umb-editor-container>
<umb-editor-sub-header>
<umb-editor-sub-header-content-right>
<umb-editor-sub-header-section>
// section content here
</umb-editor-sub-header-section>
<umb-editor-sub-header-section>
// section content here
</umb-editor-sub-header-section>
<umb-editor-sub-header-section>
// section content here
</umb-editor-sub-header-section>
</umb-editor-sub-header-content-right>
</umb-editor-sub-header>
</umb-editor-container>
</umb-editor-view>
</form>
</div>
</pre>
<h3>Use in combination with</h3>
<ul>
<li>{@link umbraco.directives.directive:umbEditorSubHeader umbEditorSubHeader}</li>
<li>{@link umbraco.directives.directive:umbEditorSubHeaderContentLeft umbEditorSubHeaderContentLeft}</li>
<li>{@link umbraco.directives.directive:umbEditorSubHeaderContentRight umbEditorSubHeaderContentRight}</li>
</ul>
**/
(function() {
'use strict';
@@ -1,3 +1,47 @@
/**
@ngdoc directive
@name umbraco.directives.directive:umbBreadcrumbs
@restrict E
@scope
@description
Use this directive to generate a list of breadcrumbs.
<h3>Markup example</h3>
<pre>
<div ng-controller="My.Controller as vm">
<umb-breadcrumbs
ng-if="vm.ancestors && vm.ancestors.length > 0"
ancestors="vm.ancestors"
entity-type="content">
</umb-breadcrumbs>
</div>
</pre>
<h3>Controller example</h3>
<pre>
(function () {
"use strict";
function Controller(myService) {
var vm = this;
vm.ancestors = [];
myService.getAncestors().then(function(ancestors){
vm.ancestors = ancestors;
});
}
angular.module("umbraco").controller("My.Controller", Controller);
})();
</pre>
@param {array} ancestors Array of ancestors
@param {string} entityType The content entity type (member, media, content).
**/
(function() {
'use strict';
@@ -1,3 +1,42 @@
/**
@ngdoc directive
@name umbraco.directives.directive:umbEditorContainer
@restrict E
@description
Use this directive to construct a main content area inside the main editor window.
<h3>Markup example</h3>
<pre>
<div ng-controller="Umbraco.Controller as vm">
<umb-editor-view>
<umb-editor-header
// header configuration>
</umb-editor-header>
<umb-editor-container>
// main content here
</umb-editor-container>
<umb-editor-footer>
// footer content here
</umb-editor-footer>
</umb-editor-view>
</div>
</pre>
<h3>Use in combination with</h3>
<ul>
<li>{@link umbraco.directives.directive:umbEditorView umbEditorView}</li>
<li>{@link umbraco.directives.directive:umbEditorHeader umbEditorHeader}</li>
<li>{@link umbraco.directives.directive:umbEditorFooter umbEditorFooter}</li>
</ul>
**/
(function() {
'use strict';
@@ -1,3 +1,48 @@
/**
@ngdoc directive
@name umbraco.directives.directive:umbEditorFooter
@restrict E
@description
Use this directive to construct a footer inside the main editor window.
<h3>Markup example</h3>
<pre>
<div ng-controller="MySection.Controller as vm">
<form name="mySectionForm" novalidate>
<umb-editor-view>
<umb-editor-header
// header configuration>
</umb-editor-header>
<umb-editor-container>
// main content here
</umb-editor-container>
<umb-editor-footer>
// footer content here
</umb-editor-footer>
</umb-editor-view>
</form>
</div>
</pre>
<h3>Use in combination with</h3>
<ul>
<li>{@link umbraco.directives.directive:umbEditorView umbEditorView}</li>
<li>{@link umbraco.directives.directive:umbEditorHeader umbEditorHeader}</li>
<li>{@link umbraco.directives.directive:umbEditorContainer umbEditorContainer}</li>
<li>{@link umbraco.directives.directive:umbEditorFooterContentLeft umbEditorFooterContentLeft}</li>
<li>{@link umbraco.directives.directive:umbEditorFooterContentRight umbEditorFooterContentRight}</li>
</ul>
**/
(function() {
'use strict';
@@ -1,3 +1,48 @@
/**
@ngdoc directive
@name umbraco.directives.directive:umbEditorFooterContentLeft
@restrict E
@description
Use this directive to align content left inside the main editor footer.
<h3>Markup example</h3>
<pre>
<div ng-controller="MySection.Controller as vm">
<form name="mySectionForm" novalidate>
<umb-editor-view>
<umb-editor-footer>
<umb-editor-footer-content-left>
// align content left
</umb-editor-footer-content-left>
<umb-editor-footer-content-right>
// align content right
</umb-editor-footer-content-right>
</umb-editor-footer>
</umb-editor-view>
</form>
</div>
</pre>
<h3>Use in combination with</h3>
<ul>
<li>{@link umbraco.directives.directive:umbEditorView umbEditorView}</li>
<li>{@link umbraco.directives.directive:umbEditorHeader umbEditorHeader}</li>
<li>{@link umbraco.directives.directive:umbEditorContainer umbEditorContainer}</li>
<li>{@link umbraco.directives.directive:umbEditorFooter umbEditorFooter}</li>
<li>{@link umbraco.directives.directive:umbEditorFooterContentRight umbEditorFooterContentRight}</li>
</ul>
**/
(function() {
'use strict';
@@ -1,3 +1,48 @@
/**
@ngdoc directive
@name umbraco.directives.directive:umbEditorFooterContentRight
@restrict E
@description
Use this directive to align content right inside the main editor footer.
<h3>Markup example</h3>
<pre>
<div ng-controller="MySection.Controller as vm">
<form name="mySectionForm" novalidate>
<umb-editor-view>
<umb-editor-footer>
<umb-editor-footer-content-left>
// align content left
</umb-editor-footer-content-left>
<umb-editor-footer-content-right>
// align content right
</umb-editor-footer-content-right>
</umb-editor-footer>
</umb-editor-view>
</form>
</div>
</pre>
<h3>Use in combination with</h3>
<ul>
<li>{@link umbraco.directives.directive:umbEditorView umbEditorView}</li>
<li>{@link umbraco.directives.directive:umbEditorHeader umbEditorHeader}</li>
<li>{@link umbraco.directives.directive:umbEditorContainer umbEditorContainer}</li>
<li>{@link umbraco.directives.directive:umbEditorFooter umbEditorFooter}</li>
<li>{@link umbraco.directives.directive:umbEditorFooterContentLeft umbEditorFooterContentLeft}</li>
</ul>
**/
(function() {
'use strict';
@@ -1,3 +1,206 @@
/**
@ngdoc directive
@name umbraco.directives.directive:umbEditorHeader
@restrict E
@scope
@description
Use this directive to construct a header inside the main editor window.
<h3>Markup example</h3>
<pre>
<div ng-controller="MySection.Controller as vm">
<form name="mySectionForm" novalidate>
<umb-editor-view>
<umb-editor-header
name="vm.content.name"
hide-alias="true"
hide-description="true"
hide-icon="true">
</umb-editor-header>
<umb-editor-container>
// main content here
</umb-editor-container>
<umb-editor-footer>
// footer content here
</umb-editor-footer>
</umb-editor-view>
</form>
</div>
</pre>
<h3>Markup example - with tabs</h3>
<pre>
<div ng-controller="MySection.Controller as vm">
<form name="mySectionForm" val-form-manager novalidate>
<umb-editor-view umb-tabs>
<umb-editor-header
name="vm.content.name"
tabs="vm.content.tabs"
hide-alias="true"
hide-description="true"
hide-icon="true">
</umb-editor-header>
<umb-editor-container>
<umb-tabs-content class="form-horizontal" view="true">
<umb-tab id="tab{{tab.id}}" ng-repeat="tab in vm.content.tabs" rel="{{tab.id}}">
<div ng-show="tab.alias==='tab1'">
// tab 1 content
</div>
<div ng-show="tab.alias==='tab2'">
// tab 2 content
</div>
</umb-tab>
</umb-tabs-content>
</umb-editor-container>
<umb-editor-footer>
// footer content here
</umb-editor-footer>
</umb-editor-view>
</form>
</div>
</pre>
<h3>Controller example - with tabs</h3>
<pre>
(function () {
"use strict";
function Controller() {
var vm = this;
vm.content = {
name: "",
tabs: [
{
id: 1,
label: "Tab 1",
alias: "tab1",
active: true
},
{
id: 2,
label: "Tab 2",
alias: "tab2",
active: false
}
]
};
}
angular.module("umbraco").controller("MySection.Controller", Controller);
})();
</pre>
<h3>Markup example - with sub views</h3>
<pre>
<div ng-controller="MySection.Controller as vm">
<form name="mySectionForm" val-form-manager novalidate>
<umb-editor-view>
<umb-editor-header
name="vm.content.name"
navigation="vm.content.navigation"
hide-alias="true"
hide-description="true"
hide-icon="true">
</umb-editor-header>
<umb-editor-container>
<umb-editor-sub-views
sub-views="vm.content.navigation"
model="vm.content">
</umb-editor-sub-views>
</umb-editor-container>
<umb-editor-footer>
// footer content here
</umb-editor-footer>
</umb-editor-view>
</form>
</div>
</pre>
<h3>Controller example - with sub views</h3>
<pre>
(function () {
"use strict";
function Controller() {
var vm = this;
vm.content = {
name: "",
navigation: [
{
"name": "Section 1",
"icon": "icon-document-dashed-line",
"view": "/App_Plugins/path/to/html.html",
"active": true
},
{
"name": "Section 2",
"icon": "icon-list",
"view": "/App_Plugins/path/to/html.html",
}
]
};
}
angular.module("umbraco").controller("MySection.Controller", Controller);
})();
</pre>
<h3>Use in combination with</h3>
<ul>
<li>{@link umbraco.directives.directive:umbEditorView umbEditorView}</li>
<li>{@link umbraco.directives.directive:umbEditorContainer umbEditorContainer}</li>
<li>{@link umbraco.directives.directive:umbEditorFooter umbEditorFooter}</li>
</ul>
@param {string} name The content name.
@param {array=} tabs Array of tabs. See example above.
@param {array=} navigation Array of sub views. See example above.
@param {boolean=} nameLocked Set to <code>true</code> to lock the name.
@param {object=} menu Add a context menu to the editor.
@param {string=} icon Show and edit the content icon. Opens an overlay to change the icon.
@param {boolean=} hideIcon Set to <code>true</code> to hide icon.
@param {string=} alias show and edit the content alias.
@param {boolean=} hideAlias Set to <code>true</code> to hide alias.
@param {string=} description Add a description to the content.
@param {boolean=} hideDescription Set to <code>true</code> to hide description.
**/
(function() {
'use strict';
@@ -1,3 +1,66 @@
/**
@ngdoc directive
@name umbraco.directives.directive:umbEditorView
@restrict E
@scope
@description
Use this directive to construct the main editor window.
<h3>Markup example</h3>
<pre>
<div ng-controller="MySection.Controller as vm">
<form name="mySectionForm" novalidate>
<umb-editor-view>
<umb-editor-header
name="vm.content.name"
hide-alias="true"
hide-description="true"
hide-icon="true">
</umb-editor-header>
<umb-editor-container>
// main content here
</umb-editor-container>
<umb-editor-footer>
// footer content here
</umb-editor-footer>
</umb-editor-view>
</form>
</div>
</pre>
<h3>Controller example</h3>
<pre>
(function () {
"use strict";
function Controller() {
var vm = this;
}
angular.module("umbraco").controller("MySection.Controller", Controller);
})();
</pre>
<h3>Use in combination with</h3>
<ul>
<li>{@link umbraco.directives.directive:umbEditorHeader umbEditorHeader}</li>
<li>{@link umbraco.directives.directive:umbEditorContainer umbEditorContainer}</li>
<li>{@link umbraco.directives.directive:umbEditorFooter umbEditorFooter}</li>
</ul>
**/
(function() {
'use strict';
@@ -1,7 +1,8 @@
/**
* @ngdoc directive
* @name umbraco.directives.directive:headline
**/
* @ngdoc directive
* @name umbraco.directives.directive:hotkey
**/
angular.module("umbraco.directives")
.directive('hotkey', function($window, keyboardService, $log) {
@@ -1,13 +1,23 @@
/**
* @ngdoc directive
* @name umbraco.directives.directive:preventDefault
@ngdoc directive
@name umbraco.directives.directive:preventDefault
@description
Use this directive to prevent default action of an element. Effectively implementing <a href="https://api.jquery.com/event.preventdefault/">jQuery's preventdefault</a>
<h3>Markup example</h3>
<pre>
<a href="https://umbraco.com" prevent-default>Don't go to Umbraco.com</a>
</pre>
**/
angular.module("umbraco.directives")
.directive('preventDefault', function() {
return function(scope, element, attrs) {
var enabled = true;
//check if there's a value for the attribute, if there is and it's false then we conditionally don't
//check if there's a value for the attribute, if there is and it's false then we conditionally don't
//prevent default.
if (attrs.preventDefault) {
attrs.$observe("preventDefault", function (newVal) {
@@ -26,4 +36,4 @@ angular.module("umbraco.directives")
}
});
};
});
});
@@ -1,6 +1,6 @@
/**
* @ngdoc directive
* @name umbraco.directives.directive:umbProperty
* @name umbraco.directives.directive:umbControlGroup
* @restrict E
**/
angular.module("umbraco.directives.html")
@@ -1,6 +1,6 @@
/**
* @ngdoc directive
* @name umbraco.directives.directive:umbProperty
* @name umbraco.directives.directive:umbPane
* @restrict E
**/
angular.module("umbraco.directives.html")
@@ -1,10 +1,9 @@
/**
* @ngdoc directive
* @name umbraco.directives.directive:umbCropsy
* @name umbraco.directives.directive:umbImageGravity
* @restrict E
* @function
* @description
* Used by editors that require naming an entity. Shows a textbox/headline with a required validator within it's own form.
**/
angular.module("umbraco.directives")
.directive('umbImageGravity', function ($timeout, localizationService, $log) {
@@ -1,10 +1,9 @@
/**
* @ngdoc directive
* @name umbraco.directives.directive:umbCropsy
* @name umbraco.directives.directive:umbImageThumbnail
* @restrict E
* @function
* @description
* Used by editors that require naming an entity. Shows a textbox/headline with a required validator within it's own form.
**/
angular.module("umbraco.directives")
.directive('umbImageThumbnail',
@@ -1,8 +1,409 @@
/**
* @ngdoc directive
* @name umbraco.directives.directive:umbProperty
* @restrict E
**/
@ngdoc directive
@name umbraco.directives.directive:umbOverlay
@restrict E
@scope
@description
<h3>Markup example</h3>
<pre>
<div ng-controller="My.Controller as vm">
<button type="button" ng-click="vm.openOverlay()"></button>
<umb-overlay
ng-if="vm.overlay.show"
model="vm.overlay"
view="vm.overlay.view"
position="right">
</umb-overlay>
</div>
</pre>
<h3>Controller example</h3>
<pre>
(function () {
"use strict";
function Controller() {
var vm = this;
vm.openOverlay = openOverlay;
function openOverlay() {
vm.overlay = {
view: "mediapicker",
show: true,
submit: function(model) {
vm.overlay.show = false;
vm.overlay = null;
},
close: function(oldModel) {
vm.overlay.show = false;
vm.overlay = null;
}
}
};
}
angular.module("umbraco").controller("My.Controller", Controller);
})();
</pre>
<h1>General Options</h1>
Lorem ipsum dolor sit amet..
<table>
<thead>
<tr>
<th>Param</th>
<th>Type</th>
<th>Details</th>
</tr>
</thead>
<tr>
<td>model.title</td>
<td>String</td>
<td>Set the title of the overlay.</td>
</tr>
<tr>
<td>model.subTitle</td>
<td>String</td>
<td>Set the subtitle of the overlay.</td>
</tr>
<tr>
<td>model.submitButtonLabel</td>
<td>String</td>
<td>Set an alternate submit button text</td>
</tr>
<tr>
<td>model.submitButtonLabelKey</td>
<td>String</td>
<td>Set an alternate submit button label key for localized texts</td>
</tr>
<tr>
<td>model.hideSubmitButton</td>
<td>Boolean</td>
<td>Hides the submit button</td>
</tr>
<tr>
<td>model.closeButtonLabel</td>
<td>String</td>
<td>Set an alternate close button text</td>
</tr>
<tr>
<td>model.closeButtonLabelKey</td>
<td>String</td>
<td>Set an alternate close button label key for localized texts</td>
</tr>
<tr>
<td>model.show</td>
<td>Boolean</td>
<td>Show/hide the overlay</td>
</tr>
<tr>
<td>model.submit</td>
<td>Function</td>
<td>Callback function when the overlay submits. Returns the overlay model object</td>
</tr>
<tr>
<td>model.close</td>
<td>Function</td>
<td>Callback function when the overlay closes. Returns a copy of the overlay model object before being modified</td>
</tr>
</table>
<h1>Content Picker</h1>
Opens a content picker.</br>
<strong>view: </strong>contentpicker
<table>
<thead>
<tr>
<th>Param</th>
<th>Type</th>
<th>Details</th>
</tr>
</thead>
<tr>
<td>model.multiPicker</td>
<td>Boolean</td>
<td>Pick one or multiple items</td>
</tr>
</table>
<table>
<thead>
<tr>
<th>Returns</th>
<th>Type</th>
<th>Details</th>
</tr>
</thead>
<tr>
<td>model.selection</td>
<td>Array</td>
<td>Array of content objects</td>
</tr>
</table>
<h1>Icon Picker</h1>
Opens an icon picker.</br>
<strong>view: </strong>iconpicker
<table>
<thead>
<tr>
<th>Returns</th>
<th>Type</th>
<th>Details</th>
</tr>
</thead>
<tr>
<td>model.icon</td>
<td>String</td>
<td>The icon class</td>
</tr>
</table>
<h1>Item Picker</h1>
Opens an item picker.</br>
<strong>view: </strong>itempicker
<table>
<thead>
<tr>
<th>Param</th>
<th>Type</th>
<th>Details</th>
</tr>
</thead>
<tbody>
<tr>
<td>model.availableItems</td>
<td>Array</td>
<td>Array of available items</td>
</tr>
<tr>
<td>model.selectedItems</td>
<td>Array</td>
<td>Array of selected items. When passed in the selected items will be filtered from the available items.</td>
</tr>
<tr>
<td>model.filter</td>
<td>Boolean</td>
<td>Set to false to hide the filter</td>
</tr>
</tbody>
</table>
<table>
<thead>
<tr>
<th>Returns</th>
<th>Type</th>
<th>Details</th>
</tr>
</thead>
<tr>
<td>model.selectedItem</td>
<td>Object</td>
<td>The selected item</td>
</tr>
</table>
<h1>Macro Picker</h1>
Opens a media picker.</br>
<strong>view: </strong>macropicker
<table>
<thead>
<tr>
<th>Param</th>
<th>Type</th>
<th>Details</th>
</tr>
</thead>
<tbody>
<tr>
<td>model.dialogData</td>
<td>Object</td>
<td>Object which contains array of allowedMacros. Set to <code>null</code> to allow all.</td>
</tr>
</tbody>
</table>
<table>
<thead>
<tr>
<th>Returns</th>
<th>Type</th>
<th>Details</th>
</tr>
</thead>
<tbody>
<tr>
<td>model.macroParams</td>
<td>Array</td>
<td>Array of macro params</td>
</tr>
<tr>
<td>model.selectedMacro</td>
<td>Object</td>
<td>The selected macro</td>
</tr>
</tbody>
</table>
<h1>Media Picker</h1>
Opens a media picker.</br>
<strong>view: </strong>mediapicker
<table>
<thead>
<tr>
<th>Param</th>
<th>Type</th>
<th>Details</th>
</tr>
</thead>
<tbody>
<tr>
<td>model.multiPicker</td>
<td>Boolean</td>
<td>Pick one or multiple items</td>
</tr>
<tr>
<td>model.onlyImages</td>
<td>Boolean</td>
<td>Only display files that have an image file-extension</td>
</tr>
<tr>
<td>model.disableFolderSelect</td>
<td>Boolean</td>
<td>Disable folder selection</td>
</tr>
</tbody>
</table>
<table>
<thead>
<tr>
<th>Returns</th>
<th>Type</th>
<th>Details</th>
</tr>
</thead>
<tbody>
<tr>
<td>model.selectedImages</td>
<td>Array</td>
<td>Array of selected images</td>
</tr>
</tbody>
</table>
<h1>Member Group Picker</h1>
Opens a member group picker.</br>
<strong>view: </strong>membergrouppicker
<table>
<thead>
<tr>
<th>Param</th>
<th>Type</th>
<th>Details</th>
</tr>
</thead>
<tbody>
<tr>
<td>model.multiPicker</td>
<td>Boolean</td>
<td>Pick one or multiple items</td>
</tr>
</tbody>
</table>
<table>
<thead>
<tr>
<th>Returns</th>
<th>Type</th>
<th>Details</th>
</tr>
</thead>
<tbody>
<tr>
<td>model.selectedMemberGroup</td>
<td>String</td>
<td>The selected member group</td>
</tr>
<tr>
<td>model.selectedMemberGroups (multiPicker)</td>
<td>Array</td>
<td>The selected member groups</td>
</tr>
</tbody>
</table>
<h1>Member Picker</h1>
Opens a member picker. </br>
<strong>view: </strong>memberpicker
<table>
<thead>
<tr>
<th>Param</th>
<th>Type</th>
<th>Details</th>
</tr>
</thead>
<tbody>
<tr>
<td>model.multiPicker</td>
<td>Boolean</td>
<td>Pick one or multiple items</td>
</tr>
</tbody>
</table>
<table>
<thead>
<tr>
<th>Returns</th>
<th>Type</th>
<th>Details</th>
</tr>
</thead>
<tbody>
<tr>
<td>model.selection</td>
<td>Array</td>
<td>Array of selected members/td>
</tr>
</tbody>
</table>
<h1>YSOD</h1>
Opens an overlay to show a custom YSOD. </br>
<strong>view: </strong>ysod
<table>
<thead>
<tr>
<th>Param</th>
<th>Type</th>
<th>Details</th>
</tr>
</thead>
<tbody>
<tr>
<td>model.error</td>
<td>Object</td>
<td>Error object</td>
</tr>
</tbody>
</table>
@param {object} model Overlay options.
@param {string} view Path to view or one of the default view names.
@param {string} position The overlay position ("left", "right", "center": "target").
**/
(function() {
'use strict';
@@ -1,3 +1,52 @@
/**
@ngdoc directive
@name umbraco.directives.directive:umbGenerateAlias
@restrict E
@scope
@description
Use this directive to generate a camelCased umbraco alias.
When the aliasFrom value is changed the directive will get a formatted alias from the server and update the alias model. If "enableLock" is set to <code>true</code>
the directive will use {@link umbraco.directives.directive:umbLockedField umbLockedField} to lock and unlock the alias.
<h3>Markup example</h3>
<pre>
<div ng-controller="My.Controller as vm">
<input type="text" ng-model="vm.name" />
<umb-generate-alias
enable-lock="true"
alias-from="vm.name"
alias="vm.alias">
</umb-generate-alias>
</div>
</pre>
<h3>Controller example</h3>
<pre>
(function () {
"use strict";
function Controller() {
var vm = this;
vm.name = "";
vm.alias = "";
}
angular.module("umbraco").controller("My.Controller", Controller);
})();
</pre>
@param {string} alias (<code>binding</code>): The model where the alias is bound.
@param {string} aliasFrom (<code>binding</code>): The model to generate the alias from.
@param {boolean=} enableLock (<code>binding</code>): Set to <code>true</code> to add a lock next to the alias from where it can be unlocked and changed.
**/
angular.module("umbraco.directives")
.directive('umbGenerateAlias', function ($timeout, entityResource) {
return {
@@ -1,3 +1,117 @@
/**
@ngdoc directive
@name umbraco.directives.directive:umbChildSelector
@restrict E
@scope
@description
Use this directive to render a ui component for selecting child items to a parent node.
<h3>Markup example</h3>
<pre>
<div ng-controller="My.Controller as vm">
<umb-child-selector
selected-children="vm.selectedChildren"
available-children="vm.availableChildren"
parent-name="vm.name"
parent-icon="vm.icon"
parent-id="vm.id"
on-add="vm.addChild"
on-remove="vm.removeChild">
</umb-child-selector>
<!-- use overlay to select children from -->
<umb-overlay
ng-if="vm.overlay.show"
model="vm.overlay"
position="target"
view="vm.overlay.view">
</umb-overlay>
</div>
</pre>
<h3>Controller example</h3>
<pre>
(function () {
"use strict";
function Controller() {
var vm = this;
vm.id = 1;
vm.name = "My Parent element";
vm.icon = "icon-document";
vm.selectedChildren = [];
vm.availableChildren = [
{
id: 1,
alias: "item1",
name: "Item 1",
icon: "icon-document"
},
{
id: 2,
alias: "item2",
name: "Item 2",
icon: "icon-document"
}
];
vm.addChild = addChild;
vm.removeChild = removeChild;
function addChild($event) {
vm.overlay = {
view: "itempicker",
title: "Choose child",
availableItems: vm.availableChildren,
selectedItems: vm.selectedChildren,
event: $event,
show: true,
submit: function(model) {
// add selected child
vm.selectedChildren.push(model.selectedItem);
// close overlay
vm.overlay.show = false;
vm.overlay = null;
}
};
}
function removeChild($index) {
vm.selectedChildren.splice($index, 1);
}
}
angular.module("umbraco").controller("My.Controller", Controller);
})();
</pre>
@param {array} selectedChildren (<code>binding</code>): Array of selected children.
@param {array} availableChildren (<code>binding</code>: Array of items available for selection.
@param {string} parentName (<code>binding</code>): The parent name.
@param {string} parentIcon (<code>binding</code>): The parent icon.
@param {number} parentId (<code>binding</code>): The parent id.
@param {callback} onRemove (<code>binding</code>): Callback when the remove button is clicked on an item.
<h3>The callback returns:</h3>
<ul>
<li><code>child</code>: The selected item.</li>
<li><code>$index</code>: The selected item index.</li>
</ul>
@param {callback} onAdd (<code>binding</code>): Callback when the add button is clicked.
<h3>The callback returns:</h3>
<ul>
<li><code>$event</code>: The select event.</li>
</ul>
**/
(function() {
'use strict';
@@ -1,3 +1,69 @@
/**
@ngdoc directive
@name umbraco.directives.directive:umbConfirmAction
@restrict E
@scope
@description
<p>Use this directive to toggle a confirmation prompt for an action.
The prompt consists of a checkmark and a cross to confirm or cancel the action.
The prompt can be opened in four direction up, down, left or right.</p>
<h3>Markup example</h3>
<pre>
<div ng-controller="My.Controller as vm">
<div class="my-action" style="position:relative;">
<i class="icon-trash" ng-click="vm.showPrompt()"></i>
<umb-confirm-action
ng-if="vm.promptIsVisible"
direction="left"
on-confirm="vm.confirmAction()"
on-cancel="vm.hidePrompt()">
</umb-confirm-action>
</div>
</div>
</pre>
<h3>Controller example</h3>
<pre>
(function () {
"use strict";
function Controller() {
var vm = this;
vm.promptIsVisible = false;
vm.confirmAction = confirmAction;
vm.showPrompt = showPrompt;
vm.hidePrompt = hidePrompt;
function confirmAction() {
// confirm logic here
}
function showPrompt() {
vm.promptIsVisible = true;
}
function hidePrompt() {
vm.promptIsVisible = false;
}
}
angular.module("umbraco").controller("My.Controller", Controller);
})();
</pre>
@param {string} direction The direction the prompt opens ("up", "down", "left", "right").
@param {callback} onConfirm Callback when the checkmark is clicked.
@param {callback} onCancel Callback when the cross is clicked.
**/
(function() {
'use strict';
@@ -1,3 +1,108 @@
/**
@ngdoc directive
@name umbraco.directives.directive:umbContentGrid
@restrict E
@scope
@description
Use this directive to generate a list of content items presented as a flexbox grid.
<h3>Markup example</h3>
<pre>
<div ng-controller="My.Controller as vm">
<umb-content-grid
content="vm.contentItems"
content-properties="vm.includeProperties"
on-click="vm.selectItem"
on-click-name="vm.clickItem">
</umb-content-grid>
</div>
</pre>
<h3>Controller example</h3>
<pre>
(function () {
"use strict";
function Controller() {
var vm = this;
vm.contentItems = [
{
"name": "Cape",
"published": true,
"icon": "icon-document",
"updateDate": "15-02-2016",
"owner": "Mr. Batman",
"selected": false
},
{
"name": "Utility Belt",
"published": true,
"icon": "icon-document",
"updateDate": "15-02-2016",
"owner": "Mr. Batman",
"selected": false
},
{
"name": "Cave",
"published": true,
"icon": "icon-document",
"updateDate": "15-02-2016",
"owner": "Mr. Batman",
"selected": false
}
];
vm.includeProperties = [
{
"alias": "updateDate",
"header": "Last edited"
},
{
"alias": "owner",
"header": "Created by"
}
];
vm.clickItem = clickItem;
vm.selectItem = selectItem;
function clickItem(item, $event, $index){
// do magic here
}
function selectItem(item, $event, $index) {
// set item.selected = true; to select the item
// do magic here
}
}
angular.module("umbraco").controller("My.Controller", Controller);
})();
</pre>
@param {array} content (<code>binding</code>): Array of content items.
@param {array=} contentProperties (<code>binding</code>): Array of content item properties to include in the item. If left empty the item will only show the item icon and name.
@param {callback=} onClick (<code>binding</code>): Callback method to handle click events on the content item.
<h3>The callback returns:</h3>
<ul>
<li><code>item</code>: The clicked item</li>
<li><code>$event</code>: The select event</li>
<li><code>$index</code>: The item index</li>
</ul>
@param {callback=} onClickName (<code>binding</code>): Callback method to handle click events on the checkmark icon.
<h3>The callback returns:</h3>
<ul>
<li><code>item</code>: The selected item</li>
<li><code>$event</code>: The select event</li>
<li><code>$index</code>: The item index</li>
</ul>
**/
(function() {
'use strict';
@@ -1,3 +1,29 @@
/**
@ngdoc directive
@name umbraco.directives.directive:umbEmptyState
@restrict E
@scope
@description
Use this directive to show an empty state message.
<h3>Markup example</h3>
<pre>
<div ng-controller="My.Controller as vm">
<umb-empty-state
ng-if="!vm.items"
position="center">
// Empty state content
</umb-empty-state>
</div>
</pre>
@param {string=} size Set the size of the text ("small", "large").
@param {string=} position Set the position of the text ("center").
**/
(function() {
'use strict';
@@ -1,3 +1,83 @@
/**
@ngdoc directive
@name umbraco.directives.directive:umbFolderGrid
@restrict E
@scope
@description
Use this directive to generate a list of folders presented as a flexbox grid.
<h3>Markup example</h3>
<pre>
<div ng-controller="My.Controller as vm">
<umb-folder-grid
ng-if="vm.folders.length > 0"
folders="vm.folders"
on-click="vm.clickFolder"
on-select="vm.selectFolder">
</umb-folder-grid>
</div>
</pre>
<h3>Controller example</h3>
<pre>
(function () {
"use strict";
function Controller(myService) {
var vm = this;
vm.folders = [
{
"name": "Folder 1",
"icon": "icon-folder",
"selected": false
},
{
"name": "Folder 2",
"icon": "icon-folder",
"selected": false
}
];
vm.clickFolder = clickFolder;
vm.selectFolder = selectFolder;
myService.getFolders().then(function(folders){
vm.folders = folders;
});
function clickFolder(folder){
// Execute when clicking folder name/link
}
function selectFolder(folder, event, index) {
// Execute when clicking folder
// set folder.selected = true; to show checkmark icon
}
}
angular.module("umbraco").controller("My.Controller", Controller);
})();
</pre>
@param {array} folders (<code>binding</code>): Array of folders
@param {callback=} onClick (<code>binding</code>): Callback method to handle click events on the folder.
<h3>The callback returns:</h3>
<ul>
<li><code>folder</code>: The selected folder</li>
</ul>
@param {callback=} onSelect (<code>binding</code>): Callback method to handle click events on the checkmark icon.
<h3>The callback returns:</h3>
<ul>
<li><code>folder</code>: The selected folder</li>
<li><code>$event</code>: The select event</li>
<li><code>$index</code>: The folder index</li>
</ul>
**/
(function() {
'use strict';
@@ -1,3 +1,112 @@
/**
@ngdoc directive
@name umbraco.directives.directive:umbkeyboardShortcutsOverview
@restrict E
@scope
@description
<p>Use this directive to show an overview of keyboard shortcuts in an editor.
The directive will render an overview trigger wich shows how the overview is opened.
When this combination is hit an overview is opened with shortcuts based on the model sent to the directive.</p>
<h3>Markup example</h3>
<pre>
<div ng-controller="My.Controller as vm">
<umb-keyboard-shortcuts-overview
model="vm.keyboardShortcutsOverview">
</umb-keyboard-shortcuts-overview>
</div>
</pre>
<h3>Controller example</h3>
<pre>
(function () {
"use strict";
function Controller() {
var vm = this;
vm.keyboardShortcutsOverview = [
{
"name": "Sections",
"shortcuts": [
{
"description": "Navigate sections",
"keys": [
{"key": "1"},
{"key": "4"}
],
"keyRange": true
}
]
},
{
"name": "Design",
"shortcuts": [
{
"description": "Add tab",
"keys": [
{"key": "alt"},
{"key": "shift"},
{"key": "t"}
]
}
]
}
];
}
angular.module("umbraco").controller("My.Controller", Controller);
})();
</pre>
<h3>Model description</h3>
<ul>
<li>
<strong>name</strong>
<small>(string)</small> -
Sets the shortcut section name.
</li>
<li>
<strong>shortcuts</strong>
<small>(array)</small> -
Array of available shortcuts in the section.
</li>
<ul>
<li>
<strong>description</strong>
<small>(string)</small> -
Short description of the shortcut.
</li>
<li>
<strong>keys</strong>
<small>(array)</small> -
Array of keys in the shortcut.
</li>
<ul>
<li>
<strong>key</strong>
<small>(string)</small> -
The invidual key in the shortcut.
</li>
</ul>
<li>
<strong>keyRange</strong>
<small>(boolean)</small> -
Set to <code>true</code> to show a key range. It combines the shortcut keys with "-" instead of "+".
</li>
</ul>
</ul>
@param {object} model keyboard shortcut model. See description and example above.
**/
(function() {
'use strict';
@@ -1,3 +1,50 @@
/**
@ngdoc directive
@name umbraco.directives.directive:umbLoadIndicator
@restrict E
@description
Use this directive to generate a loading indicator.
<h3>Markup example</h3>
<pre>
<div ng-controller="My.Controller as vm">
<umb-load-indicator
ng-if="vm.loading">
</umb-load-indicator>
<div class="content" ng-if="!vm.loading">
<p>{{content}}</p>
</div>
</div>
</pre>
<h3>Controller example</h3>
<pre>
(function () {
"use strict";
function Controller(myService) {
var vm = this;
vm.content = "";
vm.loading = true;
myService.getContent().then(function(content){
vm.content = content;
vm.loading = false;
});
}
½
angular.module("umbraco").controller("My.Controller", Controller);
})();
</pre>
**/
(function() {
'use strict';
@@ -1,11 +1,48 @@
/**
* @ngdoc directive
* @name umbraco.directives.directive:umbContentName
* @restrict E
* @function
* @description
* Used by editors that require naming an entity. Shows a textbox/headline with a required validator within it's own form.
@ngdoc directive
@name umbraco.directives.directive:umbLockedField
@restrict E
@scope
@description
Use this directive to render a value with a lock next to it. When the lock is clicked the value gets unlocked and can be edited.
<h3>Markup example</h3>
<pre>
<div ng-controller="My.Controller as vm">
<umb-locked-field
ng-model="vm.value"
placeholder-text="'Click to unlock...'">
</umb-locked-field>
</div>
</pre>
<h3>Controller example</h3>
<pre>
(function () {
"use strict";
function Controller() {
var vm = this;
vm.value = "My locked text";
}
angular.module("umbraco").controller("My.Controller", Controller);
})();
</pre>
@param {string} ngModel (<code>binding</code>): The locked text.
@param {boolean=} locked (<code>binding</code>): <Code>true</code> by default. Set to <code>false</code> to unlock the text.
@param {string=} placeholderText (<code>binding</code>): If ngModel is empty this text will be shown.
@param {string=} regexValidation (<code>binding</code>): Set a regex expression for validation of the field.
@param {string=} serverValidationField (<code>attribute</code>): Set a server validation field.
**/
(function() {
'use strict';
@@ -1,3 +1,87 @@
/**
@ngdoc directive
@name umbraco.directives.directive:umbMediaGrid
@restrict E
@scope
@description
Use this directive to generate a thumbnail grid of media items.
<h3>Markup example</h3>
<pre>
<div ng-controller="My.Controller as vm">
<umb-media-grid
items="vm.mediaItems"
on-click="vm.clickItem"
on-click-name="vm.clickItemName">
</umb-media-grid>
</div>
</pre>
<h3>Controller example</h3>
<pre>
(function () {
"use strict";
function Controller() {
var vm = this;
vm.mediaItems = [];
vm.clickItem = clickItem;
vm.clickItemName = clickItemName;
myService.getMediaItems().then(function (mediaItems) {
vm.mediaItems = mediaItems;
});
function clickItem(item, $event, $index){
// do magic here
}
function clickItemName(item, $event, $index) {
// set item.selected = true; to select the item
// do magic here
}
}
angular.module("umbraco").controller("My.Controller", Controller);
})();
</pre>
@param {array} items (<code>binding</code>): Array of media items.
@param {callback=} onDetailsHover (<code>binding</code>): Callback method when the details icon is hovered.
<h3>The callback returns:</h3>
<ul>
<li><code>item</code>: The hovered item</li>
<li><code>$event</code>: The hover event</li>
<li><code>hover</code>: Boolean to tell if the item is hovered or not</li>
</ul>
@param {callback=} onClick (<code>binding</code>): Callback method to handle click events on the media item.
<h3>The callback returns:</h3>
<ul>
<li><code>item</code>: The clicked item</li>
<li><code>$event</code>: The click event</li>
<li><code>$index</code>: The item index</li>
</ul>
@param {callback=} onClickName (<code>binding</code>): Callback method to handle click events on the media item name.
<h3>The callback returns:</h3>
<ul>
<li><code>item</code>: The clicked item</li>
<li><code>$event</code>: The click event</li>
<li><code>$index</code>: The item index</li>
</ul>
@param {string=} filterBy (<code>binding</code>): String to filter media items by
@param {string=} itemMaxWidth (<code>attribute</code>): Sets a max width on the media item thumbnails.
@param {string=} itemMaxHeight (<code>attribute</code>): Sets a max height on the media item thumbnails.
@param {string=} itemMinWidth (<code>attribute</code>): Sets a min width on the media item thumbnails.
@param {string=} itemMinHeight (<code>attribute</code>): Sets a min height on the media item thumbnails.
**/
(function() {
'use strict';
@@ -34,6 +118,13 @@
var item = scope.items[i];
setItemData(item);
setOriginalSize(item, itemMaxHeight);
// remove non images when onlyImages is set to true
if(scope.onlyImages === "true" && !item.isFolder && !item.thumbnail){
scope.items.splice(i, 1);
i--;
}
}
if (scope.items.length > 0) {
@@ -181,7 +272,8 @@
itemMaxWidth: "@",
itemMaxHeight: "@",
itemMinWidth: "@",
itemMinHeight: "@"
itemMinHeight: "@",
onlyImages: "@"
},
link: link
};
@@ -1,3 +1,88 @@
/**
@ngdoc directive
@name umbraco.directives.directive:umbPagination
@restrict E
@scope
@description
Use this directive to generate a pagination.
<h3>Markup example</h3>
<pre>
<div ng-controller="My.Controller as vm">
<umb-pagination
page-number="vm.pagination.pageNumber"
total-pages="vm.pagination.totalPages"
on-next="vm.nextPage"
on-prev="vm.prevPage"
on-go-to-page="vm.goToPage">
</umb-pagination>
</div>
</pre>
<h3>Controller example</h3>
<pre>
(function () {
"use strict";
function Controller() {
var vm = this;
vm.pagination = {
pageNumber: 1,
totalPages: 10
}
vm.nextPage = nextPage;
vm.prevPage = prevPage;
vm.goToPage = goToPage;
function nextPage(pageNumber) {
// do magic here
console.log(pageNumber);
alert("nextpage");
}
function prevPage(pageNumber) {
// do magic here
console.log(pageNumber);
alert("prevpage");
}
function goToPage(pageNumber) {
// do magic here
console.log(pageNumber);
alert("go to");
}
}
angular.module("umbraco").controller("My.Controller", Controller);
})();
</pre>
@param {number} pageNumber (<code>binding</code>): Current page number.
@param {number} totalPages (<code>binding</code>): The total number of pages.
@param {callback} onNext (<code>binding</code>): Callback method to go to the next page.
<h3>The callback returns:</h3>
<ul>
<li><code>pageNumber</code>: The page number</li>
</ul>
@param {callback=} onPrev (<code>binding</code>): Callback method to go to the previous page.
<h3>The callback returns:</h3>
<ul>
<li><code>pageNumber</code>: The page number</li>
</ul>
@param {callback=} onGoToPage (<code>binding</code>): Callback method to go to a specific page.
<h3>The callback returns:</h3>
<ul>
<li><code>pageNumber</code>: The page number</li>
</ul>
**/
(function() {
'use strict';
@@ -1,3 +1,41 @@
/**
@ngdoc directive
@name umbraco.directives.directive:umbStickyBar
@restrict A
@description
Use this directive make an element sticky and follow the page when scrolling.
<h3>Markup example</h3>
<pre>
<div ng-controller="My.Controller as vm">
<div
class="my-sticky-bar"
umb-sticky-bar
scrollable-container=".container">
</div>
</div>
</pre>
<h3>CSS example</h3>
<pre>
.my-sticky-bar {
padding: 15px 0;
background: #000000;
position: relative;
top: 0;
}
.my-sticky-bar.-umb-sticky-bar {
top: 100px;
}
</pre>
@param {string} scrollableContainer Set the class (".element") or the id ("#element") of the scrollable container element.
**/
(function() {
'use strict';
@@ -1,3 +1,71 @@
/**
@ngdoc directive
@name umbraco.directives.directive:umbTooltip
@restrict E
@scope
@description
Use this directive to render a tooltip.
<h3>Markup example</h3>
<pre>
<div ng-controller="My.Controller as vm">
<div
ng-mouseover="vm.mouseOver($event)"
ng-mouseleave="vm.mouseLeave()">
Hover me
</div>
<umb-tooltip
ng-if="vm.tooltip.show"
event="vm.tooltip.event">
// tooltip content here
</umb-tooltip>
</div>
</pre>
<h3>Controller example</h3>
<pre>
(function () {
"use strict";
function Controller() {
var vm = this;
vm.tooltip = {
show: false,
event: null
};
vm.mouseOver = mouseOver;
vm.mouseLeave = mouseLeave;
function mouseOver($event) {
vm.tooltip = {
show: true,
event: $event
};
}
function mouseLeave() {
vm.tooltip = {
show: false,
event: null
};
}
}
angular.module("umbraco").controller("My.Controller", Controller);
})();
</pre>
@param {string} event Set the $event from the target element to position the tooltip relative to the mouse cursor.
**/
(function() {
'use strict';
@@ -1,6 +1,6 @@
/**
* @ngdoc directive
* @name umbraco.directives.directive:umbContentName
* @name umbraco.directives.directive:umbFileDropzone
* @restrict E
* @function
* @description
@@ -1,6 +1,6 @@
/**
* @ngdoc directive
* @name umbraco.directives.directive:umbFileUpload
* @name umbraco.directives.directive:umbSingleFileUpload
* @function
* @restrict A
* @scope
@@ -509,6 +509,16 @@ function contentResource($q, $http, umbDataFormatter, umbRequestHelper) {
'Failed to check permission for item ' + id);
},
getPermissions: function (nodeIds) {
return umbRequestHelper.resourcePromise(
$http.post(
umbRequestHelper.getApiUrl(
"contentApiBaseUrl",
"GetPermissions"),
nodeIds),
'Failed to get permissions');
},
/**
* @ngdoc method
* @name umbraco.resources.contentResource#save
@@ -29,7 +29,7 @@ function contentTypeResource($q, $http, umbRequestHelper, umbDataFormatter) {
filterContentTypes: filterContentTypes,
filterPropertyTypes: filterPropertyTypes
};
return umbRequestHelper.resourcePromise(
$http.post(
umbRequestHelper.getApiUrl(
@@ -201,9 +201,9 @@ function contentTypeResource($q, $http, umbRequestHelper, umbDataFormatter) {
* .then(function() {
* alert("node was moved");
* }, function(err){
* alert("node didnt move:" + err.data.Message);
* alert("node didnt move:" + err.data.Message);
* });
* </pre>
* </pre>
* @param {Object} args arguments object
* @param {Int} args.idd the ID of the node to move
* @param {Int} args.parentId the ID of the parent node to move to
@@ -230,6 +230,26 @@ function contentTypeResource($q, $http, umbRequestHelper, umbDataFormatter) {
'Failed to move content');
},
copy: function(args) {
if (!args) {
throw "args cannot be null";
}
if (!args.parentId) {
throw "args.parentId cannot be null";
}
if (!args.id) {
throw "args.id cannot be null";
}
return umbRequestHelper.resourcePromise(
$http.post(umbRequestHelper.getApiUrl("contentTypeApiBaseUrl", "PostCopy"),
{
parentId: args.parentId,
id: args.id
}),
'Failed to copy content');
},
createContainer: function(parentId, name) {
return umbRequestHelper.resourcePromise(
@@ -237,7 +257,7 @@ function contentTypeResource($q, $http, umbRequestHelper, umbDataFormatter) {
'Failed to create a folder under parent id ' + parentId);
}
};
}
angular.module('umbraco.resources').factory('contentTypeResource', contentTypeResource);
@@ -53,7 +53,7 @@ function mediaTypeResource($q, $http, umbRequestHelper, umbDataFormatter) {
* .then(function(array) {
* $scope.type = type;
* });
* </pre>
* </pre>
* @param {Int} mediaId id of the media item to retrive allowed child types for
* @returns {Promise} resourcePromise object.
*
@@ -145,9 +145,9 @@ function mediaTypeResource($q, $http, umbRequestHelper, umbDataFormatter) {
* .then(function() {
* alert("node was moved");
* }, function(err){
* alert("node didnt move:" + err.data.Message);
* alert("node didnt move:" + err.data.Message);
* });
* </pre>
* </pre>
* @param {Object} args arguments object
* @param {Int} args.idd the ID of the node to move
* @param {Int} args.parentId the ID of the parent node to move to
@@ -174,6 +174,26 @@ function mediaTypeResource($q, $http, umbRequestHelper, umbDataFormatter) {
'Failed to move content');
},
copy: function (args) {
if (!args) {
throw "args cannot be null";
}
if (!args.parentId) {
throw "args.parentId cannot be null";
}
if (!args.id) {
throw "args.id cannot be null";
}
return umbRequestHelper.resourcePromise(
$http.post(umbRequestHelper.getApiUrl("mediaTypeApiBaseUrl", "PostCopy"),
{
parentId: args.parentId,
id: args.id
}),
'Failed to copy content');
},
createContainer: function(parentId, name) {
return umbRequestHelper.resourcePromise(
@@ -16,7 +16,7 @@ function treeResource($q, $http, umbRequestHelper) {
/** internal method to get the tree menu url */
function getTreeMenuUrl(node) {
if (!node.menuUrl) {
throw "No menuUrl property found on the tree node, cannot load menu";
return null;
}
return node.menuUrl;
}
@@ -26,10 +26,16 @@ function treeResource($q, $http, umbRequestHelper) {
/** Loads in the data to display the nodes menu */
loadMenu: function (node) {
return umbRequestHelper.resourcePromise(
$http.get(getTreeMenuUrl(node)),
"Failed to retrieve data for a node's menu " + node.id);
var treeMenuUrl = getTreeMenuUrl(node);
if (treeMenuUrl !== undefined && treeMenuUrl !== null && treeMenuUrl.length > 0) {
return umbRequestHelper.resourcePromise(
$http.get(getTreeMenuUrl(node)),
"Failed to retrieve data for a node's menu " + node.id);
} else {
return $q.reject({
errorMsg: "No tree menu url defined for node " + node.id
});
}
},
/** Loads in the data to display the nodes for an application */
@@ -1,270 +1,323 @@
// This service was based on OpenJS library available in BSD License
// http://www.openjs.com/scripts/events/keyboard_shortcuts/index.php
angular.module('umbraco.services')
.factory('keyboardService', ['$window', '$timeout', function ($window, $timeout) {
var keyboardManagerService = {};
var defaultOpt = {
'type': 'keydown',
'propagate': false,
'inputDisabled': false,
'target': $window.document,
'keyCode': false
};
var isMac = navigator.platform.toUpperCase().indexOf('MAC')>=0;
function keyboardService($window, $timeout) {
var keyboardManagerService = {};
var defaultOpt = {
'type': 'keydown',
'propagate': false,
'inputDisabled': false,
'target': $window.document,
'keyCode': false
};
// Store all keyboard combination shortcuts
keyboardManagerService.keyboardEvent = {};
// Work around for stupid Shift key bug created by using lowercase - as a result the shift+num combination was broken
var shift_nums = {
"`": "~",
"1": "!",
"2": "@",
"3": "#",
"4": "$",
"5": "%",
"6": "^",
"7": "&",
"8": "*",
"9": "(",
"0": ")",
"-": "_",
"=": "+",
";": ":",
"'": "\"",
",": "<",
".": ">",
"/": "?",
"\\": "|"
};
// Special Keys - and their codes
var special_keys = {
'esc': 27,
'escape': 27,
'tab': 9,
'space': 32,
'return': 13,
'enter': 13,
'backspace': 8,
// Add a new keyboard combination shortcut
keyboardManagerService.bind = function (label, callback, opt) {
'scrolllock': 145,
'scroll_lock': 145,
'scroll': 145,
'capslock': 20,
'caps_lock': 20,
'caps': 20,
'numlock': 144,
'num_lock': 144,
'num': 144,
//replace ctrl key with meta key
if(isMac && label !== "ctrl+space"){
label = label.replace("ctrl","meta");
}
'pause': 19,
'break': 19,
var fct, elt, code, k;
// Initialize opt object
opt = angular.extend({}, defaultOpt, opt);
label = label.toLowerCase();
elt = opt.target;
if(typeof opt.target === 'string'){
elt = document.getElementById(opt.target);
}
'insert': 45,
'home': 36,
'delete': 46,
'end': 35,
'pageup': 33,
'page_up': 33,
'pu': 33,
fct = function (e) {
e = e || $window.event;
'pagedown': 34,
'page_down': 34,
'pd': 34,
// Disable event handler when focus input and textarea
if (opt['inputDisabled']) {
var elt;
if (e.target){
elt = e.target;
}else if (e.srcElement){
elt = e.srcElement;
}
'left': 37,
'up': 38,
'right': 39,
'down': 40,
if (elt.nodeType === 3){elt = elt.parentNode;}
if (elt.tagName === 'INPUT' || elt.tagName === 'TEXTAREA'){return;}
}
'f1': 112,
'f2': 113,
'f3': 114,
'f4': 115,
'f5': 116,
'f6': 117,
'f7': 118,
'f8': 119,
'f9': 120,
'f10': 121,
'f11': 122,
'f12': 123
};
// Find out which key is pressed
if (e.keyCode){
code = e.keyCode;
}else if (e.which){
code = e.which;
}
var isMac = navigator.platform.toUpperCase().indexOf('MAC')>=0;
var character = String.fromCharCode(code).toLowerCase();
// The event handler for bound element events
function eventHandler(e) {
e = e || $window.event;
if (code === 188){character = ",";} // If the user presses , when the type is onkeydown
if (code === 190){character = ".";} // If the user presses , when the type is onkeydown
var code, k;
var keys = label.split("+");
// Key Pressed - counts the number of valid keypresses - if it is same as the number of keys, the shortcut function is invoked
var kp = 0;
// Work around for stupid Shift key bug created by using lowercase - as a result the shift+num combination was broken
var shift_nums = {
"`":"~",
"1":"!",
"2":"@",
"3":"#",
"4":"$",
"5":"%",
"6":"^",
"7":"&",
"8":"*",
"9":"(",
"0":")",
"-":"_",
"=":"+",
";":":",
"'":"\"",
",":"<",
".":">",
"/":"?",
"\\":"|"
};
// Special Keys - and their codes
var special_keys = {
'esc':27,
'escape':27,
'tab':9,
'space':32,
'return':13,
'enter':13,
'backspace':8,
// Find out which key is pressed
if (e.keyCode)
{
code = e.keyCode;
}
else if (e.which) {
code = e.which;
}
'scrolllock':145,
'scroll_lock':145,
'scroll':145,
'capslock':20,
'caps_lock':20,
'caps':20,
'numlock':144,
'num_lock':144,
'num':144,
var character = String.fromCharCode(code).toLowerCase();
'pause':19,
'break':19,
if (code === 188){character = ",";} // If the user presses , when the type is onkeydown
if (code === 190){character = ".";} // If the user presses , when the type is onkeydown
'insert':45,
'home':36,
'delete':46,
'end':35,
var propagate = true;
'pageup':33,
'page_up':33,
'pu':33,
//Now we need to determine which shortcut this event is for, we'll do this by iterating over each
//registered shortcut to find the match. We use Find here so that the loop exits as soon
//as we've found the one we're looking for
_.find(_.keys(keyboardManagerService.keyboardEvent), function(key) {
'pagedown':34,
'page_down':34,
'pd':34,
var shortcutLabel = key;
var shortcutVal = keyboardManagerService.keyboardEvent[key];
'left':37,
'up':38,
'right':39,
'down':40,
// Key Pressed - counts the number of valid keypresses - if it is same as the number of keys, the shortcut function is invoked
var kp = 0;
'f1':112,
'f2':113,
'f3':114,
'f4':115,
'f5':116,
'f6':117,
'f7':118,
'f8':119,
'f9':120,
'f10':121,
'f11':122,
'f12':123
};
// Some modifiers key
var modifiers = {
shift: {
wanted: false,
pressed: e.shiftKey ? true : false
},
ctrl : {
wanted: false,
pressed: e.ctrlKey ? true : false
},
alt : {
wanted: false,
pressed: e.altKey ? true : false
},
meta : { //Meta is Mac specific
wanted: false,
pressed: e.metaKey ? true : false
}
};
// Foreach keys in label (split on +)
var l = keys.length;
for (var i = 0; i < l; i++) {
// Some modifiers key
var modifiers = {
shift: {
wanted: false,
pressed: e.shiftKey ? true : false
},
ctrl: {
wanted: false,
pressed: e.ctrlKey ? true : false
},
alt: {
wanted: false,
pressed: e.altKey ? true : false
},
meta: { //Meta is Mac specific
wanted: false,
pressed: e.metaKey ? true : false
}
};
var k=keys[i];
switch (k) {
case 'ctrl':
case 'control':
kp++;
modifiers.ctrl.wanted = true;
break;
case 'shift':
case 'alt':
case 'meta':
kp++;
modifiers[k].wanted = true;
break;
}
var keys = shortcutLabel.split("+");
var opt = shortcutVal.opt;
var callback = shortcutVal.callback;
if (k.length > 1) { // If it is a special key
if(special_keys[k] === code){
kp++;
}
// Foreach keys in label (split on +)
var l = keys.length;
for (var i = 0; i < l; i++) {
} else if (opt['keyCode']) { // If a specific key is set into the config
if (opt['keyCode'] === code) {
kp++;
}
var k = keys[i];
switch (k) {
case 'ctrl':
case 'control':
kp++;
modifiers.ctrl.wanted = true;
break;
case 'shift':
case 'alt':
case 'meta':
kp++;
modifiers[k].wanted = true;
break;
}
} else { // The special keys did not match
if(character === k) {
kp++;
}else {
if(shift_nums[character] && e.shiftKey) { // Stupid Shift key bug created by using lowercase
character = shift_nums[character];
if(character === k){
kp++;
}
}
}
}
if (k.length > 1) { // If it is a special key
if (special_keys[k] === code) {
kp++;
}
}
else if (opt['keyCode']) { // If a specific key is set into the config
if (opt['keyCode'] === code) {
kp++;
}
}
else { // The special keys did not match
if (character === k) {
kp++;
}
else {
if (shift_nums[character] && e.shiftKey) { // Stupid Shift key bug created by using lowercase
character = shift_nums[character];
if (character === k) {
kp++;
}
}
}
}
} //for end
} //for end
if(kp === keys.length &&
modifiers.ctrl.pressed === modifiers.ctrl.wanted &&
modifiers.shift.pressed === modifiers.shift.wanted &&
modifiers.alt.pressed === modifiers.alt.wanted &&
modifiers.meta.pressed === modifiers.meta.wanted) {
$timeout(function() {
callback(e);
}, 1);
if (kp === keys.length &&
modifiers.ctrl.pressed === modifiers.ctrl.wanted &&
modifiers.shift.pressed === modifiers.shift.wanted &&
modifiers.alt.pressed === modifiers.alt.wanted &&
modifiers.meta.pressed === modifiers.meta.wanted) {
if(!opt['propagate']) { // Stop the event
// e.cancelBubble is supported by IE - this will kill the bubbling process.
e.cancelBubble = true;
e.returnValue = false;
//found the right callback!
// e.stopPropagation works in Firefox.
if (e.stopPropagation) {
e.stopPropagation();
e.preventDefault();
}
return false;
}
}
};
// Store shortcut
keyboardManagerService.keyboardEvent[label] = {
'callback': fct,
'target': elt,
'event': opt['type']
};
// Disable event handler when focus input and textarea
if (opt['inputDisabled']) {
var elt;
if (e.target) {
elt = e.target;
} else if (e.srcElement) {
elt = e.srcElement;
}
//Attach the function with the event
if(elt.addEventListener){
elt.addEventListener(opt['type'], fct, false);
}else if(elt.attachEvent){
elt.attachEvent('on' + opt['type'], fct);
}else{
elt['on' + opt['type']] = fct;
}
};
// Remove the shortcut - just specify the shortcut and I will remove the binding
keyboardManagerService.unbind = function (label) {
label = label.toLowerCase();
var binding = keyboardManagerService.keyboardEvent[label];
delete(keyboardManagerService.keyboardEvent[label]);
if (elt.nodeType === 3) { elt = elt.parentNode; }
if (elt.tagName === 'INPUT' || elt.tagName === 'TEXTAREA') {
//This exits the Find loop
return true;
}
}
if(!binding){return;}
$timeout(function () {
callback(e);
}, 1);
var type = binding['event'],
if (!opt['propagate']) { // Stop the event
propagate = false;
}
//This exits the Find loop
return true;
}
//we haven't found one so continue looking
return false;
});
// Stop the event if required
if (!propagate) {
// e.cancelBubble is supported by IE - this will kill the bubbling process.
e.cancelBubble = true;
e.returnValue = false;
// e.stopPropagation works in Firefox.
if (e.stopPropagation) {
e.stopPropagation();
e.preventDefault();
}
return false;
}
}
// Store all keyboard combination shortcuts
keyboardManagerService.keyboardEvent = {};
// Add a new keyboard combination shortcut
keyboardManagerService.bind = function (label, callback, opt) {
//replace ctrl key with meta key
if(isMac && label !== "ctrl+space"){
label = label.replace("ctrl","meta");
}
var elt;
// Initialize opt object
opt = angular.extend({}, defaultOpt, opt);
label = label.toLowerCase();
elt = opt.target;
if(typeof opt.target === 'string'){
elt = document.getElementById(opt.target);
}
//Ensure we aren't double binding to the same element + type otherwise we'll end up multi-binding
// and raising events for now reason. So here we'll check if the event is already registered for the element
var boundValues = _.values(keyboardManagerService.keyboardEvent);
var found = _.find(boundValues, function (i) {
return i.target === elt && i.event === opt['type'];
});
// Store shortcut
keyboardManagerService.keyboardEvent[label] = {
'callback': callback,
'target': elt,
'opt': opt
};
if (!found) {
//Attach the function with the event
if (elt.addEventListener) {
elt.addEventListener(opt['type'], eventHandler, false);
} else if (elt.attachEvent) {
elt.attachEvent('on' + opt['type'], eventHandler);
} else {
elt['on' + opt['type']] = eventHandler;
}
}
};
// Remove the shortcut - just specify the shortcut and I will remove the binding
keyboardManagerService.unbind = function (label) {
label = label.toLowerCase();
var binding = keyboardManagerService.keyboardEvent[label];
delete(keyboardManagerService.keyboardEvent[label]);
if(!binding){return;}
var type = binding['event'],
elt = binding['target'],
callback = binding['callback'];
if(elt.detachEvent){
elt.detachEvent('on' + type, callback);
}else if(elt.removeEventListener){
elt.removeEventListener(type, callback, false);
}else{
elt['on'+type] = false;
}
};
//
if(elt.detachEvent){
elt.detachEvent('on' + type, callback);
}else if(elt.removeEventListener){
elt.removeEventListener(type, callback, false);
}else{
elt['on'+type] = false;
}
};
//
return keyboardManagerService;
}]);
return keyboardManagerService;
}

Some files were not shown because too many files have changed in this diff Show More