Compare commits

...

177 Commits

Author SHA1 Message Date
Mads Rasmussen 1dacbbdbf6 added dots to website/language selector 2016-03-16 11:09:06 +01:00
Mads Rasmussen f0b374c30b filter out selected item 2016-03-16 10:43:09 +01:00
Mads Rasmussen ec5feee1f3 WIP prototyping website/language selector 2016-03-16 09:26:34 +01:00
Simon Busborg 1d1d99ddad added variationsHelper service and toggler for content 2016-03-15 14:47:03 +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
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
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
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
Stephan 1b37475144 U4-6438 - fix dynamic extension methods when type loading goes bad 2016-03-09 15:55:41 +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
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
Sebastiaan Janssen 05c35b22bd Merge pull request #1148 from umbraco/temp-U4-7040
U4-7040 - Fix bug with permissions cache refresh
2016-03-02 15:03:47 +01: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
Mads Rasmussen f6318fb6f3 Merge pull request #1147 from lars-erik/fix-u4-8082-nested-forms-and-submit-bug
Fixes: U4-8082 New overlays post forms in IE / Edge
2016-02-26 10:08:51 +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 17b29357d4 U4-7040 - Fix bug with permissions cache refresh 2016-02-25 17:43:38 +01: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
Lars-Erik Aabech 57a766098d Removed nested form and changed buttons to type="button" + action instead of ng-submit on form. 2016-02-25 16:04:37 +01: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
Simon Busborg f78cb8a970 Merge pull request #1119 from jchurchley/dev-v7
Fixes U4-7963 Listview columns not evenly spaced in Chrome
2016-02-25 14:52:17 +01:00
Sebastiaan Janssen def276de01 Merge pull request #1143 from umbraco/temp-U4-8027
U4-8027 - fix ApplicationContext request cache (was null cache)
2016-02-25 10:46:31 +01:00
Stephan 293b170a56 U4-8027 - fix ApplicationContext request cache (was null cache) 2016-02-24 14:16:48 +01:00
Stephan 9f7b82e20f U4-8077 - ensure product name in migration event handlers 2016-02-24 13:59:15 +01:00
Warren Buckley 6ba4efc416 Merge pull request #1142 from umbraco/temp-U4-7570
Temp u4 7570
2016-02-24 11:12:59 +00:00
Simon Busborg 981fb39af6 Fixed crop slider 2016-02-24 09:14:13 +01:00
Sebastiaan Janssen c64f6f894e U4-8024 Unable to use MvcBuildViews since 7.4.0 upgrade because 'umbraco.cms.presentation.create.controls.content' has been removed
Removes files for which the codebehind no longer exists
2016-02-23 17:23:55 +01:00
Simon Busborg 3e73c2da43 Fixed width of cropper 2016-02-23 16:31:10 +01:00
Mads Rasmussen 26a8d23039 Fixes: U4-8063 Content type editor: Keyboard shortcut overview should close on escape 2016-02-23 15:09:27 +01:00
Mads Rasmussen 2632ef740c Fixes: U4-7570 Hide image, focal point and remove link until image has loaded 2016-02-23 13:55:05 +01:00
Sebastiaan Janssen f024dba864 Merge pull request #1139 from umbraco/temp-U4-8017
U4-8017 - fix issues with MySql InitColumnTypeMap
2016-02-22 19:05:41 +01:00
Stephan 9758851a4b Fix SqlCeSyntaxProviderTests 2016-02-22 18:55:49 +01:00
Stephan 04b3532e9d U4-8030 - Fix RenderModelBinder issue with surface 2016-02-22 18:38:06 +01:00
Sebastiaan Janssen 38e56f0fea Might make the build server happy? 2016-02-22 17:57:44 +01:00
Sebastiaan Janssen 462baf91e4 Merge pull request #1137 from umbraco/temp-U4-7914
U4-7914 - add PublishedContentRequest.Preparing event
2016-02-22 17:45:50 +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
Stephan f1366c7d29 U4-8017 - fix issues with MySql InitColumnTypeMap 2016-02-19 13:33:11 +01:00
Warren Buckley baaa9340e4 Merge pull request #1131 from umbraco/temp-U4-7918
Fixes U4-7918 Make icon picker for document type and list views consistent
2016-02-19 12:03:27 +00:00
Mads Rasmussen 183a5b5c43 U4-7472: fix macro parameter column width 2016-02-19 09:52:29 +01:00
Mads Rasmussen 1a0c095f40 Merge pull request #932 from engern/MacroParamSortOrder
Fixes U4-7472 - Should be possible to sort macro parameters
2016-02-19 09:27:27 +01:00
Stephan ffada74aa4 Improve RenderModelBinder error msg when same type, different assemblies 2016-02-18 16:04:45 +01:00
Mads Rasmussen f2fc70f731 Merge pull request #982 from abryukhov/patch-4
U4-7616 - Nodes sort dialog - additional date formats
2016-02-18 14:19:06 +01:00
Simon Busborg 866b0113e7 Fixes grunt break 2016-02-18 12:43:09 +01:00
Simon Busborg 06c49daca7 Merge branch 'dev-v7-login-retina-umbraco-logo' of git://github.com/bjarnef/Umbraco-CMS into bjarnef-dev-v7-login-retina-umbraco-logo
# Conflicts:
#	src/Umbraco.Web.UI.Client/src/less/pages/login.less
2016-02-18 12:42:17 +01:00
Stephan 9293008b94 U4-7914 - add PublishedContentRequest.Preparing event 2016-02-18 11:36:48 +01:00
Mads Rasmussen dbb9386d22 Fixes: U4-7660 [7.4 Fix] Added a default value to the Umbaco.TrueFalse datatype. Thanks Jeremy Pyne 2016-02-18 11:20:04 +01:00
Mads Rasmussen 51ed441b85 Merge branch 'u4-5123' of https://github.com/AndyButland/Umbraco-CMS into AndyButland-u4-5123
# Conflicts:
#	src/Umbraco.Web/PropertyEditors/ListViewPropertyEditor.cs
2016-02-18 10:00:22 +01:00
Simon Busborg f566fec665 Merge branch 'Acentrage-U4-6700' into dev-v7 2016-02-17 15:26:51 +01:00
Mads Rasmussen 9d92781a97 Merge pull request #949 from kgiszewski/dev-v7
Fix u4-7534
2016-02-17 15:04:14 +01:00
Simon Busborg 123bfe5afe Fixed merge conflict 2016-02-17 14:31:30 +01:00
Shannon Deminick 3383d2a2ac Merge pull request #1135 from umbraco/temp-U4-7601
U4-7601 - filter published content by composition
2016-02-17 13:31:07 +01:00
Sebastiaan Janssen d9f38a20af Merge remote-tracking branch 'origin/7.3.8' into dev-v7 2016-02-17 13:28:52 +01:00
Sebastiaan Janssen a91669abc0 Fixes unit tests 2016-02-17 13:28:11 +01:00
Stephan cc6dfd0c55 U4-7601 - refactor PR, case insensitive 2016-02-17 12:55:40 +01:00
Stephan d4802fcef6 Merge branch 'feature/is-composed-of' of https://github.com/AndyButland/Umbraco-CMS into temp-U4-7601 2016-02-17 12:44:18 +01:00
Sebastiaan Janssen 35c3208b77 Fixes merge error 2016-02-17 12:30:42 +01:00
Shannon 3b9db8a92f tries fixing test for appveyor 2016-02-17 12:25:40 +01:00
Sebastiaan Janssen 7debe17c58 Merge remote-tracking branch 'origin/7.3.8' into dev-v7
Conflicts:
	src/Umbraco.Web.UI/packages.config
2016-02-17 11:56:24 +01:00
Sebastiaan Janssen 1bfc1229bd Merge pull request #1134 from umbraco/temp-738-U4-7996
Upgrade SQL CE to hopefully fix SQL CE data loss bug
2016-02-17 11:54:25 +01:00
Shannon f941456af6 fixes namespace 2016-02-17 11:48:32 +01:00
Shannon 828e88e6f2 Merge remote-tracking branch 'origin/7.3.8' into dev-v7
Conflicts:
	src/Umbraco.Tests/Web/Mvc/UmbracoViewPageTests.cs
	src/Umbraco.Web/Mvc/UmbracoViewPageOfTModel.cs
2016-02-17 11:46:33 +01:00
Sebastiaan Janssen 3d6fd2d785 Updates to SQL CE 4.0.0.1 2016-02-17 11:44:33 +01:00
Shannon e56881abc6 adds unit tests for new ext methods 2016-02-17 11:21:15 +01:00
Shannon d32991c30a re-organizing some namespaces for tests 2016-02-17 10:59:48 +01:00
Shannon 8758f9649b checks for null before assigning culture 2016-02-17 10:57:20 +01:00
Sebastiaan Janssen 07902e840f Merge pull request #1133 from rodyvansambeek/patch-2
Changed allow upload whitelist to disallow extensions
2016-02-17 10:53:05 +01:00
rodyvansambeek e807ee7d64 Changed allow upload whitelist to disallow extensions
It is not possible to upload files in 7.4.0 with an extension different then the imageTypes in the Umbraco.Sys.ServerVariables.umbracoSettings.imageFileTypes, in the single upload this was changed after beta 7.4.0-beta1 to Umbraco.Sys.ServerVariables.umbracoSettings.disallowedUploadFiles. However the change was not added to the drag-drop-uploader. This fixes that.
2016-02-17 10:30:57 +01:00
Shannon 6f0f1ab2c3 fixes wrong constant used 2016-02-17 10:22:37 +01:00
Shannon cd28240172 Moves strings to constants, adds ControllerContextExtensions to get the UmbracoContext from the hierarchy of ControllerContext's, changes RenderModelBinder to use this method to get the UmbracoContext, changes UmbracoViewPageOfTModel to use this method to get the UmbracoContext, adds RouteDataExtensions to get the UmbracoContext from routedata, adds extension methods on the HttpContext to get the UmbracoContext from it.
Conflicts:
	src/Umbraco.Web/Mvc/RenderModelBinder.cs
2016-02-17 10:22:22 +01:00
Sebastiaan Janssen 85ca85fd42 Merge pull request #1129 from umbraco/temp-U4-7577
U4-7577 Remove dependency on UmbracoContext in CreateServiceContext /…
2016-02-16 17:32:38 +01:00
Sebastiaan Janssen 4a10178697 Merge pull request #1123 from umbraco/temp-U4-8000
U4-8000 NullReferenceException in RenderModelBinder when performing an async controller action
2016-02-16 17:28:49 +01:00
Shannon ccba7f14a0 tries fixing test for appveyor 2016-02-16 16:26:21 +01:00
Sebastiaan Janssen b797e0d0c5 Merge pull request #1127 from umbraco/temp-U4-7953
U4-7953 Creating Templates via new DocType have camelCased aliases, b…
2016-02-16 15:39:35 +01:00
Sebastiaan Janssen 8220b033f3 Merge pull request #1125 from umbraco/temp-U4-7954
U4-7954 Error upgrading database to 7.4.0 - [ FK_cmsPropertyTypeGroup…
2016-02-16 15:20:53 +01:00
Shannon 6fffc8b45e U4-7577 Remove dependency on UmbracoContext in CreateServiceContext / RequestLifespanMessagesFactory 2016-02-16 15:07:42 +01:00
Shannon b550b3dde3 Merge remote-tracking branch 'origin/7.3.8' into dev-v7 2016-02-16 14:52:14 +01:00
Shannon 7002291c41 adds tests for ShouldAuthenticateRequest for app configurations 2016-02-16 14:51:15 +01:00
Shannon 51bbf7ceb5 U4-7494 Installation Fails for 7.3.3 - Intermittent - Value cannot be null. Parameter name: sqlSyntax 2016-02-16 14:22:59 +01:00
Shannon 93d9f09fcc U4-7953 Creating Templates via new DocType have camelCased aliases, but from the Template section have PascalCase aliases 2016-02-16 14:20:29 +01:00
Sebastiaan Janssen 42a68cb770 U4-7494 Installation Fails for 7.3.3 - Intermittent - Value cannot be null. Parameter name: sqlSyntax 2016-02-16 14:00:28 +01:00
Shannon 1c2dec00fc bumps version 2016-02-16 13:32:03 +01:00
Shannon fcea4c7fdd Merge branch 'dev-v7' of https://github.com/umbraco/Umbraco-CMS into dev-v7 2016-02-16 13:30:21 +01:00
Shannon b6ef4bf6b5 Merge branch '7.3.8' into dev-v7
Conflicts:
	build/UmbracoVersion.txt
	src/SolutionInfo.cs
	src/Umbraco.Core/Configuration/UmbracoVersion.cs
	src/Umbraco.Core/Umbraco.Core.csproj
	src/Umbraco.Web.UI/Umbraco.Web.UI.csproj
2016-02-16 13:29:59 +01:00
Shannon 82297a6ff1 U4-7929 Label datatype strips leading zeros 2016-02-16 13:23:37 +01:00
Warren Buckley 3bf79f0a23 Merge pull request #1102 from umbraco/temp-U4-7837
Fixes: U4-7837 Changing document type should refresh the current node
2016-02-16 12:22:56 +00:00
Shannon 3f5aa3aa2b U4-7954 Error upgrading database to 7.4.0 - [ FK_cmsPropertyTypeGroup_cmsPropertyTypeGroup_id ] doesn't exist 2016-02-16 12:17:21 +01:00
Shannon cc5ac1a84c bumps version 2016-02-16 11:57:10 +01:00
Shannon 6373add383 U4-7922 Preview is not working 2016-02-16 11:53:54 +01:00
Shannon 180099b718 U4-7890 XSLT Macro's not working - "Cannot use this obsoleted overload when the current provider" 2016-02-16 11:52:16 +01:00
Shannon 65f15125e1 U4-7939 - fix routes cache 2016-02-16 11:48:09 +01:00
Shannon f026201c68 fixes wrong constant used 2016-02-16 11:35:38 +01:00
Shannon 640b2c0ee0 Moves strings to constants, adds ControllerContextExtensions to get the UmbracoContext from the hierarchy of ControllerContext's, changes RenderModelBinder to use this method to get the UmbracoContext, changes UmbracoViewPageOfTModel to use this method to get the UmbracoContext, adds RouteDataExtensions to get the UmbracoContext from routedata, adds extension methods on the HttpContext to get the UmbracoContext from it. 2016-02-16 11:17:47 +01:00
Shannon Deminick bef7ad1196 Merge pull request #1120 from lars-erik/fix-silly-long-grid-translation
Grid translations
2016-02-16 10:12:02 +01:00
Shannon Deminick 33c6c8b473 Merge pull request #1121 from umbraco/temp-U4-7950
Fixes another reported bug for U4-7950
2016-02-16 10:05:09 +01:00
Sebastiaan Janssen 0a26e482aa Fixes another reported bug for U4-7950 2016-02-16 09:01:28 +01:00
Lars-Erik Aabech d0de54e2d3 Grid translations:
Fixed a silly long translation of "Add content".
Added missing keys.
Fixed a few spelling mistakes.
2016-02-16 08:50:07 +01:00
Stephan cbdabaa3b1 Merge pull request #1118 from umbraco/temp-U4-7950
Use CultureInfo.CurrentCulture if UmbracoContext.PublishedContentRequ…
2016-02-15 15:21:00 +01:00
John Churchley 65c97040b3 Fix Chrome issue listview columns not evenly spaced
http://issues.umbraco.org/issue/U4-7963#
2016-02-15 12:17:13 +00:00
Simon Busborg a33d7da211 Fixes: U4-7945 Grid's Reorder bar covers content
http://issues.umbraco.org/issue/U4-7945
2016-02-15 12:55:44 +01:00
Sebastiaan Janssen f31b6d9c2c Use CultureInfo.CurrentCulture if UmbracoContext.PublishedContentRequest is not available 2016-02-15 08:27:07 +01:00
Sebastiaan Janssen 367c945b42 Merge pull request #1117 from s-moon/patch-1
Minor text changes.
2016-02-14 11:08:19 +01:00
Stephen Moon b962fcdbc3 Minor text changes. 2016-02-13 21:31:13 +00:00
Simon Busborg 0f8a13d60a 7 in a row instead of 8, bumped font-size on icons to 30 2016-02-12 10:17:42 +01:00
Simon Busborg 5c1502c806 Removes umb-control-group when no icons displayed 2016-02-12 10:13:30 +01:00
Simon Busborg 3cdebf4427 Fixes U4-7918 Make icon picker for document type and list views consistent 2016-02-12 09:38:37 +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
Claus 44f2a9e96f Fixes: U4-7837 Changing document type should refresh the current node 2016-02-05 14:37:01 +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 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
Alexander Bryukhov ae85b7bf2b Nodes sort dialog - adding date formats
Adding dates processing for 'dd.MM.yyyy' formats
2015-12-28 23:00:08 +06:00
AndyButland b52c480da3 Added IPublishedContent extension method for filtering nodes based on composition alias
Created unit test for IsComposedOf
2015-12-22 16:27:12 +01:00
kgiszewski dada91f006 Fix u4-7534 2015-12-14 13:35:46 -05:00
engern 348694d9d4 Use same color as the rest 2015-11-29 12:22:22 +01:00
engern 855e3b3dcc Add the possibility to sort the macro parameters 2015-11-29 12:06:19 +01:00
engern 5a8ea4aa41 Merge branch 'dev-v7' of https://github.com/engern/Umbraco-CMS into dev-v7 2015-11-29 09:38:36 +01:00
engern 4bd465f666 Merge remote-tracking branch 'refs/remotes/umbraco/dev-v7' into dev-v7 2015-11-29 09:38:20 +01:00
Tommy Enger ad591c07cf Merge pull request #1 from umbraco/dev-v7
Update from original
2015-11-29 09:37:54 +01:00
bjarnef cd3aaa47ca Add retina version of Umbraco logo in login screen 2015-11-19 00:25:05 +01:00
AndyButland a05cc03254 Allows position of the list view child items tab to be positioned within the tab list 2015-11-15 21:18:21 +01:00
207 changed files with 5227 additions and 2706 deletions
+5 -5
View File
@@ -15,11 +15,11 @@ If you're interested in making changes to Belle make sure to read the [Belle Rea
**More than 177,000 sites trust Umbraco**
For the first time on the Microsoft platform 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 developers dream and your users will love it too.
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 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.
To view more examples please visit [http://umbraco.com/why-umbraco/#caseStudies](http://umbraco.com/why-umbraco/#caseStudies)
To view more examples, please visit [http://umbraco.com/why-umbraco/#caseStudies](http://umbraco.com/why-umbraco/#caseStudies)
## Downloading ##
@@ -35,6 +35,6 @@ If you want to contribute back to Umbraco you should check out our [guide to con
## Found a bug? ##
Another way you can contribute to Umbraco is by providing issue reports, for information on how to submit an issue report refer to our [online guide for reporting issues](http://our.umbraco.org/contribute/report-an-issue-or-request-a-feature).
Another way you can contribute to Umbraco is by providing issue reports. For information on how to submit an issue report refer to our [online guide for reporting issues](http://our.umbraco.org/contribute/report-an-issue-or-request-a-feature).
To view existing issues please visit [http://issues.umbraco.org](http://issues.umbraco.org)
To view existing issues, please visit [http://issues.umbraco.org](http://issues.umbraco.org).
+2 -2
View File
@@ -175,8 +175,8 @@
<!-- Copy SQL CE -->
<ItemGroup>
<SQLCE4Files
Include="..\src\packages\SqlServerCE.4.0.0.0\**\*.*"
Exclude="..\src\packages\SqlServerCE.4.0.0.0\lib\**\*;..\src\packages\SqlServerCE.4.0.0.0\**\*.nu*"
Include="..\src\packages\SqlServerCE.4.0.0.1\**\*.*"
Exclude="..\src\packages\SqlServerCE.4.0.0.1\lib\**\*;..\src\packages\SqlServerCE.4.0.0.1\**\*.nu*"
/>
</ItemGroup>
-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
View File
@@ -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.0
7.4.1
+8 -6
View File
@@ -47,13 +47,15 @@
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Data.SqlServerCe, Version=4.0.0.0, Culture=neutral, PublicKeyToken=89845dcd8080cc91, processorArchitecture=MSIL">
<Private>True</Private>
<HintPath>..\packages\SqlServerCE.4.0.0.0\lib\System.Data.SqlServerCe.dll</HintPath>
<Reference Include="System.Data.SqlServerCe, Version=4.0.0.1, Culture=neutral, PublicKeyToken=89845dcd8080cc91, processorArchitecture=MSIL">
<HintPath>..\packages\SqlServerCE.4.0.0.1\lib\System.Data.SqlServerCe.dll</HintPath>
<SpecificVersion>False</SpecificVersion>
<Private>False</Private>
</Reference>
<Reference Include="System.Data.SqlServerCe.Entity, Version=4.0.0.0, Culture=neutral, PublicKeyToken=89845dcd8080cc91, processorArchitecture=MSIL">
<Private>True</Private>
<HintPath>..\packages\SqlServerCE.4.0.0.0\lib\System.Data.SqlServerCe.Entity.dll</HintPath>
<Reference Include="System.Data.SqlServerCe.Entity, Version=4.0.0.1, Culture=neutral, PublicKeyToken=89845dcd8080cc91, processorArchitecture=MSIL">
<HintPath>..\packages\SqlServerCE.4.0.0.1\lib\System.Data.SqlServerCe.Entity.dll</HintPath>
<SpecificVersion>False</SpecificVersion>
<Private>False</Private>
</Reference>
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
+1 -1
View File
@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="SqlServerCE" version="4.0.0.0" targetFramework="net40" />
<package id="SqlServerCE" version="4.0.0.1" targetFramework="net45" />
</packages>
+2 -2
View File
@@ -11,5 +11,5 @@ using System.Resources;
[assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyFileVersion("7.4.0")]
[assembly: AssemblyInformationalVersion("7.4.0")]
[assembly: AssemblyFileVersion("7.4.1")]
[assembly: AssemblyInformationalVersion("7.4.1")]
@@ -6,7 +6,7 @@ namespace Umbraco.Core.Configuration
{
public class UmbracoVersion
{
private static readonly Version Version = new Version("7.4.0");
private static readonly Version Version = new Version("7.4.1");
/// <summary>
/// Gets the current version of Umbraco.
+6
View File
@@ -10,6 +10,12 @@ namespace Umbraco.Core
/// </summary>
public static class Web
{
public const string UmbracoContextDataToken = "umbraco-context";
public const string UmbracoDataToken = "umbraco";
public const string PublishedDocumentRequestDataToken = "umbraco-doc-request";
public const string CustomRouteDataToken = "umbraco-custom-route";
public const string UmbracoRouteDefinitionDataToken = "umbraco-route-def";
/// <summary>
/// The preview cookie name
/// </summary>
@@ -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; }
}
}
+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;
}
}
}
@@ -1,9 +1,6 @@
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Web.Caching;
using System.Web.UI;
using Umbraco.Core.Cache;
namespace Umbraco.Core.Models.PublishedContent
@@ -16,6 +13,7 @@ namespace Umbraco.Core.Models.PublishedContent
public class PublishedContentType
{
private readonly PublishedPropertyType[] _propertyTypes;
private readonly HashSet<string> _compositionAliases;
// fast alias-to-index xref containing both the raw alias and its lowercase version
private readonly Dictionary<string, int> _indexes = new Dictionary<string, int>();
@@ -27,6 +25,7 @@ namespace Umbraco.Core.Models.PublishedContent
{
Id = contentType.Id;
Alias = contentType.Alias;
_compositionAliases = new HashSet<string>(contentType.CompositionAliases(), StringComparer.InvariantCultureIgnoreCase);
_propertyTypes = contentType.CompositionPropertyTypes
.Select(x => new PublishedPropertyType(this, x))
.ToArray();
@@ -34,10 +33,11 @@ namespace Umbraco.Core.Models.PublishedContent
}
// internal so it can be used for unit tests
internal PublishedContentType(int id, string alias, IEnumerable<PublishedPropertyType> propertyTypes)
internal PublishedContentType(int id, string alias, IEnumerable<string> compositionAliases, IEnumerable<PublishedPropertyType> propertyTypes)
{
Id = id;
Alias = alias;
_compositionAliases = new HashSet<string>(compositionAliases, StringComparer.InvariantCultureIgnoreCase);
_propertyTypes = propertyTypes.ToArray();
foreach (var propertyType in _propertyTypes)
propertyType.ContentType = this;
@@ -45,8 +45,8 @@ namespace Umbraco.Core.Models.PublishedContent
}
// create detached content type - ie does not match anything in the DB
internal PublishedContentType(string alias, IEnumerable<PublishedPropertyType> propertyTypes)
: this (0, alias, propertyTypes)
internal PublishedContentType(string alias, IEnumerable<string> compositionAliases, IEnumerable<PublishedPropertyType> propertyTypes)
: this(0, alias, compositionAliases, propertyTypes)
{ }
private void InitializeIndexes()
@@ -63,6 +63,7 @@ namespace Umbraco.Core.Models.PublishedContent
public int Id { get; private set; }
public string Alias { get; private set; }
public HashSet<string> CompositionAliases { get { return _compositionAliases; } }
#endregion
@@ -113,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)
@@ -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;
}
@@ -20,7 +20,17 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenFourZer
if (columns.Any(x => x.TableName.InvariantEquals("cmsPropertyTypeGroup") && x.ColumnName.InvariantEquals("parentGroupId")) == false)
return;
Delete.ForeignKey("FK_cmsPropertyTypeGroup_cmsPropertyTypeGroup_id").OnTable("cmsPropertyTypeGroup");
//This constraing can be based on old aliases, before removing them, check they exist
var constraints = SqlSyntax.GetConstraintsPerColumn(Context.Database).Distinct().ToArray();
if (constraints.Any(x => x.Item1.InvariantEquals("cmsPropertyTypeGroup") && x.Item3.InvariantEquals("FK_cmsPropertyTypeGroup_cmsPropertyTypeGroup_id")))
{
Delete.ForeignKey("FK_cmsPropertyTypeGroup_cmsPropertyTypeGroup_id").OnTable("cmsPropertyTypeGroup");
}
if (constraints.Any(x => x.Item1.InvariantEquals("cmsPropertyTypeGroup") && x.Item3.InvariantEquals("FK_cmsPropertyTypeGroup_cmsPropertyTypeGroup")))
{
Delete.ForeignKey("FK_cmsPropertyTypeGroup_cmsPropertyTypeGroup").OnTable("cmsPropertyTypeGroup");
}
Delete.Column("parentGroupId").FromTable("cmsPropertyTypeGroup");
}
@@ -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);
@@ -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 "NOT (" + o + " = @0)";
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 o + " = @0";
default:
// could be anything else, such as: x => x.Path.StartsWith("-20")
return o;
}
}
protected virtual string VisitNewArray(NewArrayExpression na)
{
@@ -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);
}
}
@@ -28,6 +28,8 @@ namespace Umbraco.Core.Persistence.SqlSyntax
GuidColumnDefinition = "char(36)";
DefaultValueFormat = "DEFAULT {0}";
InitColumnTypeMap();
}
public override IEnumerable<string> GetTablesInSchema(Database db)
@@ -0,0 +1,28 @@
using Umbraco.Core.Models.PublishedContent;
namespace Umbraco.Core.PropertyEditors.ValueConverters
{
/// <summary>
/// We need this property converter so that we always force the value of a label to be a string
/// </summary>
/// <remarks>
/// Without a property converter defined for the label type, the value will be converted with
/// the `ConvertUsingDarkMagic` method which will try to parse the value into it's correct type, but this
/// can cause issues if the string is detected as a number and then strips leading zeros.
/// Example: http://issues.umbraco.org/issue/U4-7929
/// </remarks>
[DefaultPropertyValueConverter]
[PropertyValueType(typeof (string))]
[PropertyValueCache(PropertyCacheValue.All, PropertyCacheLevel.Content)]
public class LabelValueConverter : PropertyValueConverterBase
{
public override bool IsConverter(PublishedPropertyType propertyType)
{
return Constants.PropertyEditors.NoEditAlias.Equals(propertyType.PropertyEditorAlias);
}
public override object ConvertDataToSource(PublishedPropertyType propertyType, object source, bool preview)
{
return source == null ? string.Empty : source.ToString();
}
}
}
@@ -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>
+6 -1
View File
@@ -255,7 +255,12 @@ namespace Umbraco.Core.Services
/// </returns>
public Attempt<OperationStatus<ITemplate, OperationStatusType>> CreateTemplateForContentType(string contentTypeAlias, string contentTypeName, int userId = 0)
{
var template = new Template(contentTypeName, contentTypeAlias);
var template = new Template(contentTypeName,
//NOTE: We are NOT passing in the content type alias here, we want to use it's name since we don't
// want to save template file names as camelCase, the Template ctor will clean the alias as
// `alias.ToCleanString(CleanStringType.UnderscoreAlias)` which has been the default.
// This fixes: http://issues.umbraco.org/issue/U4-7953
contentTypeName);
var evtMsgs = EventMessagesFactory.Get();
@@ -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);
}
}
+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)
{
+5 -4
View File
@@ -102,13 +102,13 @@
<Reference Include="System.ComponentModel.DataAnnotations" />
<Reference Include="System.Configuration" />
<Reference Include="System.Data.Entity" />
<Reference Include="System.Data.SqlServerCe, Version=4.0.0.0, Culture=neutral, PublicKeyToken=89845dcd8080cc91, processorArchitecture=MSIL">
<Reference Include="System.Data.SqlServerCe, Version=4.0.0.1, Culture=neutral, PublicKeyToken=89845dcd8080cc91, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\SqlServerCE.4.0.0.0\lib\System.Data.SqlServerCe.dll</HintPath>
<HintPath>..\packages\SqlServerCE.4.0.0.1\lib\System.Data.SqlServerCe.dll</HintPath>
</Reference>
<Reference Include="System.Data.SqlServerCe.Entity, Version=4.0.0.0, Culture=neutral, PublicKeyToken=89845dcd8080cc91, processorArchitecture=MSIL">
<Reference Include="System.Data.SqlServerCe.Entity, Version=4.0.0.1, Culture=neutral, PublicKeyToken=89845dcd8080cc91, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\SqlServerCE.4.0.0.0\lib\System.Data.SqlServerCe.Entity.dll</HintPath>
<HintPath>..\packages\SqlServerCE.4.0.0.1\lib\System.Data.SqlServerCe.Entity.dll</HintPath>
</Reference>
<Reference Include="System.Drawing" />
<Reference Include="System.Net.Http" />
@@ -478,6 +478,7 @@
<Compile Include="PropertyEditors\DecimalValidator.cs" />
<Compile Include="PropertyEditors\ValueConverters\GridValueConverter.cs" />
<Compile Include="PropertyEditors\ValueConverters\DecimalValueConverter.cs" />
<Compile Include="PropertyEditors\ValueConverters\LabelValueConverter.cs" />
<Compile Include="PropertyEditors\ValueConverters\ImageCropperValueConverter.cs" />
<Compile Include="Publishing\UnPublishedStatusType.cs" />
<Compile Include="Publishing\UnPublishStatus.cs" />
+1 -1
View File
@@ -15,5 +15,5 @@
<package id="Owin" version="1.0" targetFramework="net45" />
<package id="semver" version="1.1.2" targetFramework="net45" />
<package id="SharpZipLib" version="0.86.0" targetFramework="net4" />
<package id="SqlServerCE" version="4.0.0.0" targetFramework="net4" />
<package id="SqlServerCE" version="4.0.0.1" targetFramework="net45" />
</packages>
+1 -1
View File
@@ -72,7 +72,7 @@
<system.data>
<DbProviderFactories>
<remove invariant="System.Data.SqlServerCe.4.0" />
<add name="Microsoft SQL Server Compact Data Provider 4.0" invariant="System.Data.SqlServerCe.4.0" description=".NET Framework Data Provider for Microsoft SQL Server Compact" type="System.Data.SqlServerCe.SqlCeProviderFactory, System.Data.SqlServerCe, Version=4.0.0.0, Culture=neutral, PublicKeyToken=89845dcd8080cc91" />
<add name="Microsoft SQL Server Compact Data Provider 4.0" invariant="System.Data.SqlServerCe.4.0" description=".NET Framework Data Provider for Microsoft SQL Server Compact" type="System.Data.SqlServerCe.SqlCeProviderFactory, System.Data.SqlServerCe, Version=4.0.0.1, Culture=neutral, PublicKeyToken=89845dcd8080cc91" />
<remove invariant="MySql.Data.MySqlClient" />
<add name="MySQL Data Provider" invariant="MySql.Data.MySqlClient" description=".Net Framework Data Provider for MySQL" type="MySql.Data.MySqlClient.MySqlClientFactory, MySql.Data, Version=6.6.4.0, Culture=neutral, PublicKeyToken=c5687fc88969c44d" />
</DbProviderFactories>
@@ -42,7 +42,7 @@ namespace Umbraco.Tests.Cache.DistributedCache
{
for (var i = 1; i < 11; i++)
{
Web.Cache.DistributedCache.Instance.Refresh(Guid.Parse("E0F452CB-DCB2-4E84-B5A5-4F01744C5C73"), i);
global::Umbraco.Web.Cache.DistributedCache.Instance.Refresh(Guid.Parse("E0F452CB-DCB2-4E84-B5A5-4F01744C5C73"), i);
}
Assert.AreEqual(10, ((TestServerMessenger)ServerMessengerResolver.Current.Messenger).IntIdsRefreshed.Count);
}
@@ -52,7 +52,7 @@ namespace Umbraco.Tests.Cache.DistributedCache
{
for (var i = 0; i < 10; i++)
{
Web.Cache.DistributedCache.Instance.Refresh(
global::Umbraco.Web.Cache.DistributedCache.Instance.Refresh(
Guid.Parse("E0F452CB-DCB2-4E84-B5A5-4F01744C5C73"),
x => x.Id,
new TestObjectWithId{Id = i});
@@ -65,7 +65,7 @@ namespace Umbraco.Tests.Cache.DistributedCache
{
for (var i = 0; i < 11; i++)
{
Web.Cache.DistributedCache.Instance.Refresh(Guid.Parse("E0F452CB-DCB2-4E84-B5A5-4F01744C5C73"), Guid.NewGuid());
global::Umbraco.Web.Cache.DistributedCache.Instance.Refresh(Guid.Parse("E0F452CB-DCB2-4E84-B5A5-4F01744C5C73"), Guid.NewGuid());
}
Assert.AreEqual(11, ((TestServerMessenger)ServerMessengerResolver.Current.Messenger).GuidIdsRefreshed.Count);
}
@@ -75,7 +75,7 @@ namespace Umbraco.Tests.Cache.DistributedCache
{
for (var i = 1; i < 13; i++)
{
Web.Cache.DistributedCache.Instance.Remove(Guid.Parse("E0F452CB-DCB2-4E84-B5A5-4F01744C5C73"), i);
global::Umbraco.Web.Cache.DistributedCache.Instance.Remove(Guid.Parse("E0F452CB-DCB2-4E84-B5A5-4F01744C5C73"), i);
}
Assert.AreEqual(12, ((TestServerMessenger)ServerMessengerResolver.Current.Messenger).IntIdsRemoved.Count);
}
@@ -85,7 +85,7 @@ namespace Umbraco.Tests.Cache.DistributedCache
{
for (var i = 0; i < 13; i++)
{
Web.Cache.DistributedCache.Instance.RefreshAll(Guid.Parse("E0F452CB-DCB2-4E84-B5A5-4F01744C5C73"));
global::Umbraco.Web.Cache.DistributedCache.Instance.RefreshAll(Guid.Parse("E0F452CB-DCB2-4E84-B5A5-4F01744C5C73"));
}
Assert.AreEqual(13, ((TestServerMessenger)ServerMessengerResolver.Current.Messenger).CountOfFullRefreshes);
}
@@ -56,19 +56,19 @@ namespace Umbraco.Tests.Integration
ServiceContext.DomainService.Save(new UmbracoDomain("*100112") { DomainName = "*100112", RootContentId = c3.Id, LanguageId = l2.Id });
var content = c2;
var culture = Web.Models.ContentExtensions.GetCulture(null,
var culture = global::Umbraco.Web.Models.ContentExtensions.GetCulture(null,
ServiceContext.DomainService, ServiceContext.LocalizationService, ServiceContext.ContentService,
content.Id, content.Path, new Uri("http://domain1.com/"));
Assert.AreEqual("en-US", culture.Name);
content = c2;
culture = Web.Models.ContentExtensions.GetCulture(null,
culture = global::Umbraco.Web.Models.ContentExtensions.GetCulture(null,
ServiceContext.DomainService, ServiceContext.LocalizationService, ServiceContext.ContentService,
content.Id, content.Path, new Uri("http://domain1.fr/"));
Assert.AreEqual("fr-FR", culture.Name);
content = c4;
culture = Web.Models.ContentExtensions.GetCulture(null,
culture = global::Umbraco.Web.Models.ContentExtensions.GetCulture(null,
ServiceContext.DomainService, ServiceContext.LocalizationService, ServiceContext.ContentService,
content.Id, content.Path, new Uri("http://domain1.fr/"));
Assert.AreEqual("de-DE", culture.Name);
@@ -104,13 +104,13 @@ namespace Umbraco.Tests.Integration
//ServiceContext.DomainService.Save(new UmbracoDomain("*100112") { DomainName = "*100112", RootContentId = c3.Id, LanguageId = l2.Id });
var content = c2;
var culture = Web.Models.ContentExtensions.GetCulture(null,
var culture = Umbraco.Web.Models.ContentExtensions.GetCulture(null,
ServiceContext.DomainService, ServiceContext.LocalizationService, ServiceContext.ContentService,
content.Id, content.Path, new Uri("http://domain1.com/"));
Assert.AreEqual("de-DE", culture.Name);
content = c4;
culture = Web.Models.ContentExtensions.GetCulture(null,
culture = Umbraco.Web.Models.ContentExtensions.GetCulture(null,
ServiceContext.DomainService, ServiceContext.LocalizationService, ServiceContext.ContentService,
content.Id, content.Path, new Uri("http://domain1.fr/"));
Assert.AreEqual("fr-FR", culture.Name);
@@ -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}; }
}
}
}
}
@@ -51,6 +51,18 @@ namespace Umbraco.Tests.Persistence.Querying
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]);
}
[Test]
public void Where_Clause_With_Equals_Clause()
{
@@ -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()
{
@@ -1,17 +1,20 @@
using System;
using System.Linq;
using Moq;
using NUnit.Framework;
using Umbraco.Core.Logging;
using Umbraco.Core.Models.Rdbms;
using Umbraco.Core.Persistence;
using Umbraco.Core.Persistence.DatabaseModelDefinitions;
using Umbraco.Core.Persistence.Migrations;
using Umbraco.Core.Persistence.SqlSyntax;
using Umbraco.Tests.TestHelpers;
namespace Umbraco.Tests.Persistence.SyntaxProvider
{
[NUnit.Framework.Ignore("This doesn't actually test anything")]
//[NUnit.Framework.Ignore("This doesn't actually test anything")]
[TestFixture]
public class MySqlSyntaxProviderTests
public class MySqlSyntaxProviderTests : BaseUsingSqlCeSyntax
{
[SetUp]
public void SetUp()
@@ -20,6 +23,7 @@ namespace Umbraco.Tests.Persistence.SyntaxProvider
}
[Test]
[NUnit.Framework.Ignore]
public void Can_Generate_Create_Table_Statement()
{
var type = typeof(TagRelationshipDto);
@@ -48,5 +52,40 @@ namespace Umbraco.Tests.Persistence.SyntaxProvider
{
SqlSyntaxContext.SqlSyntaxProvider = null;
}
[Test]
public void U4_8017()
{
var logger = Mock.Of<ILogger>();
var migration = new TestMigration(SqlSyntaxContext.SqlSyntaxProvider, logger);
var context = new MigrationContext(DatabaseProviders.MySql, null, logger);
migration.Context = context;
migration.Up();
var x = context.Expressions;
Assert.AreEqual(1, x.Count);
var e = x.First().ToString();
// SQLCE provider *does* use UniqueIdentifier
// MySql using GUID...? because InitColumnTypeMap() missing in provider, fixed
Assert.AreEqual("ALTER TABLE `cmsPropertyTypeGroup` ADD COLUMN `uniqueID` char(36) NOT NULL", e);
}
[Migration("1.0.0", 0, "Test")]
private class TestMigration : MigrationBase
{
public TestMigration(ISqlSyntaxProvider sqlSyntax, ILogger logger) : base(sqlSyntax, logger)
{}
public override void Up()
{
Create.Column("uniqueID").OnTable("cmsPropertyTypeGroup").AsGuid().NotNullable().WithDefault(SystemMethods.NewGuid);
}
public override void Down()
{
throw new NotImplementedException();
}
}
}
}
@@ -9,11 +9,12 @@ using Umbraco.Core.Persistence.DatabaseModelDefinitions;
using Umbraco.Core.Persistence.Migrations.Syntax.Create.Index;
using Umbraco.Core.Persistence.Migrations.Syntax.Expressions;
using Umbraco.Core.Persistence.SqlSyntax;
using Umbraco.Tests.TestHelpers;
namespace Umbraco.Tests.Persistence.SyntaxProvider
{
[TestFixture]
public class SqlCeSyntaxProviderTests
public class SqlCeSyntaxProviderTests : BaseUsingSqlCeSyntax
{
[Test]
+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]
@@ -147,7 +147,7 @@ namespace Umbraco.Tests.PropertyEditors
var dataTypeService = new Mock<IDataTypeService>();
dataTypeService.Setup(x => x.GetPreValuesCollectionByDataTypeId(It.IsAny<int>())).Returns(new PreValueCollection(Enumerable.Empty<PreValue>()));
var converter = new Web.PropertyEditors.ValueConverters.ImageCropperValueConverter(dataTypeService.Object);
var converter = new Umbraco.Web.PropertyEditors.ValueConverters.ImageCropperValueConverter(dataTypeService.Object);
var result = converter.ConvertDataToSource(new PublishedPropertyType("test", 0, "test"), val1, false); // does not use type for conversion
var resultShouldMatch = val2.SerializeToCropDataSet();
@@ -234,9 +234,9 @@ namespace Umbraco.Tests.PublishedContent
new PublishedPropertyType("prop1", 1, "?"),
};
var contentType1 = new PublishedContentType(1, "ContentType1", props);
var contentType2 = new PublishedContentType(2, "ContentType2", props);
var contentType2s = new PublishedContentType(3, "ContentType2Sub", props);
var contentType1 = new PublishedContentType(1, "ContentType1", Enumerable.Empty<string>(), props);
var contentType2 = new PublishedContentType(2, "ContentType2", Enumerable.Empty<string>(), props);
var contentType2s = new PublishedContentType(3, "ContentType2Sub", Enumerable.Empty<string>(), props);
cache.Add(new SolidPublishedContent(contentType1)
{
@@ -355,7 +355,11 @@ namespace Umbraco.Tests.PublishedContent
private static readonly PublishedPropertyType Default = new PublishedPropertyType("*", 0, "?");
public AutoPublishedContentType(int id, string alias, IEnumerable<PublishedPropertyType> propertyTypes)
: base(id, alias, propertyTypes)
: base(id, alias, Enumerable.Empty<string>(), propertyTypes)
{ }
public AutoPublishedContentType(int id, string alias, IEnumerable<string> compositionAliases, IEnumerable<PublishedPropertyType> propertyTypes)
: base(id, alias, compositionAliases, propertyTypes)
{ }
public override PublishedPropertyType GetPropertyType(string alias)
@@ -50,7 +50,8 @@ namespace Umbraco.Tests.PublishedContent
new PublishedPropertyType("content", 0, Constants.PropertyEditors.TinyMCEAlias),
new PublishedPropertyType("testRecursive", 0, "?"),
};
var type = new AutoPublishedContentType(0, "anything", propertyTypes);
var compositionAliases = new[] {"MyCompositionAlias"};
var type = new AutoPublishedContentType(0, "anything", compositionAliases, propertyTypes);
PublishedContentType.GetPublishedContentTypeCallback = (alias) => type;
}
@@ -468,6 +469,16 @@ namespace Umbraco.Tests.PublishedContent
Assert.IsNull(doc.FirstChild<IPublishedContent>());
}
[Test]
public void IsComposedOf()
{
var doc = GetNode(1173);
var isComposedOf = doc.IsComposedOf("MyCompositionAlias");
Assert.IsTrue(isComposedOf);
}
[Test]
public void HasProperty()
{
@@ -475,8 +486,7 @@ namespace Umbraco.Tests.PublishedContent
var hasProp = doc.HasProperty(Constants.Conventions.Content.UrlAlias);
Assert.AreEqual(true, (bool)hasProp);
Assert.IsTrue(hasProp);
}
[Test]
@@ -380,7 +380,7 @@ namespace Umbraco.Tests.Routing
var content = umbracoContext.ContentCache.GetById(nodeId);
Assert.IsNotNull(content);
var culture = Web.Models.ContentExtensions.GetCulture(umbracoContext, domainService, ServiceContext.LocalizationService, null, content.Id, content.Path, new Uri(currentUrl));
var culture = global::Umbraco.Web.Models.ContentExtensions.GetCulture(umbracoContext, domainService, ServiceContext.LocalizationService, null, content.Id, content.Path, new Uri(currentUrl));
Assert.AreEqual(expectedCulture, culture.Name);
}
}
@@ -0,0 +1,85 @@
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Web;
using Microsoft.Owin;
using Moq;
using NUnit.Framework;
using Umbraco.Core;
using Umbraco.Core.Configuration.UmbracoSettings;
using Umbraco.Core.Logging;
using Umbraco.Core.Persistence;
using Umbraco.Core.Persistence.SqlSyntax;
using Umbraco.Core.Profiling;
using Umbraco.Tests.TestHelpers;
using Umbraco.Web;
using Umbraco.Web.Routing;
using Umbraco.Web.Security;
using Umbraco.Web.Security.Identity;
namespace Umbraco.Tests.Security
{
[TestFixture]
public class BackOfficeCookieManagerTests
{
[Test]
public void ShouldAuthenticateRequest_When_Not_Configured()
{
//should force app ctx to show not-configured
ConfigurationManager.AppSettings.Set("umbracoConfigurationStatus", "");
var dbCtx = new Mock<DatabaseContext>(Mock.Of<IDatabaseFactory>(), Mock.Of<ILogger>(), Mock.Of<ISqlSyntaxProvider>(), "test");
dbCtx.Setup(x => x.IsDatabaseConfigured).Returns(false);
var appCtx = new ApplicationContext(
dbCtx.Object,
MockHelper.GetMockedServiceContext(),
CacheHelper.CreateDisabledCacheHelper(),
new ProfilingLogger(Mock.Of<ILogger>(), Mock.Of<IProfiler>()));
var umbCtx = UmbracoContext.CreateContext(
Mock.Of<HttpContextBase>(),
appCtx,
new WebSecurity(Mock.Of<HttpContextBase>(), appCtx),
Mock.Of<IUmbracoSettingsSection>(), new List<IUrlProvider>(), false);
var mgr = new BackOfficeCookieManager(Mock.Of<IUmbracoContextAccessor>(accessor => accessor.Value == umbCtx));
var result = mgr.ShouldAuthenticateRequest(Mock.Of<IOwinContext>(), new Uri("http://localhost/umbraco"));
Assert.IsFalse(result);
}
[Test]
public void ShouldAuthenticateRequest_When_Configured()
{
var dbCtx = new Mock<DatabaseContext>(Mock.Of<IDatabaseFactory>(), Mock.Of<ILogger>(), Mock.Of<ISqlSyntaxProvider>(), "test");
dbCtx.Setup(x => x.IsDatabaseConfigured).Returns(true);
var appCtx = new ApplicationContext(
dbCtx.Object,
MockHelper.GetMockedServiceContext(),
CacheHelper.CreateDisabledCacheHelper(),
new ProfilingLogger(Mock.Of<ILogger>(), Mock.Of<IProfiler>()));
var umbCtx = UmbracoContext.CreateContext(
Mock.Of<HttpContextBase>(),
appCtx,
new WebSecurity(Mock.Of<HttpContextBase>(), appCtx),
Mock.Of<IUmbracoSettingsSection>(), new List<IUrlProvider>(), false);
var mgr = new BackOfficeCookieManager(Mock.Of<IUmbracoContextAccessor>(accessor => accessor.Value == umbCtx));
var request = new Mock<OwinRequest>();
request.Setup(owinRequest => owinRequest.Uri).Returns(new Uri("http://localhost/umbraco"));
var result = mgr.ShouldAuthenticateRequest(
Mock.Of<IOwinContext>(context => context.Request == request.Object),
new Uri("http://localhost/umbraco"));
Assert.IsTrue(result);
}
//TODO : Write remaining tests for `ShouldAuthenticateRequest`
}
}
@@ -1,5 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Claims;
using System.Text;
@@ -9,6 +8,7 @@ using Newtonsoft.Json;
using NUnit.Framework;
using Umbraco.Core;
using Umbraco.Core.Security;
using Umbraco.Core.Services;
namespace Umbraco.Tests.Security
{
+39 -22
View File
@@ -75,6 +75,10 @@
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\Lucene.Net.2.9.4.1\lib\net40\Lucene.Net.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Owin, Version=3.0.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.Owin.3.0.1\lib\net45\Microsoft.Owin.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Microsoft.Web.Infrastructure, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<Private>True</Private>
<HintPath>..\packages\Microsoft.Web.Infrastructure.1.0.0.0\lib\net40\Microsoft.Web.Infrastructure.dll</HintPath>
@@ -94,6 +98,10 @@
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\NUnit.2.6.2\lib\nunit.framework.dll</HintPath>
</Reference>
<Reference Include="Owin, Version=1.0.0.0, Culture=neutral, PublicKeyToken=f0ebd12fd5e55cc5, processorArchitecture=MSIL">
<HintPath>..\packages\Owin.1.0\lib\net40\Owin.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Semver">
<HintPath>..\packages\semver.1.1.2\lib\net45\Semver.dll</HintPath>
</Reference>
@@ -102,13 +110,13 @@
<Reference Include="System.configuration" />
<Reference Include="System.Core" />
<Reference Include="System.Data.Entity.Design" />
<Reference Include="System.Data.SqlServerCe, Version=4.0.0.0, Culture=neutral, PublicKeyToken=89845dcd8080cc91, processorArchitecture=MSIL">
<Reference Include="System.Data.SqlServerCe, Version=4.0.0.1, Culture=neutral, PublicKeyToken=89845dcd8080cc91, processorArchitecture=MSIL">
<Private>True</Private>
<HintPath>..\packages\SqlServerCE.4.0.0.0\lib\System.Data.SqlServerCe.dll</HintPath>
<HintPath>..\packages\SqlServerCE.4.0.0.1\lib\System.Data.SqlServerCe.dll</HintPath>
</Reference>
<Reference Include="System.Data.SqlServerCe.Entity, Version=4.0.0.0, Culture=neutral, PublicKeyToken=89845dcd8080cc91, processorArchitecture=MSIL">
<Reference Include="System.Data.SqlServerCe.Entity, Version=4.0.0.1, Culture=neutral, PublicKeyToken=89845dcd8080cc91, processorArchitecture=MSIL">
<Private>True</Private>
<HintPath>..\packages\SqlServerCE.4.0.0.0\lib\System.Data.SqlServerCe.Entity.dll</HintPath>
<HintPath>..\packages\SqlServerCE.4.0.0.1\lib\System.Data.SqlServerCe.Entity.dll</HintPath>
</Reference>
<Reference Include="System.Drawing" />
<Reference Include="System.Net.Http" />
@@ -167,10 +175,11 @@
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="AngularIntegration\AngularAntiForgeryTests.cs" />
<Compile Include="AngularIntegration\ContentModelSerializationTests.cs" />
<Compile Include="AngularIntegration\JsInitializationTests.cs" />
<Compile Include="AngularIntegration\ServerVariablesParserTests.cs" />
<Compile Include="Persistence\Migrations\MigrationStartupHandlerTests.cs" />
<Compile Include="Web\AngularIntegration\AngularAntiForgeryTests.cs" />
<Compile Include="Web\AngularIntegration\ContentModelSerializationTests.cs" />
<Compile Include="Web\AngularIntegration\JsInitializationTests.cs" />
<Compile Include="Web\AngularIntegration\ServerVariablesParserTests.cs" />
<Compile Include="ApplicationContextTests.cs" />
<Compile Include="AttemptTests.cs" />
<Compile Include="Cache\CacheRefresherTests.cs" />
@@ -180,12 +189,12 @@
<Compile Include="Cache\FullDataSetCachePolicyTests.cs" />
<Compile Include="Cache\SingleItemsOnlyCachePolicyTests.cs" />
<Compile Include="Collections\DeepCloneableListTests.cs" />
<Compile Include="Controllers\BackOfficeControllerUnitTests.cs" />
<Compile Include="Web\Controllers\BackOfficeControllerUnitTests.cs" />
<Compile Include="DelegateExtensionsTests.cs" />
<Compile Include="Logging\AsyncRollingFileAppenderTest.cs" />
<Compile Include="Logging\DebugAppender.cs" />
<Compile Include="Logging\ParallelForwarderTest.cs" />
<Compile Include="Mvc\RenderIndexActionSelectorAttributeTests.cs" />
<Compile Include="Web\Mvc\RenderIndexActionSelectorAttributeTests.cs" />
<Compile Include="Persistence\Repositories\AuditRepositoryTest.cs" />
<Compile Include="Persistence\Repositories\DomainRepositoryTest.cs" />
<Compile Include="Persistence\Repositories\PartialViewRepositoryTests.cs" />
@@ -195,6 +204,7 @@
<Compile Include="Resolvers\ResolverBaseTest.cs" />
<Compile Include="Routing\RoutesCacheTests.cs" />
<Compile Include="Routing\UrlRoutingTestBase.cs" />
<Compile Include="Security\BackOfficeCookieManagerTests.cs" />
<Compile Include="Security\UmbracoBackOfficeIdentityTests.cs" />
<Compile Include="Services\ContentTypeServiceExtensionsTests.cs" />
<Compile Include="Services\PublicAccessServiceTests.cs" />
@@ -235,8 +245,9 @@
<Compile Include="Models\UmbracoEntityTests.cs" />
<Compile Include="Models\UserTests.cs" />
<Compile Include="Models\UserTypeTests.cs" />
<Compile Include="Mvc\SurfaceControllerTests.cs" />
<Compile Include="Mvc\UmbracoViewPageTests.cs" />
<Compile Include="Web\Mvc\RenderModelBinderTests.cs" />
<Compile Include="Web\Mvc\SurfaceControllerTests.cs" />
<Compile Include="Web\Mvc\UmbracoViewPageTests.cs" />
<Compile Include="BootManagers\CoreBootManagerTests.cs" />
<Compile Include="BootManagers\WebBootManagerTests.cs" />
<Compile Include="Cache\ObjectCacheProviderTests.cs" />
@@ -311,9 +322,9 @@
<Compile Include="Configurations\UmbracoSettings\ViewstateMoverModuleElementTests.cs" />
<Compile Include="Configurations\UmbracoSettings\WebRoutingElementDefaultTests.cs" />
<Compile Include="Configurations\UmbracoSettings\WebRoutingElementTests.cs" />
<Compile Include="Controllers\WebApiEditors\ContentControllerUnitTests.cs" />
<Compile Include="Controllers\WebApiEditors\FilterAllowedOutgoingContentAttributeTests.cs" />
<Compile Include="Controllers\WebApiEditors\MediaControllerUnitTests.cs" />
<Compile Include="Web\Controllers\WebApiEditors\ContentControllerUnitTests.cs" />
<Compile Include="Web\Controllers\WebApiEditors\FilterAllowedOutgoingContentAttributeTests.cs" />
<Compile Include="Web\Controllers\WebApiEditors\MediaControllerUnitTests.cs" />
<Compile Include="CoreXml\FrameworkXmlTests.cs" />
<Compile Include="DynamicsAndReflection\QueryableExtensionTests.cs" />
<Compile Include="DynamicsAndReflection\ExtensionMethodFinderTests.cs" />
@@ -323,8 +334,8 @@
<Compile Include="Migrations\Upgrades\ValidateV7UpgradeTest.cs" />
<Compile Include="Models\ContentExtensionsTests.cs" />
<Compile Include="Models\UserExtensionsTests.cs" />
<Compile Include="Mvc\MergeParentContextViewDataAttributeTests.cs" />
<Compile Include="Mvc\ViewDataDictionaryExtensionTests.cs" />
<Compile Include="Web\Mvc\MergeParentContextViewDataAttributeTests.cs" />
<Compile Include="Web\Mvc\ViewDataDictionaryExtensionTests.cs" />
<Compile Include="Persistence\PetaPocoExtensionsTest.cs" />
<Compile Include="Persistence\Querying\ContentTypeSqlMappingTests.cs" />
<Compile Include="Persistence\Repositories\MacroRepositoryTest.cs" />
@@ -421,7 +432,7 @@
<Compile Include="PublishedContent\PublishedContentTests.cs" />
<Compile Include="PublishedContent\PublishedMediaTests.cs" />
<Compile Include="HashCodeCombinerTests.cs" />
<Compile Include="Mvc\HtmlHelperExtensionMethodsTests.cs" />
<Compile Include="Web\Mvc\HtmlHelperExtensionMethodsTests.cs" />
<Compile Include="IO\IOHelperTest.cs" />
<Compile Include="LibraryTests.cs" />
<Compile Include="PropertyEditors\PropertyEditorValueConverterTests.cs" />
@@ -506,7 +517,7 @@
<DependentUpon>ImportResources.resx</DependentUpon>
</Compile>
<Compile Include="Services\ThreadSafetyServiceTest.cs" />
<Compile Include="Controllers\PluginControllerAreaTests.cs" />
<Compile Include="Web\Controllers\PluginControllerAreaTests.cs" />
<Compile Include="Cache\DistributedCache\DistributedCacheTests.cs" />
<Compile Include="Templates\MasterPageHelperTests.cs" />
<Compile Include="TestHelpers\BaseDatabaseFactoryTest.cs" />
@@ -570,6 +581,7 @@
<Compile Include="Plugins\TypeFinderTests.cs" />
<Compile Include="Routing\UmbracoModuleTests.cs" />
<Compile Include="VersionExtensionTests.cs" />
<Compile Include="Web\WebExtensionMethodTests.cs" />
<Compile Include="XmlExtensionsTests.cs" />
<Compile Include="XmlHelperTests.cs" />
</ItemGroup>
@@ -739,11 +751,16 @@
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<PropertyGroup>
<PostBuildEvent>xcopy "$(ProjectDir)"..\packages\SqlServerCE.4.0.0.0\amd64\*.* "$(TargetDir)amd64\" /Y /F /E /D
xcopy "$(ProjectDir)"..\packages\SqlServerCE.4.0.0.0\x86\*.* "$(TargetDir)x86\" /Y /F /E /D</PostBuildEvent>
<PostBuildEvent>
</PostBuildEvent>
</PropertyGroup>
<Import Project="$(SolutionDir)\.nuget\nuget.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
<PropertyGroup>
<PreBuildEvent>xcopy "$(ProjectDir)"..\packages\SqlServerCE.4.0.0.1\amd64\*.* "$(TargetDir)amd64\" /Y /F /E /I /C /D
xcopy "$(ProjectDir)"..\packages\SqlServerCE.4.0.0.1\x86\*.* "$(TargetDir)x86\" /Y /F /E /I /C /D</PreBuildEvent>
</PropertyGroup>
<Import Project="$(SolutionDir)\.nuget\nuget.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
@@ -1,20 +1,11 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.IO;
using System.Net;
using System.Security.Claims;
using System.Security.Principal;
using System.Text;
using System.Threading.Tasks;
using System.Web;
using System.Web.Security;
using NUnit.Framework;
using Umbraco.Core.Security;
using Umbraco.Tests.TestHelpers;
using Umbraco.Web.WebApi.Filters;
namespace Umbraco.Tests.AngularIntegration
namespace Umbraco.Tests.Web.AngularIntegration
{
[TestFixture]
public class AngularAntiForgeryTests
@@ -1,80 +1,77 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using NUnit.Framework;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Umbraco.Core;
using Umbraco.Web.Models.ContentEditing;
namespace Umbraco.Tests.AngularIntegration
{
[TestFixture]
public class ContentModelSerializationTests
{
[Test]
public void Content_Display_To_Json()
{
//create 3 tabs with 3 properties each
var tabs = new List<Tab<ContentPropertyDisplay>>();
for (var tabIndex = 0; tabIndex < 3; tabIndex ++)
{
var props = new List<ContentPropertyDisplay>();
for (var propertyIndex = 0; propertyIndex < 3; propertyIndex ++)
{
props.Add(new ContentPropertyDisplay
{
Alias = "property" + propertyIndex,
Label = "Property " + propertyIndex,
Id = propertyIndex,
Value = "value" + propertyIndex,
Config = new Dictionary<string, object> {{ propertyIndex.ToInvariantString(), "value" }},
Description = "Description " + propertyIndex,
View = "~/Views/View" + propertyIndex,
HideLabel = false
});
}
tabs.Add(new Tab<ContentPropertyDisplay>()
{
Alias = "Tab" + tabIndex,
Label = "Tab" + tabIndex,
Properties = props
});
}
var displayModel = new ContentItemDisplay
{
Id = 1234,
Name = "Test",
Tabs = tabs
};
var json = JsonConvert.SerializeObject(displayModel);
var jObject = JObject.Parse(json);
Assert.AreEqual("1234", jObject["id"].ToString());
Assert.AreEqual("Test", jObject["name"].ToString());
Assert.AreEqual(3, jObject["tabs"].Count());
for (var tab = 0; tab < jObject["tabs"].Count(); tab++)
{
Assert.AreEqual("Tab" + tab, jObject["tabs"][tab]["alias"].ToString());
Assert.AreEqual("Tab" + tab, jObject["tabs"][tab]["label"].ToString());
Assert.AreEqual(3, jObject["tabs"][tab]["properties"].Count());
for (var prop = 0; prop < jObject["tabs"][tab]["properties"].Count(); prop++)
{
Assert.AreEqual("property" + prop, jObject["tabs"][tab]["properties"][prop]["alias"].ToString());
Assert.AreEqual("Property " + prop, jObject["tabs"][tab]["properties"][prop]["label"].ToString());
Assert.AreEqual(prop, jObject["tabs"][tab]["properties"][prop]["id"].Value<int>());
Assert.AreEqual("value" + prop, jObject["tabs"][tab]["properties"][prop]["value"].ToString());
Assert.AreEqual("{\"" + prop + "\":\"value\"}", jObject["tabs"][tab]["properties"][prop]["config"].ToString(Formatting.None));
Assert.AreEqual("Description " + prop, jObject["tabs"][tab]["properties"][prop]["description"].ToString());
Assert.AreEqual(false, jObject["tabs"][tab]["properties"][prop]["hideLabel"].Value<bool>());
}
}
}
}
}
using System.Collections.Generic;
using System.Linq;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using NUnit.Framework;
using Umbraco.Core;
using Umbraco.Web.Models.ContentEditing;
namespace Umbraco.Tests.Web.AngularIntegration
{
[TestFixture]
public class ContentModelSerializationTests
{
[Test]
public void Content_Display_To_Json()
{
//create 3 tabs with 3 properties each
var tabs = new List<Tab<ContentPropertyDisplay>>();
for (var tabIndex = 0; tabIndex < 3; tabIndex ++)
{
var props = new List<ContentPropertyDisplay>();
for (var propertyIndex = 0; propertyIndex < 3; propertyIndex ++)
{
props.Add(new ContentPropertyDisplay
{
Alias = "property" + propertyIndex,
Label = "Property " + propertyIndex,
Id = propertyIndex,
Value = "value" + propertyIndex,
Config = new Dictionary<string, object> {{ propertyIndex.ToInvariantString(), "value" }},
Description = "Description " + propertyIndex,
View = "~/Views/View" + propertyIndex,
HideLabel = false
});
}
tabs.Add(new Tab<ContentPropertyDisplay>()
{
Alias = "Tab" + tabIndex,
Label = "Tab" + tabIndex,
Properties = props
});
}
var displayModel = new ContentItemDisplay
{
Id = 1234,
Name = "Test",
Tabs = tabs
};
var json = JsonConvert.SerializeObject(displayModel);
var jObject = JObject.Parse(json);
Assert.AreEqual("1234", jObject["id"].ToString());
Assert.AreEqual("Test", jObject["name"].ToString());
Assert.AreEqual(3, jObject["tabs"].Count());
for (var tab = 0; tab < jObject["tabs"].Count(); tab++)
{
Assert.AreEqual("Tab" + tab, jObject["tabs"][tab]["alias"].ToString());
Assert.AreEqual("Tab" + tab, jObject["tabs"][tab]["label"].ToString());
Assert.AreEqual(3, jObject["tabs"][tab]["properties"].Count());
for (var prop = 0; prop < jObject["tabs"][tab]["properties"].Count(); prop++)
{
Assert.AreEqual("property" + prop, jObject["tabs"][tab]["properties"][prop]["alias"].ToString());
Assert.AreEqual("Property " + prop, jObject["tabs"][tab]["properties"][prop]["label"].ToString());
Assert.AreEqual(prop, jObject["tabs"][tab]["properties"][prop]["id"].Value<int>());
Assert.AreEqual("value" + prop, jObject["tabs"][tab]["properties"][prop]["value"].ToString());
Assert.AreEqual("{\"" + prop + "\":\"value\"}", jObject["tabs"][tab]["properties"][prop]["config"].ToString(Formatting.None));
Assert.AreEqual("Description " + prop, jObject["tabs"][tab]["properties"][prop]["description"].ToString());
Assert.AreEqual(false, jObject["tabs"][tab]["properties"][prop]["hideLabel"].Value<bool>());
}
}
}
}
}
@@ -1,41 +1,36 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using NUnit.Framework;
using Newtonsoft.Json.Linq;
using Umbraco.Core.Manifest;
using Umbraco.Web.UI.JavaScript;
namespace Umbraco.Tests.AngularIntegration
{
[TestFixture]
public class JsInitializationTests
{
[Test]
public void Get_Default_Init()
{
var init = JsInitialization.GetDefaultInitialization();
Assert.IsTrue(init.Any());
}
[Test]
public void Parse_Main()
{
var result = JsInitialization.ParseMain(new[] {"[World]", "Hello" });
Assert.AreEqual(@"LazyLoad.js([World], function () {
//we need to set the legacy UmbClientMgr path
UmbClientMgr.setUmbracoPath('Hello');
jQuery(document).ready(function () {
angular.bootstrap(document, ['umbraco']);
});
});", result);
}
}
}
using System.Linq;
using NUnit.Framework;
using Umbraco.Core;
using Umbraco.Web.UI.JavaScript;
namespace Umbraco.Tests.Web.AngularIntegration
{
[TestFixture]
public class JsInitializationTests
{
[Test]
public void Get_Default_Init()
{
var init = JsInitialization.GetDefaultInitialization();
Assert.IsTrue(init.Any());
}
[Test]
public void Parse_Main()
{
var result = JsInitialization.ParseMain(new[] {"[World]", "Hello" });
Assert.AreEqual(@"LazyLoad.js([World], function () {
//we need to set the legacy UmbClientMgr path
UmbClientMgr.setUmbracoPath('Hello');
jQuery(document).ready(function () {
angular.bootstrap(document, ['umbraco']);
});
});".StripWhitespace(), result.StripWhitespace());
}
}
}
@@ -1,33 +1,34 @@
using System.Collections.Generic;
using NUnit.Framework;
using Umbraco.Web.UI.JavaScript;
namespace Umbraco.Tests.AngularIntegration
{
[TestFixture]
public class ServerVariablesParserTests
{
[Test]
public void Parse()
{
var d = new Dictionary<string, object>();
d.Add("test1", "Test 1");
d.Add("test2", "Test 2");
d.Add("test3", "Test 3");
d.Add("test4", "Test 4");
d.Add("test5", "Test 5");
var output = ServerVariablesParser.Parse(d);
Assert.IsTrue(output.Contains(@"Umbraco.Sys.ServerVariables = {
""test1"": ""Test 1"",
""test2"": ""Test 2"",
""test3"": ""Test 3"",
""test4"": ""Test 4"",
""test5"": ""Test 5""
} ;"));
}
}
using System.Collections.Generic;
using NUnit.Framework;
using Umbraco.Web.UI.JavaScript;
using Umbraco.Core;
namespace Umbraco.Tests.Web.AngularIntegration
{
[TestFixture]
public class ServerVariablesParserTests
{
[Test]
public void Parse()
{
var d = new Dictionary<string, object>();
d.Add("test1", "Test 1");
d.Add("test2", "Test 2");
d.Add("test3", "Test 3");
d.Add("test4", "Test 4");
d.Add("test5", "Test 5");
var output = ServerVariablesParser.Parse(d).StripWhitespace();
Assert.IsTrue(output.Contains(@"Umbraco.Sys.ServerVariables = {
""test1"": ""Test 1"",
""test2"": ""Test 2"",
""test3"": ""Test 3"",
""test4"": ""Test 4"",
""test5"": ""Test 5""
} ;".StripWhitespace()));
}
}
}
@@ -2,7 +2,7 @@
using NUnit.Framework;
using Umbraco.Web.Editors;
namespace Umbraco.Tests.Controllers
namespace Umbraco.Tests.Web.Controllers
{
[TestFixture]
public class BackOfficeControllerUnitTests
@@ -4,7 +4,7 @@ using Umbraco.Tests.TestHelpers;
using Umbraco.Web;
using Umbraco.Web.Mvc;
namespace Umbraco.Tests.Controllers
namespace Umbraco.Tests.Web.Controllers
{
[TestFixture]
public class PluginControllerAreaTests : BaseWebTest
@@ -1,366 +1,366 @@
using System.Collections.Generic;
using System.Web.Http;
using Moq;
using NUnit.Framework;
using Umbraco.Core.Models;
using Umbraco.Core.Models.Membership;
using Umbraco.Core.Services;
using Umbraco.Web.Editors;
namespace Umbraco.Tests.Controllers.WebApiEditors
{
[TestFixture]
public class ContentControllerUnitTests
{
[Test]
public void Access_Allowed_By_Path()
{
//arrange
var userMock = new Mock<IUser>();
userMock.Setup(u => u.Id).Returns(9);
userMock.Setup(u => u.StartContentId).Returns(-1);
var user = userMock.Object;
var contentMock = new Mock<IContent>();
contentMock.Setup(c => c.Path).Returns("-1,1234,5678");
var content = contentMock.Object;
var contentServiceMock = new Mock<IContentService>();
contentServiceMock.Setup(x => x.GetById(1234)).Returns(content);
var contentService = contentServiceMock.Object;
//act
var result = ContentController.CheckPermissions(new Dictionary<string, object>(), user, null, contentService, 1234);
//assert
Assert.IsTrue(result);
}
[Test]
public void Throws_Exception_When_No_Content_Found()
{
//arrange
var userMock = new Mock<IUser>();
userMock.Setup(u => u.Id).Returns(9);
userMock.Setup(u => u.StartContentId).Returns(-1);
var user = userMock.Object;
var contentMock = new Mock<IContent>();
contentMock.Setup(c => c.Path).Returns("-1,1234,5678");
var content = contentMock.Object;
var contentServiceMock = new Mock<IContentService>();
contentServiceMock.Setup(x => x.GetById(0)).Returns(content);
var contentService = contentServiceMock.Object;
var userServiceMock = new Mock<IUserService>();
var permissions = new List<EntityPermission>();
userServiceMock.Setup(x => x.GetPermissions(user, 1234)).Returns(permissions);
var userService = userServiceMock.Object;
//act/assert
Assert.Throws<HttpResponseException>(() => ContentController.CheckPermissions(new Dictionary<string, object>(), user, userService, contentService, 1234, new[] { 'F' }));
}
[Test]
public void No_Access_By_Path()
{
//arrange
var userMock = new Mock<IUser>();
userMock.Setup(u => u.Id).Returns(9);
userMock.Setup(u => u.StartContentId).Returns(9876);
var user = userMock.Object;
var contentMock = new Mock<IContent>();
contentMock.Setup(c => c.Path).Returns("-1,1234,5678");
var content = contentMock.Object;
var contentServiceMock = new Mock<IContentService>();
contentServiceMock.Setup(x => x.GetById(1234)).Returns(content);
var contentService = contentServiceMock.Object;
var userServiceMock = new Mock<IUserService>();
var permissions = new List<EntityPermission>();
userServiceMock.Setup(x => x.GetPermissions(user, 1234)).Returns(permissions);
var userService = userServiceMock.Object;
//act
var result = ContentController.CheckPermissions(new Dictionary<string, object>(), user, userService, contentService, 1234, new[] { 'F'});
//assert
Assert.IsFalse(result);
}
[Test]
public void No_Access_By_Permission()
{
//arrange
var userMock = new Mock<IUser>();
userMock.Setup(u => u.Id).Returns(9);
userMock.Setup(u => u.StartContentId).Returns(-1);
var user = userMock.Object;
var contentMock = new Mock<IContent>();
contentMock.Setup(c => c.Path).Returns("-1,1234,5678");
var content = contentMock.Object;
var contentServiceMock = new Mock<IContentService>();
contentServiceMock.Setup(x => x.GetById(1234)).Returns(content);
var contentService = contentServiceMock.Object;
var userServiceMock = new Mock<IUserService>();
var permissions = new List<EntityPermission>
{
new EntityPermission(9, 1234, new string[]{ "A", "B", "C" })
};
userServiceMock.Setup(x => x.GetPermissions(user, 1234)).Returns(permissions);
var userService = userServiceMock.Object;
//act
var result = ContentController.CheckPermissions(new Dictionary<string, object>(), user, userService, contentService, 1234, new[] { 'F'});
//assert
Assert.IsFalse(result);
}
[Test]
public void Access_Allowed_By_Permission()
{
//arrange
var userMock = new Mock<IUser>();
userMock.Setup(u => u.Id).Returns(9);
userMock.Setup(u => u.StartContentId).Returns(-1);
var user = userMock.Object;
var contentMock = new Mock<IContent>();
contentMock.Setup(c => c.Path).Returns("-1,1234,5678");
var content = contentMock.Object;
var contentServiceMock = new Mock<IContentService>();
contentServiceMock.Setup(x => x.GetById(1234)).Returns(content);
var contentService = contentServiceMock.Object;
var userServiceMock = new Mock<IUserService>();
var permissions = new List<EntityPermission>
{
new EntityPermission(9, 1234, new string[]{ "A", "F", "C" })
};
userServiceMock.Setup(x => x.GetPermissions(user, 1234)).Returns(permissions);
var userService = userServiceMock.Object;
//act
var result = ContentController.CheckPermissions(new Dictionary<string, object>(), user, userService, contentService, 1234, new[] { 'F'});
//assert
Assert.IsTrue(result);
}
[Test]
public void Access_To_Root_By_Path()
{
//arrange
var userMock = new Mock<IUser>();
userMock.Setup(u => u.Id).Returns(0);
userMock.Setup(u => u.StartContentId).Returns(-1);
var user = userMock.Object;
//act
var result = ContentController.CheckPermissions(new Dictionary<string, object>(), user, null, null, -1);
//assert
Assert.IsTrue(result);
}
[Test]
public void Access_To_Recycle_Bin_By_Path()
{
//arrange
var userMock = new Mock<IUser>();
userMock.Setup(u => u.Id).Returns(0);
userMock.Setup(u => u.StartContentId).Returns(-1);
var user = userMock.Object;
//act
var result = ContentController.CheckPermissions(new Dictionary<string, object>(), user, null, null, -20);
//assert
Assert.IsTrue(result);
}
[Test]
public void No_Access_To_Recycle_Bin_By_Path()
{
//arrange
var userMock = new Mock<IUser>();
userMock.Setup(u => u.Id).Returns(0);
userMock.Setup(u => u.StartContentId).Returns(1234);
var user = userMock.Object;
//act
var result = ContentController.CheckPermissions(new Dictionary<string, object>(), user, null, null, -20);
//assert
Assert.IsFalse(result);
}
[Test]
public void No_Access_To_Root_By_Path()
{
//arrange
var userMock = new Mock<IUser>();
userMock.Setup(u => u.Id).Returns(0);
userMock.Setup(u => u.StartContentId).Returns(1234);
var user = userMock.Object;
//act
var result = ContentController.CheckPermissions(new Dictionary<string, object>(), user, null, null, -1);
//assert
Assert.IsFalse(result);
}
[Test]
public void Access_To_Root_By_Permission()
{
//arrange
var userMock = new Mock<IUser>();
userMock.Setup(u => u.Id).Returns(0);
userMock.Setup(u => u.StartContentId).Returns(-1);
var user = userMock.Object;
var userServiceMock = new Mock<IUserService>();
var permissions = new List<EntityPermission>
{
new EntityPermission(9, 1234, new string[]{ "A" })
};
userServiceMock.Setup(x => x.GetPermissions(user, -1)).Returns(permissions);
var userService = userServiceMock.Object;
//act
var result = ContentController.CheckPermissions(new Dictionary<string, object>(), user, userService, null, -1, new[] { 'A'});
//assert
Assert.IsTrue(result);
}
[Test]
public void No_Access_To_Root_By_Permission()
{
//arrange
var userMock = new Mock<IUser>();
userMock.Setup(u => u.Id).Returns(0);
userMock.Setup(u => u.StartContentId).Returns(-1);
var user = userMock.Object;
var userServiceMock = new Mock<IUserService>();
var permissions = new List<EntityPermission>
{
new EntityPermission(9, 1234, new string[]{ "A" })
};
userServiceMock.Setup(x => x.GetPermissions(user, -1)).Returns(permissions);
var userService = userServiceMock.Object;
//act
var result = ContentController.CheckPermissions(new Dictionary<string, object>(), user, userService, null, -1, new[] { 'B'});
//assert
Assert.IsFalse(result);
}
[Test]
public void Access_To_Recycle_Bin_By_Permission()
{
//arrange
var userMock = new Mock<IUser>();
userMock.Setup(u => u.Id).Returns(0);
userMock.Setup(u => u.StartContentId).Returns(-1);
var user = userMock.Object;
var userServiceMock = new Mock<IUserService>();
var permissions = new List<EntityPermission>
{
new EntityPermission(9, 1234, new string[]{ "A" })
};
userServiceMock.Setup(x => x.GetPermissions(user, -20)).Returns(permissions);
var userService = userServiceMock.Object;
//act
var result = ContentController.CheckPermissions(new Dictionary<string, object>(), user, userService, null, -20, new[] { 'A'});
//assert
Assert.IsTrue(result);
}
[Test]
public void No_Access_To_Recycle_Bin_By_Permission()
{
//arrange
var userMock = new Mock<IUser>();
userMock.Setup(u => u.Id).Returns(0);
userMock.Setup(u => u.StartContentId).Returns(-1);
var user = userMock.Object;
var userServiceMock = new Mock<IUserService>();
var permissions = new List<EntityPermission>
{
new EntityPermission(9, 1234, new string[]{ "A" })
};
userServiceMock.Setup(x => x.GetPermissions(user, -20)).Returns(permissions);
var userService = userServiceMock.Object;
//act
var result = ContentController.CheckPermissions(new Dictionary<string, object>(), user, userService, null, -20, new[] { 'B'});
//assert
Assert.IsFalse(result);
}
}
//NOTE: The below self hosted stuff does work so need to get some tests written. Some are not possible atm because
// of the legacy SQL calls like checking permissions.
//[TestFixture]
//public class ContentControllerHostedTests : BaseRoutingTest
//{
// protected override DatabaseBehavior DatabaseTestBehavior
// {
// get { return DatabaseBehavior.NoDatabasePerFixture; }
// }
// public override void TearDown()
// {
// base.TearDown();
// UmbracoAuthorizeAttribute.Enable = true;
// UmbracoApplicationAuthorizeAttribute.Enable = true;
// }
// /// <summary>
// /// Tests to ensure that the response filter works so that any items the user
// /// doesn't have access to are removed
// /// </summary>
// [Test]
// public async void Get_By_Ids_Response_Filtered()
// {
// UmbracoAuthorizeAttribute.Enable = false;
// UmbracoApplicationAuthorizeAttribute.Enable = false;
// var baseUrl = string.Format("http://{0}:9876", Environment.MachineName);
// var url = baseUrl + "/api/Content/GetByIds?ids=1&ids=2";
// var routingCtx = GetRoutingContext(url, 1234, null, true);
// var config = new HttpSelfHostConfiguration(baseUrl);
// using (var server = new HttpSelfHostServer(config))
// {
// var route = config.Routes.MapHttpRoute("test", "api/Content/GetByIds",
// new
// {
// controller = "Content",
// action = "GetByIds",
// id = RouteParameter.Optional
// });
// route.DataTokens["Namespaces"] = new string[] { "Umbraco.Web.Editors" };
// var client = new HttpClient(server);
// var request = new HttpRequestMessage
// {
// RequestUri = new Uri(url),
// Method = HttpMethod.Get
// };
// var result = await client.SendAsync(request);
// }
// }
//}
}
using System.Collections.Generic;
using System.Web.Http;
using Moq;
using NUnit.Framework;
using Umbraco.Core.Models;
using Umbraco.Core.Models.Membership;
using Umbraco.Core.Services;
using Umbraco.Web.Editors;
namespace Umbraco.Tests.Web.Controllers.WebApiEditors
{
[TestFixture]
public class ContentControllerUnitTests
{
[Test]
public void Access_Allowed_By_Path()
{
//arrange
var userMock = new Mock<IUser>();
userMock.Setup(u => u.Id).Returns(9);
userMock.Setup(u => u.StartContentId).Returns(-1);
var user = userMock.Object;
var contentMock = new Mock<IContent>();
contentMock.Setup(c => c.Path).Returns("-1,1234,5678");
var content = contentMock.Object;
var contentServiceMock = new Mock<IContentService>();
contentServiceMock.Setup(x => x.GetById(1234)).Returns(content);
var contentService = contentServiceMock.Object;
//act
var result = ContentController.CheckPermissions(new Dictionary<string, object>(), user, null, contentService, 1234);
//assert
Assert.IsTrue(result);
}
[Test]
public void Throws_Exception_When_No_Content_Found()
{
//arrange
var userMock = new Mock<IUser>();
userMock.Setup(u => u.Id).Returns(9);
userMock.Setup(u => u.StartContentId).Returns(-1);
var user = userMock.Object;
var contentMock = new Mock<IContent>();
contentMock.Setup(c => c.Path).Returns("-1,1234,5678");
var content = contentMock.Object;
var contentServiceMock = new Mock<IContentService>();
contentServiceMock.Setup(x => x.GetById(0)).Returns(content);
var contentService = contentServiceMock.Object;
var userServiceMock = new Mock<IUserService>();
var permissions = new List<EntityPermission>();
userServiceMock.Setup(x => x.GetPermissions(user, 1234)).Returns(permissions);
var userService = userServiceMock.Object;
//act/assert
Assert.Throws<HttpResponseException>(() => ContentController.CheckPermissions(new Dictionary<string, object>(), user, userService, contentService, 1234, new[] { 'F' }));
}
[Test]
public void No_Access_By_Path()
{
//arrange
var userMock = new Mock<IUser>();
userMock.Setup(u => u.Id).Returns(9);
userMock.Setup(u => u.StartContentId).Returns(9876);
var user = userMock.Object;
var contentMock = new Mock<IContent>();
contentMock.Setup(c => c.Path).Returns("-1,1234,5678");
var content = contentMock.Object;
var contentServiceMock = new Mock<IContentService>();
contentServiceMock.Setup(x => x.GetById(1234)).Returns(content);
var contentService = contentServiceMock.Object;
var userServiceMock = new Mock<IUserService>();
var permissions = new List<EntityPermission>();
userServiceMock.Setup(x => x.GetPermissions(user, 1234)).Returns(permissions);
var userService = userServiceMock.Object;
//act
var result = ContentController.CheckPermissions(new Dictionary<string, object>(), user, userService, contentService, 1234, new[] { 'F'});
//assert
Assert.IsFalse(result);
}
[Test]
public void No_Access_By_Permission()
{
//arrange
var userMock = new Mock<IUser>();
userMock.Setup(u => u.Id).Returns(9);
userMock.Setup(u => u.StartContentId).Returns(-1);
var user = userMock.Object;
var contentMock = new Mock<IContent>();
contentMock.Setup(c => c.Path).Returns("-1,1234,5678");
var content = contentMock.Object;
var contentServiceMock = new Mock<IContentService>();
contentServiceMock.Setup(x => x.GetById(1234)).Returns(content);
var contentService = contentServiceMock.Object;
var userServiceMock = new Mock<IUserService>();
var permissions = new List<EntityPermission>
{
new EntityPermission(9, 1234, new string[]{ "A", "B", "C" })
};
userServiceMock.Setup(x => x.GetPermissions(user, 1234)).Returns(permissions);
var userService = userServiceMock.Object;
//act
var result = ContentController.CheckPermissions(new Dictionary<string, object>(), user, userService, contentService, 1234, new[] { 'F'});
//assert
Assert.IsFalse(result);
}
[Test]
public void Access_Allowed_By_Permission()
{
//arrange
var userMock = new Mock<IUser>();
userMock.Setup(u => u.Id).Returns(9);
userMock.Setup(u => u.StartContentId).Returns(-1);
var user = userMock.Object;
var contentMock = new Mock<IContent>();
contentMock.Setup(c => c.Path).Returns("-1,1234,5678");
var content = contentMock.Object;
var contentServiceMock = new Mock<IContentService>();
contentServiceMock.Setup(x => x.GetById(1234)).Returns(content);
var contentService = contentServiceMock.Object;
var userServiceMock = new Mock<IUserService>();
var permissions = new List<EntityPermission>
{
new EntityPermission(9, 1234, new string[]{ "A", "F", "C" })
};
userServiceMock.Setup(x => x.GetPermissions(user, 1234)).Returns(permissions);
var userService = userServiceMock.Object;
//act
var result = ContentController.CheckPermissions(new Dictionary<string, object>(), user, userService, contentService, 1234, new[] { 'F'});
//assert
Assert.IsTrue(result);
}
[Test]
public void Access_To_Root_By_Path()
{
//arrange
var userMock = new Mock<IUser>();
userMock.Setup(u => u.Id).Returns(0);
userMock.Setup(u => u.StartContentId).Returns(-1);
var user = userMock.Object;
//act
var result = ContentController.CheckPermissions(new Dictionary<string, object>(), user, null, null, -1);
//assert
Assert.IsTrue(result);
}
[Test]
public void Access_To_Recycle_Bin_By_Path()
{
//arrange
var userMock = new Mock<IUser>();
userMock.Setup(u => u.Id).Returns(0);
userMock.Setup(u => u.StartContentId).Returns(-1);
var user = userMock.Object;
//act
var result = ContentController.CheckPermissions(new Dictionary<string, object>(), user, null, null, -20);
//assert
Assert.IsTrue(result);
}
[Test]
public void No_Access_To_Recycle_Bin_By_Path()
{
//arrange
var userMock = new Mock<IUser>();
userMock.Setup(u => u.Id).Returns(0);
userMock.Setup(u => u.StartContentId).Returns(1234);
var user = userMock.Object;
//act
var result = ContentController.CheckPermissions(new Dictionary<string, object>(), user, null, null, -20);
//assert
Assert.IsFalse(result);
}
[Test]
public void No_Access_To_Root_By_Path()
{
//arrange
var userMock = new Mock<IUser>();
userMock.Setup(u => u.Id).Returns(0);
userMock.Setup(u => u.StartContentId).Returns(1234);
var user = userMock.Object;
//act
var result = ContentController.CheckPermissions(new Dictionary<string, object>(), user, null, null, -1);
//assert
Assert.IsFalse(result);
}
[Test]
public void Access_To_Root_By_Permission()
{
//arrange
var userMock = new Mock<IUser>();
userMock.Setup(u => u.Id).Returns(0);
userMock.Setup(u => u.StartContentId).Returns(-1);
var user = userMock.Object;
var userServiceMock = new Mock<IUserService>();
var permissions = new List<EntityPermission>
{
new EntityPermission(9, 1234, new string[]{ "A" })
};
userServiceMock.Setup(x => x.GetPermissions(user, -1)).Returns(permissions);
var userService = userServiceMock.Object;
//act
var result = ContentController.CheckPermissions(new Dictionary<string, object>(), user, userService, null, -1, new[] { 'A'});
//assert
Assert.IsTrue(result);
}
[Test]
public void No_Access_To_Root_By_Permission()
{
//arrange
var userMock = new Mock<IUser>();
userMock.Setup(u => u.Id).Returns(0);
userMock.Setup(u => u.StartContentId).Returns(-1);
var user = userMock.Object;
var userServiceMock = new Mock<IUserService>();
var permissions = new List<EntityPermission>
{
new EntityPermission(9, 1234, new string[]{ "A" })
};
userServiceMock.Setup(x => x.GetPermissions(user, -1)).Returns(permissions);
var userService = userServiceMock.Object;
//act
var result = ContentController.CheckPermissions(new Dictionary<string, object>(), user, userService, null, -1, new[] { 'B'});
//assert
Assert.IsFalse(result);
}
[Test]
public void Access_To_Recycle_Bin_By_Permission()
{
//arrange
var userMock = new Mock<IUser>();
userMock.Setup(u => u.Id).Returns(0);
userMock.Setup(u => u.StartContentId).Returns(-1);
var user = userMock.Object;
var userServiceMock = new Mock<IUserService>();
var permissions = new List<EntityPermission>
{
new EntityPermission(9, 1234, new string[]{ "A" })
};
userServiceMock.Setup(x => x.GetPermissions(user, -20)).Returns(permissions);
var userService = userServiceMock.Object;
//act
var result = ContentController.CheckPermissions(new Dictionary<string, object>(), user, userService, null, -20, new[] { 'A'});
//assert
Assert.IsTrue(result);
}
[Test]
public void No_Access_To_Recycle_Bin_By_Permission()
{
//arrange
var userMock = new Mock<IUser>();
userMock.Setup(u => u.Id).Returns(0);
userMock.Setup(u => u.StartContentId).Returns(-1);
var user = userMock.Object;
var userServiceMock = new Mock<IUserService>();
var permissions = new List<EntityPermission>
{
new EntityPermission(9, 1234, new string[]{ "A" })
};
userServiceMock.Setup(x => x.GetPermissions(user, -20)).Returns(permissions);
var userService = userServiceMock.Object;
//act
var result = ContentController.CheckPermissions(new Dictionary<string, object>(), user, userService, null, -20, new[] { 'B'});
//assert
Assert.IsFalse(result);
}
}
//NOTE: The below self hosted stuff does work so need to get some tests written. Some are not possible atm because
// of the legacy SQL calls like checking permissions.
//[TestFixture]
//public class ContentControllerHostedTests : BaseRoutingTest
//{
// protected override DatabaseBehavior DatabaseTestBehavior
// {
// get { return DatabaseBehavior.NoDatabasePerFixture; }
// }
// public override void TearDown()
// {
// base.TearDown();
// UmbracoAuthorizeAttribute.Enable = true;
// UmbracoApplicationAuthorizeAttribute.Enable = true;
// }
// /// <summary>
// /// Tests to ensure that the response filter works so that any items the user
// /// doesn't have access to are removed
// /// </summary>
// [Test]
// public async void Get_By_Ids_Response_Filtered()
// {
// UmbracoAuthorizeAttribute.Enable = false;
// UmbracoApplicationAuthorizeAttribute.Enable = false;
// var baseUrl = string.Format("http://{0}:9876", Environment.MachineName);
// var url = baseUrl + "/api/Content/GetByIds?ids=1&ids=2";
// var routingCtx = GetRoutingContext(url, 1234, null, true);
// var config = new HttpSelfHostConfiguration(baseUrl);
// using (var server = new HttpSelfHostServer(config))
// {
// var route = config.Routes.MapHttpRoute("test", "api/Content/GetByIds",
// new
// {
// controller = "Content",
// action = "GetByIds",
// id = RouteParameter.Optional
// });
// route.DataTokens["Namespaces"] = new string[] { "Umbraco.Web.Editors" };
// var client = new HttpClient(server);
// var request = new HttpRequestMessage
// {
// RequestUri = new Uri(url),
// Method = HttpMethod.Get
// };
// var result = await client.SendAsync(request);
// }
// }
//}
}
@@ -1,136 +1,136 @@
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Net.Http.Formatting;
using System.Net.Http.Headers;
using Moq;
using NUnit.Framework;
using Umbraco.Core;
using Umbraco.Core.Models.Membership;
using Umbraco.Core.Services;
using Umbraco.Web.Models.ContentEditing;
using Umbraco.Web.WebApi.Filters;
namespace Umbraco.Tests.Controllers.WebApiEditors
{
[TestFixture]
public class FilterAllowedOutgoingContentAttributeTests
{
[Test]
public void GetValueFromResponse_Already_EnumerableContent()
{
var att = new FilterAllowedOutgoingContentAttribute(typeof(IEnumerable<ContentItemBasic>));
var val = new List<ContentItemBasic>() {new ContentItemBasic()};
var result = att.GetValueFromResponse(
new ObjectContent(typeof (IEnumerable<ContentItemBasic>),
val,
new JsonMediaTypeFormatter(),
new MediaTypeHeaderValue("html/text")));
Assert.AreEqual(val, result);
Assert.AreEqual(1, ((IEnumerable<ContentItemBasic>)result).Count());
}
[Test]
public void GetValueFromResponse_From_Property()
{
var att = new FilterAllowedOutgoingContentAttribute(typeof(IEnumerable<ContentItemBasic>), "MyList");
var val = new List<ContentItemBasic>() { new ContentItemBasic() };
var container = new MyTestClass() {MyList = val};
var result = att.GetValueFromResponse(
new ObjectContent(typeof(MyTestClass),
container,
new JsonMediaTypeFormatter(),
new MediaTypeHeaderValue("html/text")));
Assert.AreEqual(val, result);
Assert.AreEqual(1, ((IEnumerable<ContentItemBasic>)result).Count());
}
[Test]
public void GetValueFromResponse_Returns_Null_Not_Found_Property()
{
var att = new FilterAllowedOutgoingContentAttribute(typeof(IEnumerable<ContentItemBasic>), "DontFind");
var val = new List<ContentItemBasic>() { new ContentItemBasic() };
var container = new MyTestClass() { MyList = val };
var result = att.GetValueFromResponse(
new ObjectContent(typeof(MyTestClass),
container,
new JsonMediaTypeFormatter(),
new MediaTypeHeaderValue("html/text")));
Assert.AreEqual(null, result);
}
[Test]
public void Filter_On_Start_Node()
{
var att = new FilterAllowedOutgoingContentAttribute(typeof(IEnumerable<ContentItemBasic>));
var list = new List<dynamic>();
var path = "";
for (var i = 0; i < 10; i++)
{
if (i > 0 && path.EndsWith(",") == false)
{
path += ",";
}
path += i.ToInvariantString();
list.Add(new ContentItemBasic { Id = i, Name = "Test" + i, ParentId = i, Path = path });
}
var userMock = new Mock<IUser>();
userMock.Setup(u => u.Id).Returns(9);
userMock.Setup(u => u.StartContentId).Returns(5);
var user = userMock.Object;
att.FilterBasedOnStartNode(list, user);
Assert.AreEqual(5, list.Count);
}
[Test]
public void Filter_On_Permissions()
{
var att = new FilterAllowedOutgoingContentAttribute(typeof(IEnumerable<ContentItemBasic>));
var list = new List<dynamic>();
for (var i = 0; i < 10; i++)
{
list.Add(new ContentItemBasic{Id = i, Name = "Test" + i, ParentId = -1});
}
var ids = list.Select(x => (int)x.Id).ToArray();
var userMock = new Mock<IUser>();
userMock.Setup(u => u.Id).Returns(9);
userMock.Setup(u => u.StartContentId).Returns(-1);
var user = userMock.Object;
var userServiceMock = new Mock<IUserService>();
//we're only assigning 3 nodes browse permissions so that is what we expect as a result
var permissions = new List<EntityPermission>
{
new EntityPermission(9, 1, new string[]{ "F" }),
new EntityPermission(9, 2, new string[]{ "F" }),
new EntityPermission(9, 3, new string[]{ "F" }),
new EntityPermission(9, 4, new string[]{ "A" })
};
userServiceMock.Setup(x => x.GetPermissions(user, ids)).Returns(permissions);
var userService = userServiceMock.Object;
att.FilterBasedOnPermissions(list, user, userService);
Assert.AreEqual(3, list.Count);
Assert.AreEqual(1, list.ElementAt(0).Id);
Assert.AreEqual(2, list.ElementAt(1).Id);
Assert.AreEqual(3, list.ElementAt(2).Id);
}
private class MyTestClass
{
public IEnumerable<ContentItemBasic> MyList { get; set; }
}
}
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Net.Http.Formatting;
using System.Net.Http.Headers;
using Moq;
using NUnit.Framework;
using Umbraco.Core;
using Umbraco.Core.Models.Membership;
using Umbraco.Core.Services;
using Umbraco.Web.Models.ContentEditing;
using Umbraco.Web.WebApi.Filters;
namespace Umbraco.Tests.Web.Controllers.WebApiEditors
{
[TestFixture]
public class FilterAllowedOutgoingContentAttributeTests
{
[Test]
public void GetValueFromResponse_Already_EnumerableContent()
{
var att = new FilterAllowedOutgoingContentAttribute(typeof(IEnumerable<ContentItemBasic>));
var val = new List<ContentItemBasic>() {new ContentItemBasic()};
var result = att.GetValueFromResponse(
new ObjectContent(typeof (IEnumerable<ContentItemBasic>),
val,
new JsonMediaTypeFormatter(),
new MediaTypeHeaderValue("html/text")));
Assert.AreEqual(val, result);
Assert.AreEqual(1, ((IEnumerable<ContentItemBasic>)result).Count());
}
[Test]
public void GetValueFromResponse_From_Property()
{
var att = new FilterAllowedOutgoingContentAttribute(typeof(IEnumerable<ContentItemBasic>), "MyList");
var val = new List<ContentItemBasic>() { new ContentItemBasic() };
var container = new MyTestClass() {MyList = val};
var result = att.GetValueFromResponse(
new ObjectContent(typeof(MyTestClass),
container,
new JsonMediaTypeFormatter(),
new MediaTypeHeaderValue("html/text")));
Assert.AreEqual(val, result);
Assert.AreEqual(1, ((IEnumerable<ContentItemBasic>)result).Count());
}
[Test]
public void GetValueFromResponse_Returns_Null_Not_Found_Property()
{
var att = new FilterAllowedOutgoingContentAttribute(typeof(IEnumerable<ContentItemBasic>), "DontFind");
var val = new List<ContentItemBasic>() { new ContentItemBasic() };
var container = new MyTestClass() { MyList = val };
var result = att.GetValueFromResponse(
new ObjectContent(typeof(MyTestClass),
container,
new JsonMediaTypeFormatter(),
new MediaTypeHeaderValue("html/text")));
Assert.AreEqual(null, result);
}
[Test]
public void Filter_On_Start_Node()
{
var att = new FilterAllowedOutgoingContentAttribute(typeof(IEnumerable<ContentItemBasic>));
var list = new List<dynamic>();
var path = "";
for (var i = 0; i < 10; i++)
{
if (i > 0 && path.EndsWith(",") == false)
{
path += ",";
}
path += i.ToInvariantString();
list.Add(new ContentItemBasic { Id = i, Name = "Test" + i, ParentId = i, Path = path });
}
var userMock = new Mock<IUser>();
userMock.Setup(u => u.Id).Returns(9);
userMock.Setup(u => u.StartContentId).Returns(5);
var user = userMock.Object;
att.FilterBasedOnStartNode(list, user);
Assert.AreEqual(5, list.Count);
}
[Test]
public void Filter_On_Permissions()
{
var att = new FilterAllowedOutgoingContentAttribute(typeof(IEnumerable<ContentItemBasic>));
var list = new List<dynamic>();
for (var i = 0; i < 10; i++)
{
list.Add(new ContentItemBasic{Id = i, Name = "Test" + i, ParentId = -1});
}
var ids = list.Select(x => (int)x.Id).ToArray();
var userMock = new Mock<IUser>();
userMock.Setup(u => u.Id).Returns(9);
userMock.Setup(u => u.StartContentId).Returns(-1);
var user = userMock.Object;
var userServiceMock = new Mock<IUserService>();
//we're only assigning 3 nodes browse permissions so that is what we expect as a result
var permissions = new List<EntityPermission>
{
new EntityPermission(9, 1, new string[]{ "F" }),
new EntityPermission(9, 2, new string[]{ "F" }),
new EntityPermission(9, 3, new string[]{ "F" }),
new EntityPermission(9, 4, new string[]{ "A" })
};
userServiceMock.Setup(x => x.GetPermissions(user, ids)).Returns(permissions);
var userService = userServiceMock.Object;
att.FilterBasedOnPermissions(list, user, userService);
Assert.AreEqual(3, list.Count);
Assert.AreEqual(1, list.ElementAt(0).Id);
Assert.AreEqual(2, list.ElementAt(1).Id);
Assert.AreEqual(3, list.ElementAt(2).Id);
}
private class MyTestClass
{
public IEnumerable<ContentItemBasic> MyList { get; set; }
}
}
}
@@ -1,142 +1,142 @@
using System.Collections.Generic;
using System.Web.Http;
using Moq;
using NUnit.Framework;
using Umbraco.Core.Models;
using Umbraco.Core.Models.Membership;
using Umbraco.Core.Services;
using Umbraco.Web.Editors;
namespace Umbraco.Tests.Controllers.WebApiEditors
{
[TestFixture]
public class MediaControllerUnitTests
{
[Test]
public void Access_Allowed_By_Path()
{
//arrange
var userMock = new Mock<IUser>();
userMock.Setup(u => u.Id).Returns(9);
userMock.Setup(u => u.StartMediaId).Returns(-1);
var user = userMock.Object;
var mediaMock = new Mock<IMedia>();
mediaMock.Setup(m => m.Path).Returns("-1,1234,5678");
var media = mediaMock.Object;
var mediaServiceMock = new Mock<IMediaService>();
mediaServiceMock.Setup(x => x.GetById(1234)).Returns(media);
var mediaService = mediaServiceMock.Object;
//act
var result = MediaController.CheckPermissions(new Dictionary<string, object>(), user, mediaService, 1234);
//assert
Assert.IsTrue(result);
}
[Test]
public void Throws_Exception_When_No_Media_Found()
{
//arrange
var userMock = new Mock<IUser>();
userMock.Setup(u => u.Id).Returns(9);
userMock.Setup(u => u.StartMediaId).Returns(-1);
var user = userMock.Object;
var mediaMock = new Mock<IMedia>();
mediaMock.Setup(m => m.Path).Returns("-1,1234,5678");
var media = mediaMock.Object;
var mediaServiceMock = new Mock<IMediaService>();
mediaServiceMock.Setup(x => x.GetById(0)).Returns(media);
var mediaService = mediaServiceMock.Object;
//act/assert
Assert.Throws<HttpResponseException>(() => MediaController.CheckPermissions(new Dictionary<string, object>(), user, mediaService, 1234));
}
[Test]
public void No_Access_By_Path()
{
//arrange
var userMock = new Mock<IUser>();
userMock.Setup(u => u.Id).Returns(9);
userMock.Setup(u => u.StartMediaId).Returns(9876);
var user = userMock.Object;
var mediaMock = new Mock<IMedia>();
mediaMock.Setup(m => m.Path).Returns("-1,1234,5678");
var media = mediaMock.Object;
var mediaServiceMock = new Mock<IMediaService>();
mediaServiceMock.Setup(x => x.GetById(1234)).Returns(media);
var mediaService = mediaServiceMock.Object;
//act
var result = MediaController.CheckPermissions(new Dictionary<string, object>(), user, mediaService, 1234);
//assert
Assert.IsFalse(result);
}
[Test]
public void Access_To_Root_By_Path()
{
//arrange
var userMock = new Mock<IUser>();
userMock.Setup(u => u.Id).Returns(0);
userMock.Setup(u => u.StartMediaId).Returns(-1);
var user = userMock.Object;
//act
var result = MediaController.CheckPermissions(new Dictionary<string, object>(), user, null, -1);
//assert
Assert.IsTrue(result);
}
[Test]
public void No_Access_To_Root_By_Path()
{
//arrange
var userMock = new Mock<IUser>();
userMock.Setup(u => u.Id).Returns(0);
userMock.Setup(u => u.StartMediaId).Returns(1234);
var user = userMock.Object;
//act
var result = MediaController.CheckPermissions(new Dictionary<string, object>(), user, null, -1);
//assert
Assert.IsFalse(result);
}
[Test]
public void Access_To_Recycle_Bin_By_Path()
{
//arrange
var userMock = new Mock<IUser>();
userMock.Setup(u => u.Id).Returns(0);
userMock.Setup(u => u.StartMediaId).Returns(-1);
var user = userMock.Object;
//act
var result = MediaController.CheckPermissions(new Dictionary<string, object>(), user, null, -21);
//assert
Assert.IsTrue(result);
}
[Test]
public void No_Access_To_Recycle_Bin_By_Path()
{
//arrange
var userMock = new Mock<IUser>();
userMock.Setup(u => u.Id).Returns(0);
userMock.Setup(u => u.StartMediaId).Returns(1234);
var user = userMock.Object;
//act
var result = MediaController.CheckPermissions(new Dictionary<string, object>(), user, null, -21);
//assert
Assert.IsFalse(result);
}
}
using System.Collections.Generic;
using System.Web.Http;
using Moq;
using NUnit.Framework;
using Umbraco.Core.Models;
using Umbraco.Core.Models.Membership;
using Umbraco.Core.Services;
using Umbraco.Web.Editors;
namespace Umbraco.Tests.Web.Controllers.WebApiEditors
{
[TestFixture]
public class MediaControllerUnitTests
{
[Test]
public void Access_Allowed_By_Path()
{
//arrange
var userMock = new Mock<IUser>();
userMock.Setup(u => u.Id).Returns(9);
userMock.Setup(u => u.StartMediaId).Returns(-1);
var user = userMock.Object;
var mediaMock = new Mock<IMedia>();
mediaMock.Setup(m => m.Path).Returns("-1,1234,5678");
var media = mediaMock.Object;
var mediaServiceMock = new Mock<IMediaService>();
mediaServiceMock.Setup(x => x.GetById(1234)).Returns(media);
var mediaService = mediaServiceMock.Object;
//act
var result = MediaController.CheckPermissions(new Dictionary<string, object>(), user, mediaService, 1234);
//assert
Assert.IsTrue(result);
}
[Test]
public void Throws_Exception_When_No_Media_Found()
{
//arrange
var userMock = new Mock<IUser>();
userMock.Setup(u => u.Id).Returns(9);
userMock.Setup(u => u.StartMediaId).Returns(-1);
var user = userMock.Object;
var mediaMock = new Mock<IMedia>();
mediaMock.Setup(m => m.Path).Returns("-1,1234,5678");
var media = mediaMock.Object;
var mediaServiceMock = new Mock<IMediaService>();
mediaServiceMock.Setup(x => x.GetById(0)).Returns(media);
var mediaService = mediaServiceMock.Object;
//act/assert
Assert.Throws<HttpResponseException>(() => MediaController.CheckPermissions(new Dictionary<string, object>(), user, mediaService, 1234));
}
[Test]
public void No_Access_By_Path()
{
//arrange
var userMock = new Mock<IUser>();
userMock.Setup(u => u.Id).Returns(9);
userMock.Setup(u => u.StartMediaId).Returns(9876);
var user = userMock.Object;
var mediaMock = new Mock<IMedia>();
mediaMock.Setup(m => m.Path).Returns("-1,1234,5678");
var media = mediaMock.Object;
var mediaServiceMock = new Mock<IMediaService>();
mediaServiceMock.Setup(x => x.GetById(1234)).Returns(media);
var mediaService = mediaServiceMock.Object;
//act
var result = MediaController.CheckPermissions(new Dictionary<string, object>(), user, mediaService, 1234);
//assert
Assert.IsFalse(result);
}
[Test]
public void Access_To_Root_By_Path()
{
//arrange
var userMock = new Mock<IUser>();
userMock.Setup(u => u.Id).Returns(0);
userMock.Setup(u => u.StartMediaId).Returns(-1);
var user = userMock.Object;
//act
var result = MediaController.CheckPermissions(new Dictionary<string, object>(), user, null, -1);
//assert
Assert.IsTrue(result);
}
[Test]
public void No_Access_To_Root_By_Path()
{
//arrange
var userMock = new Mock<IUser>();
userMock.Setup(u => u.Id).Returns(0);
userMock.Setup(u => u.StartMediaId).Returns(1234);
var user = userMock.Object;
//act
var result = MediaController.CheckPermissions(new Dictionary<string, object>(), user, null, -1);
//assert
Assert.IsFalse(result);
}
[Test]
public void Access_To_Recycle_Bin_By_Path()
{
//arrange
var userMock = new Mock<IUser>();
userMock.Setup(u => u.Id).Returns(0);
userMock.Setup(u => u.StartMediaId).Returns(-1);
var user = userMock.Object;
//act
var result = MediaController.CheckPermissions(new Dictionary<string, object>(), user, null, -21);
//assert
Assert.IsTrue(result);
}
[Test]
public void No_Access_To_Recycle_Bin_By_Path()
{
//arrange
var userMock = new Mock<IUser>();
userMock.Setup(u => u.Id).Returns(0);
userMock.Setup(u => u.StartMediaId).Returns(1234);
var user = userMock.Object;
//act
var result = MediaController.CheckPermissions(new Dictionary<string, object>(), user, null, -21);
//assert
Assert.IsFalse(result);
}
}
}
@@ -2,7 +2,7 @@ using System.Web.Mvc;
using NUnit.Framework;
using Umbraco.Web;
namespace Umbraco.Tests.Mvc
namespace Umbraco.Tests.Web.Mvc
{
[TestFixture]
public class HtmlHelperExtensionMethodsTests
@@ -1,86 +1,86 @@
using System.Web.Mvc;
using System.Web.Routing;
using NUnit.Framework;
using Umbraco.Tests.TestHelpers;
using Umbraco.Web.Mvc;
namespace Umbraco.Tests.Mvc
{
[TestFixture]
public class MergeParentContextViewDataAttributeTests
{
[Test]
public void Ensure_All_Ancestor_ViewData_Is_Merged()
{
var http = new FakeHttpContextFactory("http://localhost");
//setup an heirarchy
var rootViewCtx = new ViewContext {Controller = new MyController(), RequestContext = http.RequestContext, ViewData = new ViewDataDictionary()};
var parentViewCtx = new ViewContext { Controller = new MyController(), RequestContext = http.RequestContext, RouteData = new RouteData(), ViewData = new ViewDataDictionary() };
parentViewCtx.RouteData.DataTokens.Add("ParentActionViewContext", rootViewCtx);
var controllerCtx = new ControllerContext(http.RequestContext, new MyController()) {RouteData = new RouteData()};
controllerCtx.RouteData.DataTokens.Add("ParentActionViewContext", parentViewCtx);
//set up the view data
controllerCtx.Controller.ViewData["Test1"] = "Test1";
controllerCtx.Controller.ViewData["Test2"] = "Test2";
controllerCtx.Controller.ViewData["Test3"] = "Test3";
parentViewCtx.ViewData["Test4"] = "Test4";
parentViewCtx.ViewData["Test5"] = "Test5";
parentViewCtx.ViewData["Test6"] = "Test6";
rootViewCtx.ViewData["Test7"] = "Test7";
rootViewCtx.ViewData["Test8"] = "Test8";
rootViewCtx.ViewData["Test9"] = "Test9";
var filter = new ResultExecutingContext(controllerCtx, new ContentResult()) {RouteData = controllerCtx.RouteData};
var att = new MergeParentContextViewDataAttribute();
Assert.IsTrue(filter.IsChildAction);
att.OnResultExecuting(filter);
Assert.AreEqual(9, controllerCtx.Controller.ViewData.Count);
}
[Test]
public void Ensure_All_Ancestor_ViewData_Is_Merged_Without_Data_Loss()
{
var http = new FakeHttpContextFactory("http://localhost");
//setup an heirarchy
var rootViewCtx = new ViewContext { Controller = new MyController(), RequestContext = http.RequestContext, ViewData = new ViewDataDictionary() };
var parentViewCtx = new ViewContext { Controller = new MyController(), RequestContext = http.RequestContext, RouteData = new RouteData(), ViewData = new ViewDataDictionary() };
parentViewCtx.RouteData.DataTokens.Add("ParentActionViewContext", rootViewCtx);
var controllerCtx = new ControllerContext(http.RequestContext, new MyController()) { RouteData = new RouteData() };
controllerCtx.RouteData.DataTokens.Add("ParentActionViewContext", parentViewCtx);
//set up the view data with overlapping keys
controllerCtx.Controller.ViewData["Test1"] = "Test1";
controllerCtx.Controller.ViewData["Test2"] = "Test2";
controllerCtx.Controller.ViewData["Test3"] = "Test3";
parentViewCtx.ViewData["Test2"] = "Test4";
parentViewCtx.ViewData["Test3"] = "Test5";
parentViewCtx.ViewData["Test4"] = "Test6";
rootViewCtx.ViewData["Test3"] = "Test7";
rootViewCtx.ViewData["Test4"] = "Test8";
rootViewCtx.ViewData["Test5"] = "Test9";
var filter = new ResultExecutingContext(controllerCtx, new ContentResult()) { RouteData = controllerCtx.RouteData };
var att = new MergeParentContextViewDataAttribute();
Assert.IsTrue(filter.IsChildAction);
att.OnResultExecuting(filter);
Assert.AreEqual(5, controllerCtx.Controller.ViewData.Count);
Assert.AreEqual("Test1", controllerCtx.Controller.ViewData["Test1"]);
Assert.AreEqual("Test2", controllerCtx.Controller.ViewData["Test2"]);
Assert.AreEqual("Test3", controllerCtx.Controller.ViewData["Test3"]);
Assert.AreEqual("Test6", controllerCtx.Controller.ViewData["Test4"]);
Assert.AreEqual("Test9", controllerCtx.Controller.ViewData["Test5"]);
}
internal class MyController : Controller
{
}
}
using System.Web.Mvc;
using System.Web.Routing;
using NUnit.Framework;
using Umbraco.Tests.TestHelpers;
using Umbraco.Web.Mvc;
namespace Umbraco.Tests.Web.Mvc
{
[TestFixture]
public class MergeParentContextViewDataAttributeTests
{
[Test]
public void Ensure_All_Ancestor_ViewData_Is_Merged()
{
var http = new FakeHttpContextFactory("http://localhost");
//setup an heirarchy
var rootViewCtx = new ViewContext {Controller = new MyController(), RequestContext = http.RequestContext, ViewData = new ViewDataDictionary()};
var parentViewCtx = new ViewContext { Controller = new MyController(), RequestContext = http.RequestContext, RouteData = new RouteData(), ViewData = new ViewDataDictionary() };
parentViewCtx.RouteData.DataTokens.Add("ParentActionViewContext", rootViewCtx);
var controllerCtx = new ControllerContext(http.RequestContext, new MyController()) {RouteData = new RouteData()};
controllerCtx.RouteData.DataTokens.Add("ParentActionViewContext", parentViewCtx);
//set up the view data
controllerCtx.Controller.ViewData["Test1"] = "Test1";
controllerCtx.Controller.ViewData["Test2"] = "Test2";
controllerCtx.Controller.ViewData["Test3"] = "Test3";
parentViewCtx.ViewData["Test4"] = "Test4";
parentViewCtx.ViewData["Test5"] = "Test5";
parentViewCtx.ViewData["Test6"] = "Test6";
rootViewCtx.ViewData["Test7"] = "Test7";
rootViewCtx.ViewData["Test8"] = "Test8";
rootViewCtx.ViewData["Test9"] = "Test9";
var filter = new ResultExecutingContext(controllerCtx, new ContentResult()) {RouteData = controllerCtx.RouteData};
var att = new MergeParentContextViewDataAttribute();
Assert.IsTrue(filter.IsChildAction);
att.OnResultExecuting(filter);
Assert.AreEqual(9, controllerCtx.Controller.ViewData.Count);
}
[Test]
public void Ensure_All_Ancestor_ViewData_Is_Merged_Without_Data_Loss()
{
var http = new FakeHttpContextFactory("http://localhost");
//setup an heirarchy
var rootViewCtx = new ViewContext { Controller = new MyController(), RequestContext = http.RequestContext, ViewData = new ViewDataDictionary() };
var parentViewCtx = new ViewContext { Controller = new MyController(), RequestContext = http.RequestContext, RouteData = new RouteData(), ViewData = new ViewDataDictionary() };
parentViewCtx.RouteData.DataTokens.Add("ParentActionViewContext", rootViewCtx);
var controllerCtx = new ControllerContext(http.RequestContext, new MyController()) { RouteData = new RouteData() };
controllerCtx.RouteData.DataTokens.Add("ParentActionViewContext", parentViewCtx);
//set up the view data with overlapping keys
controllerCtx.Controller.ViewData["Test1"] = "Test1";
controllerCtx.Controller.ViewData["Test2"] = "Test2";
controllerCtx.Controller.ViewData["Test3"] = "Test3";
parentViewCtx.ViewData["Test2"] = "Test4";
parentViewCtx.ViewData["Test3"] = "Test5";
parentViewCtx.ViewData["Test4"] = "Test6";
rootViewCtx.ViewData["Test3"] = "Test7";
rootViewCtx.ViewData["Test4"] = "Test8";
rootViewCtx.ViewData["Test5"] = "Test9";
var filter = new ResultExecutingContext(controllerCtx, new ContentResult()) { RouteData = controllerCtx.RouteData };
var att = new MergeParentContextViewDataAttribute();
Assert.IsTrue(filter.IsChildAction);
att.OnResultExecuting(filter);
Assert.AreEqual(5, controllerCtx.Controller.ViewData.Count);
Assert.AreEqual("Test1", controllerCtx.Controller.ViewData["Test1"]);
Assert.AreEqual("Test2", controllerCtx.Controller.ViewData["Test2"]);
Assert.AreEqual("Test3", controllerCtx.Controller.ViewData["Test3"]);
Assert.AreEqual("Test6", controllerCtx.Controller.ViewData["Test4"]);
Assert.AreEqual("Test9", controllerCtx.Controller.ViewData["Test5"]);
}
internal class MyController : Controller
{
}
}
}
@@ -17,7 +17,7 @@ using Umbraco.Web.Mvc;
using Umbraco.Web.Routing;
using Umbraco.Web.Security;
namespace Umbraco.Tests.Mvc
namespace Umbraco.Tests.Web.Mvc
{
[TestFixture]
public class RenderIndexActionSelectorAttributeTests
@@ -0,0 +1,157 @@
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(IRenderModel));
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(MyOtherContent));
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 MyOtherContent
{
}
public class MyContent : PublishedContentWrapped
{
public MyContent(IPublishedContent content) : base(content)
{
}
}
}
}
@@ -1,5 +1,4 @@
using System;
using System.CodeDom;
using System.Linq;
using System.Web;
using System.Web.Mvc;
@@ -12,7 +11,6 @@ using Umbraco.Core.Configuration.UmbracoSettings;
using Umbraco.Core.Dictionary;
using Umbraco.Core.Logging;
using Umbraco.Core.Models;
using Umbraco.Core.ObjectResolution;
using Umbraco.Core.Persistence;
using Umbraco.Core.Persistence.SqlSyntax;
using Umbraco.Core.Profiling;
@@ -20,11 +18,10 @@ using Umbraco.Core.Services;
using Umbraco.Tests.TestHelpers;
using Umbraco.Web;
using Umbraco.Web.Mvc;
using Umbraco.Web.PublishedCache;
using Umbraco.Web.Routing;
using Umbraco.Web.Security;
namespace Umbraco.Tests.Mvc
namespace Umbraco.Tests.Web.Mvc
{
[TestFixture]
public class SurfaceControllerTests
@@ -165,7 +162,7 @@ namespace Umbraco.Tests.Mvc
};
var routeData = new RouteData();
routeData.DataTokens.Add("umbraco-route-def", routeDefinition);
routeData.DataTokens.Add(Umbraco.Core.Constants.Web.UmbracoRouteDefinitionDataToken, routeDefinition);
var ctrl = new TestSurfaceController(umbCtx, new UmbracoHelper());
ctrl.ControllerContext = new ControllerContext(contextBase, routeData, ctrl);
@@ -1,27 +1,22 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Web.Mvc;
using System.Web.Routing;
using System.Xml;
using Moq;
using NUnit.Framework;
using umbraco.BusinessLogic;
using Umbraco.Core;
using Umbraco.Core.Configuration.UmbracoSettings;
using Umbraco.Core.Events;
using Umbraco.Core.Logging;
using Umbraco.Core.Models;
using Umbraco.Core.Models.PublishedContent;
using Umbraco.Core.Persistence;
using Umbraco.Core.Persistence.SqlSyntax;
using Umbraco.Core.Persistence.UnitOfWork;
using Umbraco.Core.Profiling;
using Umbraco.Core.Services;
using Umbraco.Web.Security;
using umbraco.BusinessLogic;
using Umbraco.Core;
using Umbraco.Core.Events;
using Umbraco.Core.Models;
using Umbraco.Core.Models.PublishedContent;
using Umbraco.Tests.PublishedContent;
using Umbraco.Tests.TestHelpers;
using Umbraco.Tests.TestHelpers.Stubs;
using Umbraco.Web;
@@ -30,8 +25,9 @@ using Umbraco.Web.Mvc;
using Umbraco.Web.PublishedCache;
using Umbraco.Web.PublishedCache.XmlPublishedCache;
using Umbraco.Web.Routing;
using Umbraco.Web.Security;
namespace Umbraco.Tests.Mvc
namespace Umbraco.Tests.Web.Mvc
{
[TestFixture]
public class UmbracoViewPageTests
@@ -445,7 +441,7 @@ namespace Umbraco.Tests.Mvc
var context = new ViewContext();
context.RouteData = new RouteData();
context.RouteData.DataTokens.Add("umbraco-context", umbracoContext);
context.RouteData.DataTokens.Add(Umbraco.Core.Constants.Web.UmbracoContextDataToken, umbracoContext);
return context;
}
@@ -1,42 +1,40 @@
using System.Collections.Generic;
using System.Text;
using System.Web.Mvc;
using NUnit.Framework;
using Umbraco.Web.Mvc;
namespace Umbraco.Tests.Mvc
{
[TestFixture]
public class ViewDataDictionaryExtensionTests
{
[Test]
public void Merge_View_Data()
{
var source = new ViewDataDictionary();
var dest = new ViewDataDictionary();
source.Add("Test1", "Test1");
dest.Add("Test2", "Test2");
dest.MergeViewDataFrom(source);
Assert.AreEqual(2, dest.Count);
}
[Test]
public void Merge_View_Data_Retains_Destination_Values()
{
var source = new ViewDataDictionary();
var dest = new ViewDataDictionary();
source.Add("Test1", "Test1");
dest.Add("Test1", "MyValue");
dest.Add("Test2", "Test2");
dest.MergeViewDataFrom(source);
Assert.AreEqual(2, dest.Count);
Assert.AreEqual("MyValue", dest["Test1"]);
Assert.AreEqual("Test2", dest["Test2"]);
}
}
}
using System.Web.Mvc;
using NUnit.Framework;
using Umbraco.Web.Mvc;
namespace Umbraco.Tests.Web.Mvc
{
[TestFixture]
public class ViewDataDictionaryExtensionTests
{
[Test]
public void Merge_View_Data()
{
var source = new ViewDataDictionary();
var dest = new ViewDataDictionary();
source.Add("Test1", "Test1");
dest.Add("Test2", "Test2");
dest.MergeViewDataFrom(source);
Assert.AreEqual(2, dest.Count);
}
[Test]
public void Merge_View_Data_Retains_Destination_Values()
{
var source = new ViewDataDictionary();
var dest = new ViewDataDictionary();
source.Add("Test1", "Test1");
dest.Add("Test1", "MyValue");
dest.Add("Test2", "Test2");
dest.MergeViewDataFrom(source);
Assert.AreEqual(2, dest.Count);
Assert.AreEqual("MyValue", dest["Test1"]);
Assert.AreEqual("Test2", dest["Test2"]);
}
}
}
@@ -0,0 +1,170 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;
using Moq;
using NUnit.Framework;
using Umbraco.Core;
using Umbraco.Core.Configuration.UmbracoSettings;
using Umbraco.Core.Logging;
using Umbraco.Core.Profiling;
using Umbraco.Web;
using Umbraco.Web.Mvc;
using Umbraco.Web.Routing;
using Umbraco.Web.Security;
namespace Umbraco.Tests.Web
{
[TestFixture]
public class WebExtensionMethodTests
{
[Test]
public void UmbracoContextExtensions_GetUmbracoContext()
{
var appCtx = new ApplicationContext(
CacheHelper.CreateDisabledCacheHelper(),
new ProfilingLogger(Mock.Of<ILogger>(), Mock.Of<IProfiler>()));
var umbCtx = UmbracoContext.CreateContext(
Mock.Of<HttpContextBase>(),
appCtx,
new WebSecurity(Mock.Of<HttpContextBase>(), appCtx),
Mock.Of<IUmbracoSettingsSection>(),
new List<IUrlProvider>(),
false);
var items = new Dictionary<object, object>()
{
{UmbracoContext.HttpContextItemName, umbCtx}
};
var http = new Mock<HttpContextBase>();
http.Setup(x => x.Items).Returns(items);
var result = http.Object.GetUmbracoContext();
Assert.IsNotNull(result);
Assert.AreSame(umbCtx, result);
}
[Test]
public void RouteDataExtensions_GetUmbracoContext()
{
var appCtx = new ApplicationContext(
CacheHelper.CreateDisabledCacheHelper(),
new ProfilingLogger(Mock.Of<ILogger>(), Mock.Of<IProfiler>()));
var umbCtx = UmbracoContext.CreateContext(
Mock.Of<HttpContextBase>(),
appCtx,
new WebSecurity(Mock.Of<HttpContextBase>(), appCtx),
Mock.Of<IUmbracoSettingsSection>(),
new List<IUrlProvider>(),
false);
var r1 = new RouteData();
r1.DataTokens.Add(Core.Constants.Web.UmbracoContextDataToken, umbCtx);
var result = r1.GetUmbracoContext();
Assert.IsNotNull(result);
Assert.AreSame(umbCtx, result);
}
[Test]
public void ControllerContextExtensions_GetUmbracoContext_From_RouteValues()
{
var appCtx = new ApplicationContext(
CacheHelper.CreateDisabledCacheHelper(),
new ProfilingLogger(Mock.Of<ILogger>(), Mock.Of<IProfiler>()));
var umbCtx = UmbracoContext.CreateContext(
Mock.Of<HttpContextBase>(),
appCtx,
new WebSecurity(Mock.Of<HttpContextBase>(), appCtx),
Mock.Of<IUmbracoSettingsSection>(),
new List<IUrlProvider>(),
false);
var r1 = new RouteData();
r1.DataTokens.Add(Core.Constants.Web.UmbracoContextDataToken, umbCtx);
var ctx1 = CreateViewContext(new ControllerContext(Mock.Of<HttpContextBase>(), r1, new MyController()));
var r2 = new RouteData();
r2.DataTokens.Add("ParentActionViewContext", ctx1);
var ctx2 = CreateViewContext(new ControllerContext(Mock.Of<HttpContextBase>(), r2, new MyController()));
var r3 = new RouteData();
r3.DataTokens.Add("ParentActionViewContext", ctx2);
var ctx3 = CreateViewContext(new ControllerContext(Mock.Of<HttpContextBase>(), r3, new MyController()));
var result = ctx3.GetUmbracoContext();
Assert.IsNotNull(result);
Assert.AreSame(umbCtx, result);
}
[Test]
public void ControllerContextExtensions_GetUmbracoContext_From_HttpContext()
{
var appCtx = new ApplicationContext(
CacheHelper.CreateDisabledCacheHelper(),
new ProfilingLogger(Mock.Of<ILogger>(), Mock.Of<IProfiler>()));
var umbCtx = UmbracoContext.CreateContext(
Mock.Of<HttpContextBase>(),
appCtx,
new WebSecurity(Mock.Of<HttpContextBase>(), appCtx),
Mock.Of<IUmbracoSettingsSection>(),
new List<IUrlProvider>(),
false);
var items = new Dictionary<object, object>()
{
{UmbracoContext.HttpContextItemName, umbCtx}
};
var http = new Mock<HttpContextBase>();
http.Setup(x => x.Items).Returns(items);
var r1 = new RouteData();
var ctx1 = CreateViewContext(new ControllerContext(http.Object, r1, new MyController()));
var r2 = new RouteData();
r2.DataTokens.Add("ParentActionViewContext", ctx1);
var ctx2 = CreateViewContext(new ControllerContext(http.Object, r2, new MyController()));
var r3 = new RouteData();
r3.DataTokens.Add("ParentActionViewContext", ctx2);
var ctx3 = CreateViewContext(new ControllerContext(http.Object, r3, new MyController()));
var result = ctx3.GetUmbracoContext();
Assert.IsNotNull(result);
Assert.AreSame(umbCtx, result);
}
[Test]
public void ControllerContextExtensions_GetDataTokenInViewContextHierarchy()
{
var r1 = new RouteData();
r1.DataTokens.Add("hello", "world");
var ctx1 = CreateViewContext(new ControllerContext(Mock.Of<HttpContextBase>(), r1, new MyController()));
var r2 = new RouteData();
r2.DataTokens.Add("ParentActionViewContext", ctx1);
var ctx2 = CreateViewContext(new ControllerContext(Mock.Of<HttpContextBase>(), r2, new MyController()));
var r3 = new RouteData();
r3.DataTokens.Add("ParentActionViewContext", ctx2);
var ctx3 = CreateViewContext(new ControllerContext(Mock.Of<HttpContextBase>(), r3, new MyController()));
var result = ctx3.GetDataTokenInViewContextHierarchy("hello");
Assert.IsNotNull(result as string);
Assert.AreEqual((string)result, "world");
}
private ViewContext CreateViewContext(ControllerContext ctx)
{
return new ViewContext(ctx, Mock.Of<IView>(),
new ViewDataDictionary(), new TempDataDictionary(), new StringWriter());
}
private class MyController : Controller
{
}
}
}
+3 -1
View File
@@ -13,13 +13,15 @@
<package id="Microsoft.AspNet.WebApi.SelfHost" version="4.0.30506.0" targetFramework="net45" />
<package id="Microsoft.AspNet.WebApi.WebHost" version="5.2.3" targetFramework="net45" />
<package id="Microsoft.AspNet.WebPages" version="3.2.3" targetFramework="net45" />
<package id="Microsoft.Owin" version="3.0.1" targetFramework="net45" />
<package id="Microsoft.Web.Infrastructure" version="1.0.0.0" targetFramework="net45" />
<package id="MiniProfiler" version="2.1.0" targetFramework="net45" />
<package id="Moq" version="4.1.1309.0919" targetFramework="net45" />
<package id="Newtonsoft.Json" version="6.0.8" targetFramework="net45" />
<package id="NUnit" version="2.6.2" targetFramework="net45" />
<package id="Owin" version="1.0" targetFramework="net45" />
<package id="Selenium.WebDriver" version="2.32.0" targetFramework="net45" />
<package id="semver" version="1.1.2" targetFramework="net45" />
<package id="SharpZipLib" version="0.86.0" targetFramework="net45" />
<package id="SqlServerCE" version="4.0.0.0" targetFramework="net45" />
<package id="SqlServerCE" version="4.0.0.1" targetFramework="net45" />
</packages>
@@ -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:
@@ -361,6 +361,12 @@ Umbraco.Sys.registerNamespace("Umbraco.Application");
rootScope : function(){
return getRootScope();
},
reloadLocation: function() {
var injector = getRootInjector();
var $route = injector.get("$route");
$route.reload();
},
closeModalWindow: function(rVal) {
+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
@@ -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,10 +1,13 @@
(function() {
'use strict';
function EditorHeaderDirective(iconHelper) {
function EditorHeaderDirective(iconHelper, variationsHelper) {
function link(scope, el, attr, ctrl) {
scope.showVariationsQuickSwitch = false;
scope.variations = variationsHelper.getVariations();
scope.openIconPicker = function() {
scope.dialogModel = {
view: "iconpicker",
@@ -24,6 +27,10 @@
}
};
};
scope.toggleVariationsQuickSwitch = function() {
scope.showVariationsQuickSwitch = !scope.showVariationsQuickSwitch;
};
}
var directive = {
@@ -14,7 +14,8 @@ angular.module("umbraco.directives")
templateUrl: 'views/components/imaging/umb-image-gravity.html',
scope: {
src: '=',
center: "="
center: "=",
onImageLoaded: "="
},
link: function(scope, element, attrs) {
@@ -26,6 +27,8 @@ angular.module("umbraco.directives")
top: 0
};
scope.loaded = false;
//elements
var $viewport = element.find(".viewport");
var $image = element.find("img");
@@ -42,6 +45,19 @@ angular.module("umbraco.directives")
};
};
scope.setFocalPoint = function(event) {
scope.$emit("imageFocalPointStart");
var offsetX = event.offsetX - 10;
var offsetY = event.offsetY - 10;
calculateGravity(offsetX, offsetY);
lazyEndEvent();
};
var setDimensions = function(){
scope.dimensions.width = $image.width();
scope.dimensions.height = $image.height();
@@ -54,9 +70,9 @@ angular.module("umbraco.directives")
}
};
var calculateGravity = function(){
scope.dimensions.left = $overlay[0].offsetLeft;
scope.dimensions.top = $overlay[0].offsetTop;
var calculateGravity = function(offsetX, offsetY){
scope.dimensions.left = offsetX;
scope.dimensions.top = offsetY;
scope.center.left = (scope.dimensions.left+10) / scope.dimensions.width;
scope.center.top = (scope.dimensions.top+10) / scope.dimensions.height;
@@ -80,7 +96,9 @@ angular.module("umbraco.directives")
},
stop: function() {
scope.$apply(function(){
calculateGravity();
var offsetX = $overlay[0].offsetLeft;
var offsetY = $overlay[0].offsetTop;
calculateGravity(offsetX, offsetY);
});
lazyEndEvent();
@@ -91,8 +109,26 @@ angular.module("umbraco.directives")
$image.load(function(){
$timeout(function(){
setDimensions();
scope.loaded = true;
scope.onImageLoaded();
});
});
$(window).on('resize.umbImageGravity', function(){
scope.$apply(function(){
$timeout(function(){
setDimensions();
});
var offsetX = $overlay[0].offsetLeft;
var offsetY = $overlay[0].offsetTop;
calculateGravity(offsetX, offsetY);
});
});
scope.$on('$destroy', function() {
$(window).off('.umbImageGravity');
});
}
};
});
@@ -26,6 +26,7 @@ angular.module("umbraco.directives")
link: function(scope, element, attrs) {
//// INIT /////
var $image = element.find("img");
scope.loaded = false;
$image.load(function(){
$timeout(function(){
@@ -52,6 +53,7 @@ angular.module("umbraco.directives")
}
setPreviewStyle();
scope.loaded = true;
});
});
@@ -0,0 +1,76 @@
(function() {
'use strict';
function WebsiteSelector() {
function link(scope, el, attr, ctrl) {
scope.showWebsiteDropdown = false;
scope.selectedWebsite = {};
function activate() {
for(var i = 0; i < scope.websites.length; i++) {
var website = scope.websites[i];
if(website.selected) {
scope.selectedWebsite = website;
}
}
}
scope.toggleWebsiteDropDown = function() {
scope.showWebsiteDropdown = !scope.showWebsiteDropdown;
};
scope.closeWebsiteDropDown = function() {
scope.showWebsiteDropdown = false;
};
scope.createWebsite = function() {
if(scope.onCreateWebsite) {
scope.onCreateWebsite();
scope.closeWebsiteDropDown();
}
};
scope.clickWebsite = function(website) {
if(scope.onClickWebsite) {
scope.onClickWebsite(website);
setSelectedWebsite(website, scope.websites);
scope.closeWebsiteDropDown();
}
};
function setSelectedWebsite(selectedWebsite, websites) {
for(var i = 0; i < websites.length; i++) {
var website = websites[i];
website.selected = false;
}
selectedWebsite.selected = true;
scope.selectedWebsite = selectedWebsite;
}
scope.$watch('websites', function(newValue, oldValue){
activate();
}, true);
}
var directive = {
restrict: 'E',
replace: true,
templateUrl: 'views/components/umb-website-selector.html',
link: link,
scope: {
websites: "=",
onCreateWebsite: "=",
onClickWebsite: "="
}
};
return directive;
}
angular.module('umbraco.directives').directive('umbWebsiteSelector', WebsiteSelector);
})();
@@ -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 */
@@ -55,7 +55,7 @@ function contentEditingHelper(fileManager, $q, $location, $routeParams, notifica
var deferred = $q.defer();
if (!args.scope.busy && formHelper.submitForm({ scope: args.scope, statusMessage: args.statusMessage })) {
if (!args.scope.busy && formHelper.submitForm({ scope: args.scope, statusMessage: args.statusMessage, action: args.action })) {
args.scope.busy = true;
@@ -50,7 +50,7 @@ function formHelper(angularHelper, serverValidationManager, $timeout, notificati
}
//the first thing any form must do is broadcast the formSubmitting event
args.scope.$broadcast("formSubmitting", { scope: args.scope });
args.scope.$broadcast("formSubmitting", { scope: args.scope, action: args.action });
//then check if the form is valid
if (!args.skipValidation) {
@@ -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['type']
};
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;
}
@@ -1,288 +1,319 @@
(function() {
'use strict';
(function () {
'use strict';
function listViewHelper(localStorageService) {
function listViewHelper(localStorageService) {
var firstSelectedIndex = 0;
var localStorageKey = "umblistViewLayout";
var firstSelectedIndex = 0;
var localStorageKey = "umblistViewLayout";
function getLayout(nodeId, availableLayouts) {
function getLayout(nodeId, availableLayouts) {
var storedLayouts = [];
var storedLayouts = [];
if(localStorageService.get(localStorageKey)) {
storedLayouts = localStorageService.get(localStorageKey);
}
if (storedLayouts && storedLayouts.length > 0) {
for (var i = 0; storedLayouts.length > i; i++) {
var layout = storedLayouts[i];
if (layout.nodeId === nodeId) {
return setLayout(nodeId, layout, availableLayouts);
}
}
}
return getFirstAllowedLayout(availableLayouts);
}
function setLayout(nodeId, selectedLayout, availableLayouts) {
var activeLayout = {};
var layoutFound = false;
for (var i = 0; availableLayouts.length > i; i++) {
var layout = availableLayouts[i];
if (layout.path === selectedLayout.path) {
activeLayout = layout;
layout.active = true;
layoutFound = true;
} else {
layout.active = false;
}
}
if(!layoutFound) {
activeLayout = getFirstAllowedLayout(availableLayouts);
}
saveLayoutInLocalStorage(nodeId, activeLayout);
return activeLayout;
}
function saveLayoutInLocalStorage(nodeId, selectedLayout) {
var layoutFound = false;
var storedLayouts = [];
if(localStorageService.get(localStorageKey)) {
storedLayouts = localStorageService.get(localStorageKey);
}
if(storedLayouts.length > 0) {
for(var i = 0; storedLayouts.length > i; i++) {
var layout = storedLayouts[i];
if(layout.nodeId === nodeId) {
layout.path = selectedLayout.path;
layoutFound = true;
}
}
}
if(!layoutFound) {
var storageObject = {
"nodeId": nodeId,
"path": selectedLayout.path
};
storedLayouts.push(storageObject);
}
localStorageService.set(localStorageKey, storedLayouts);
}
function getFirstAllowedLayout(layouts) {
var firstAllowedLayout = {};
for (var i = 0; layouts.length > i; i++) {
var layout = layouts[i];
if (layout.selected === true) {
firstAllowedLayout = layout;
break;
if (localStorageService.get(localStorageKey)) {
storedLayouts = localStorageService.get(localStorageKey);
}
}
return firstAllowedLayout;
}
if (storedLayouts && storedLayouts.length > 0) {
for (var i = 0; storedLayouts.length > i; i++) {
var layout = storedLayouts[i];
if (layout.nodeId === nodeId) {
return setLayout(nodeId, layout, availableLayouts);
}
}
function selectHandler(selectedItem, selectedIndex, items, selection, $event) {
}
var start = 0;
var end = 0;
var item = null;
return getFirstAllowedLayout(availableLayouts);
if ($event.shiftKey === true) {
}
if(selectedIndex > firstSelectedIndex) {
function setLayout(nodeId, selectedLayout, availableLayouts) {
start = firstSelectedIndex;
end = selectedIndex;
var activeLayout = {};
var layoutFound = false;
for (; end >= start; start++) {
item = items[start];
selectItem(item, selection);
}
for (var i = 0; availableLayouts.length > i; i++) {
var layout = availableLayouts[i];
if (layout.path === selectedLayout.path) {
activeLayout = layout;
layout.active = true;
layoutFound = true;
} else {
layout.active = false;
}
}
if (!layoutFound) {
activeLayout = getFirstAllowedLayout(availableLayouts);
}
saveLayoutInLocalStorage(nodeId, activeLayout);
return activeLayout;
}
function saveLayoutInLocalStorage(nodeId, selectedLayout) {
var layoutFound = false;
var storedLayouts = [];
if (localStorageService.get(localStorageKey)) {
storedLayouts = localStorageService.get(localStorageKey);
}
if (storedLayouts.length > 0) {
for (var i = 0; storedLayouts.length > i; i++) {
var layout = storedLayouts[i];
if (layout.nodeId === nodeId) {
layout.path = selectedLayout.path;
layoutFound = true;
}
}
}
if (!layoutFound) {
var storageObject = {
"nodeId": nodeId,
"path": selectedLayout.path
};
storedLayouts.push(storageObject);
}
localStorageService.set(localStorageKey, storedLayouts);
}
function getFirstAllowedLayout(layouts) {
var firstAllowedLayout = {};
for (var i = 0; layouts.length > i; i++) {
var layout = layouts[i];
if (layout.selected === true) {
firstAllowedLayout = layout;
break;
}
}
return firstAllowedLayout;
}
function selectHandler(selectedItem, selectedIndex, items, selection, $event) {
var start = 0;
var end = 0;
var item = null;
if ($event.shiftKey === true) {
if (selectedIndex > firstSelectedIndex) {
start = firstSelectedIndex;
end = selectedIndex;
for (; end >= start; start++) {
item = items[start];
selectItem(item, selection);
}
} else {
start = firstSelectedIndex;
end = selectedIndex;
for (; end <= start; start--) {
item = items[start];
selectItem(item, selection);
}
}
} else {
start = firstSelectedIndex;
end = selectedIndex;
if (selectedItem.selected) {
deselectItem(selectedItem, selection);
} else {
selectItem(selectedItem, selection);
}
for (; end <= start; start--) {
item = items[start];
selectItem(item, selection);
}
firstSelectedIndex = selectedIndex;
}
} else {
}
if(selectedItem.selected) {
deselectItem(selectedItem, selection);
} else {
selectItem(selectedItem, selection);
function selectItem(item, selection) {
var isSelected = false;
for (var i = 0; selection.length > i; i++) {
var selectedItem = selection[i];
if (item.id === selectedItem.id) {
isSelected = true;
}
}
if (!isSelected) {
selection.push({ id: item.id });
item.selected = true;
}
}
function deselectItem(item, selection) {
for (var i = 0; selection.length > i; i++) {
var selectedItem = selection[i];
if (item.id === selectedItem.id) {
selection.splice(i, 1);
item.selected = false;
}
}
}
function clearSelection(items, folders, selection) {
var i = 0;
selection.length = 0;
if (angular.isArray(items)) {
for (i = 0; items.length > i; i++) {
var item = items[i];
item.selected = false;
}
}
firstSelectedIndex = selectedIndex;
}
}
function selectItem(item, selection) {
var isSelected = false;
for (var i = 0; selection.length > i; i++) {
var selectedItem = selection[i];
if (item.id === selectedItem.id) {
isSelected = true;
if (angular.isArray(items)) {
for (i = 0; folders.length > i; i++) {
var folder = folders[i];
folder.selected = false;
}
}
}
if(!isSelected) {
selection.push({id: item.id});
item.selected = true;
}
}
}
function deselectItem(item, selection) {
for (var i = 0; selection.length > i; i++) {
var selectedItem = selection[i];
if (item.id === selectedItem.id) {
selection.splice(i, 1);
item.selected = false;
function selectAllItems(items, selection, $event) {
var checkbox = $event.target;
var clearSelection = false;
if (!angular.isArray(items)) {
return;
}
}
}
function clearSelection(items, folders, selection) {
selection.length = 0;
var i = 0;
for (var i = 0; i < items.length; i++) {
selection.length = 0;
var item = items[i];
if (checkbox.checked) {
selection.push({ id: item.id });
} else {
clearSelection = true;
}
item.selected = checkbox.checked;
if(angular.isArray(items)) {
for(i = 0; items.length > i; i++) {
var item = items[i];
item.selected = false;
}
}
if(angular.isArray(items)) {
for(i = 0; folders.length > i; i++) {
var folder = folders[i];
folder.selected = false;
if (clearSelection) {
selection.length = 0;
}
}
}
function selectAllItems(items, selection, $event) {
}
var checkbox = $event.target;
var clearSelection = false;
function isSelectedAll(items, selection) {
if (!angular.isArray(items)) {
return;
}
var numberOfSelectedItem = 0;
selection.length = 0;
for (var itemIndex = 0; items.length > itemIndex; itemIndex++) {
var item = items[itemIndex];
for (var i = 0; i < items.length; i++) {
for (var selectedIndex = 0; selection.length > selectedIndex; selectedIndex++) {
var selectedItem = selection[selectedIndex];
var item = items[i];
if (item.id === selectedItem.id) {
numberOfSelectedItem++;
}
}
if (checkbox.checked) {
selection.push({id: item.id});
} else {
clearSelection = true;
}
}
item.selected = checkbox.checked;
if (numberOfSelectedItem === items.length) {
return true;
}
}
}
if (clearSelection) {
selection.length = 0;
}
function setSortingDirection(col, direction, options) {
return options.orderBy.toUpperCase() === col.toUpperCase() && options.orderDirection === direction;
}
}
function setSorting(field, allow, options) {
if (allow) {
options.orderBy = field;
function isSelectedAll(items, selection) {
if (options.orderDirection === "desc") {
options.orderDirection = "asc";
} else {
options.orderDirection = "desc";
}
}
}
//This takes in a dictionary of Ids with Permissions and determines
// the intersect of all permissions to return an object representing the
// listview button permissions
function getButtonPermissions(unmergedPermissions, currentIdsWithPermissions) {
if (currentIdsWithPermissions == null) {
currentIdsWithPermissions = {};
}
var numberOfSelectedItem = 0;
//merge the newly retrieved permissions to the main dictionary
_.each(unmergedPermissions, function (value, key, list) {
currentIdsWithPermissions[key] = value;
});
for(var itemIndex = 0; items.length > itemIndex; itemIndex++) {
var item = items[itemIndex];
//get the intersect permissions
var arr = [];
_.each(currentIdsWithPermissions, function (value, key, list) {
arr.push(value);
});
for(var selectedIndex = 0; selection.length > selectedIndex; selectedIndex++) {
var selectedItem = selection[selectedIndex];
//we need to use 'apply' to call intersection with an array of arrays,
//see: http://stackoverflow.com/a/16229480/694494
var intersectPermissions = _.intersection.apply(_, arr);
if(item.id === selectedItem.id) {
numberOfSelectedItem++;
}
}
return {
canCopy: _.contains(intersectPermissions, 'O'), //Magic Char = O
canCreate: _.contains(intersectPermissions, 'C'), //Magic Char = C
canDelete: _.contains(intersectPermissions, 'D'), //Magic Char = D
canMove: _.contains(intersectPermissions, 'M'), //Magic Char = M
canPublish: _.contains(intersectPermissions, 'U'), //Magic Char = U
canUnpublish: _.contains(intersectPermissions, 'U'), //Magic Char = Z (however UI says it can't be set, so if we can publish 'U' we can unpublish)
};
}
}
var service = {
getLayout: getLayout,
getFirstAllowedLayout: getFirstAllowedLayout,
setLayout: setLayout,
saveLayoutInLocalStorage: saveLayoutInLocalStorage,
selectHandler: selectHandler,
selectItem: selectItem,
deselectItem: deselectItem,
clearSelection: clearSelection,
selectAllItems: selectAllItems,
isSelectedAll: isSelectedAll,
setSortingDirection: setSortingDirection,
setSorting: setSorting,
getButtonPermissions: getButtonPermissions
};
if(numberOfSelectedItem === items.length) {
return true;
}
return service;
}
}
function setSortingDirection(col, direction, options) {
return options.orderBy.toUpperCase() === col.toUpperCase() && options.orderDirection === direction;
}
function setSorting(field, allow, options) {
if (allow) {
options.orderBy = field;
if (options.orderDirection === "desc") {
options.orderDirection = "asc";
} else {
options.orderDirection = "desc";
}
}
}
var service = {
getLayout: getLayout,
getFirstAllowedLayout: getFirstAllowedLayout,
setLayout: setLayout,
saveLayoutInLocalStorage: saveLayoutInLocalStorage,
selectHandler: selectHandler,
selectItem: selectItem,
deselectItem: deselectItem,
clearSelection: clearSelection,
selectAllItems: selectAllItems,
isSelectedAll: isSelectedAll,
setSortingDirection: setSortingDirection,
setSorting: setSorting
};
return service;
}
angular.module('umbraco.services').factory('listViewHelper', listViewHelper);
angular.module('umbraco.services').factory('listViewHelper', listViewHelper);
})();
@@ -21,6 +21,7 @@ function packageHelper(assetsService, treeService, eventsService, $templateCache
}
angular.module('umbraco.services').factory('packageHelper', packageHelper);
//TODO: I believe this is obsolete
function umbPhotoFolderHelper($compile, $log, $timeout, $filter, imageHelper, mediaHelper, umbRequestHelper) {
return {
/** sets the image's url, thumbnail and if its a folder */
@@ -319,7 +320,6 @@ function umbPhotoFolderHelper($compile, $log, $timeout, $filter, imageHelper, me
}
};
}
angular.module("umbraco.services").factory("umbPhotoFolderHelper", umbPhotoFolderHelper);
/**
@@ -0,0 +1,65 @@
(function() {
'use strict';
function variationsHelper() {
var variations = [];
function setMaster(master) {
master.master = true;
variations.push(master);
}
function getVariations() {
return variations;
}
function createVariation(variation) {
var newVariation = angular.copy(variation);
newVariation.master = false;
variations.push(newVariation);
}
function saveVariation(updatedVariation) {
for(var i = 0; i < variations.length; i++) {
var variation = variations[i];
if(variation.id === updatedVariation) {
variation.name = updatedVariation.name;
variation.description = updatedVariation.description;
}
}
}
function cloneVariation(variation) {
var variationClone = angular.copy(variation);
variationClone.master = false;
variationClone.published = false;
variations.push(variationClone);
console.log(variations);
}
function deleteVariation(variation, event, index) {
variations.splice(index, 1);
}
var service = {
setMaster: setMaster,
getVariations: getVariations,
createVariation: createVariation,
saveVariation: saveVariation,
cloneVariation: cloneVariation,
deleteVariation: deleteVariation
};
return service;
}
angular.module('umbraco.services').factory('variationsHelper', variationsHelper);
})();
@@ -155,6 +155,53 @@ function NavigationController($scope, $rootScope, $location, $log, $routeParams,
}
};
$scope.websites = [
{
name: "English",
language: "en-UK",
selected: true
},
{
name: "Dansk",
language: "da-DK",
selected: false
}
];
$scope.createWebsite = function() {
$scope.createWebsiteOverlay = {
view: "createwebsite",
title: "Create website",
submitButtonLabel: "Create website",
show: true,
submit: function(model) {
// deselct all current sites
for(var i = 0; i < $scope.websites.length; i++) {
var website = $scope.websites[i];
website.selected = false;
}
// set new site to selected and push to scope
model.website.selected = true;
$scope.websites.push(model.website);
// clsoe overlay
$scope.createWebsiteOverlay.show = false;
$scope.createWebsiteOverlay = null;
},
close: function() {
$scope.createWebsiteOverlay.show = false;
$scope.createWebsiteOverlay = null;
}
};
};
$scope.clickWebsite = function(website) {
};
//ensure to unregister from all events!
$scope.$on('$destroy', function () {
for (var e in evts) {
@@ -107,7 +107,9 @@
@import "components/umb-grid.less";
@import "components/umb-empty-state.less";
@import "components/umb-property-editor.less";
@import "components/umb-iconpicker.less";
@import "components/umb-website-selector.less";
@import "components/umb-dots.less";
@import "components/buttons/umb-button.less";
@import "components/buttons/umb-button-group.less";
@@ -6,13 +6,15 @@
justify-content: space-between;
margin-top: -30px;
position: relative;
top: 0;
}
.umb-editor-sub-header.-umb-sticky-bar {
box-shadow:
0 5px 0 rgba(0, 0, 0, 0.08),
0 1px 0 rgba(0, 0, 0, 0.16);
box-shadow: 0 5px 0 rgba(0, 0, 0, 0.08), 0 1px 0 rgba(0, 0, 0, 0.16);
transition: box-shadow 1s;
top: 100px;
transform: translate(0, 50%);
}
.umb-group-builder__property-preview .umb-editor-sub-header {
@@ -152,6 +152,30 @@
}
}
/* ---------- OVERLAY TREE ---------- */
.umb-overlay.umb-overlay-tree {
position: absolute;
width: 500px;
top: 0;
left: 100%;
bottom: 0;
border: none;
//box-shadow: 0 0 20px rgba(0,0,0,0.19), 0 0 6px rgba(0,0,0,0.23);
box-shadow: 3px 0 7px #dbdbdb;
display: inline-block;
}
.umb-overlay.umb-overlay-tree .umb-overlay-header {
flex-basis: 100px;
padding: 20px;
box-sizing: border-box;
}
.umb-overlay.umb-overlay-tree .umb-overlay-container {
padding: 20px;
}
/* ---------- OVERLAY ITEM DETAILS ---------- */
.umb-overlay__item-details {
position: absolute;
@@ -0,0 +1,26 @@
.umb-dots {
position: relative;
width: 5px;
height: 5px;
background-color: @gray;
border-radius: 50%;
}
.umb-dots:before,
.umb-dots:after {
display: block;
position: absolute;
content: '';
width: 5px;
height: 5px;
background-color: @gray;
border-radius: 50%;
}
.umb-dots:before {
transform: translateX(-8px);
}
.umb-dots:after {
transform: translateX(8px);
}
@@ -0,0 +1,46 @@
.umb-iconpicker {
display: flex;
flex-direction: row;
flex-wrap: wrap;
margin: 0;
}
.umb-iconpicker-item {
display: flex;
flex-direction: row;
flex: 0 0 14.28%;
justify-content: center;
align-items: center;
margin-bottom: 0;
overflow: hidden;
}
.umb-iconpicker-item a {
display: flex;
justify-content: center;
align-items: center;
width: 100%;
height: 100%;
padding: 15px 0;
text-decoration: none;
}
.umb-iconpicker-item a:hover,
.umb-iconpicker-item a:focus{
background: darken(@grayLighter, 1%);
outline: none;
}
.umb-iconpicker-item a:active {
background: darken(@grayLighter, 4%);
}
.umb-iconpicker-item i {
font-size: 30px;
}
@@ -16,8 +16,23 @@
.umb-keyboard-shortcuts-overview__overlay-close {
position: absolute;
top: 10px;
right: 10px;
top: 20px;
right: 20px;
font-size: 25px;
border-radius: 20px;
width: 35px;
height: 35px;
display: flex;
justify-content: center;
align-items: center;
background-color: transparent;
line-height: 1em;
}
.umb-keyboard-shortcuts-overview__overlay-close:hover {
background-color: @blue;
color: #ffffff;
text-decoration: none;
}
.umb-keyboard-shortcuts-overview__overlay-content {
@@ -198,6 +198,7 @@ input.umb-table__input {
padding: 6px 2px;
text-align: left;
overflow:hidden;
}
.umb-table-cell > * {
@@ -0,0 +1,109 @@
.umb-website-selector {
border-bottom: 1px solid #d9d9d9;
display: flex;
align-items: stretch;
height: 50px;
position: relative;
}
.umb-website-selector__create-website {
display: flex;
width: 100%;
justify-content: center;
align-items: center;
color: @blue;
}
.umb-website-selector__dropdown-toggle {
display: flex;
flex-direction: row;
align-items: center;
justify-content: space-between;
width: 100%;
box-sizing: border-box;
padding-left: 20px;
padding-right: 20px;
font-weight: bold;
}
.umb-website-selector__dropdown-toggle:hover,
.umb-website-selector__dropdown-toggle:focus {
text-decoration: none;
}
.umb-website-selector__dropdown-toggle-content {
display: flex;
align-items: center;
}
.umb-website-selector__dropdown-toggle-name {
margin-right: 5px;
}
.umb-website-selector__dropdown {
position: absolute;
top: 50px;
left: 0;
right: 0;
z-index: 1;
background: #ffffff;
}
.umb-website-selector__websites {
margin-left: 0;
margin-bottom: 0;
list-style: none;
max-height: 300px;
overflow-y: auto;
}
.umb-website-selector__website-link {
display: flex;
align-items: center;
justify-content: space-between;
padding-top: 10px;
padding-right: 20px;
padding-bottom: 10px;
padding-left: 38px;
}
.umb-website-selector__website-link:hover,
.umb-website-selector__website-link.-selected {
background-color: @grayLighter;
text-decoration: none;
}
.umb-website-selector__dropdown-action {
display: flex;
justify-content: center;
align-items: center;
padding-top: 10px;
padding-bottom: 10px;
color: @blue;
font-size: 12px;
}
.umb-website-selector__dropdown-arrow {
width: 0;
height: 0;
margin-right: 10px;
}
.umb-website-selector__dropdown-arrow.-down {
border-left: 4px solid transparent;
border-right: 4px solid transparent;
border-top: 4px solid @gray;
}
.umb-website-selector__dropdown-arrow.-up {
border-left: 4px solid transparent;
border-right: 4px solid transparent;
border-bottom: 4px solid @gray;
}
.umb-website-selector__dropdown-action:hover {
text-decoration: none;
background: @blue;
color: #ffffff;
}
@@ -16,12 +16,12 @@ label small, .guiDialogTiny {
font-size: 11px
}
label.control-label {
label.control-label, .control-label {
padding: 0 10px 0 0 !important;
font-weight: bold;
}
.umb-status-label{
color: @gray !important;
}
@@ -164,7 +164,7 @@ textarea {
// Identify controls by their labels
label {
display: block;
display: inline-block;
margin-bottom: 5px;
}
+1 -1
View File
@@ -139,7 +139,7 @@ h5.-black {
}
/* LABELS*/
.umb-control-group label.control-label {
.umb-control-group label.control-label, .umb-control-group .control-label {
text-align: left;
}
.umb-control-group label.control-label > div > label {
@@ -9,13 +9,41 @@
color: @white;
position: absolute;
z-index: 10000;
top: 0px;
left: 0px;
margin: 0 !Important;
top: 0;
left: 0;
margin: 0 !important;
padding: 0;
border-radius: 0;
}
@media only screen and (-webkit-min-device-pixel-ratio: 1.5),
only screen and (min-resolution: 144dpi)
{
.login-overlay {
background-image: url(../img/application/logo@2x.png) !important;
}
}
@media only screen and (-webkit-min-device-pixel-ratio: 2),
only screen and (min-resolution: 192dpi)
{
.login-overlay {
background-image: url(../img/application/logo@2x.png) !important;
}
}
@media only screen and (-webkit-min-device-pixel-ratio: 3),
only screen and (min-resolution: 3dppx),
only screen and (min-resolution: 350dpi)
{
.login-overlay {
background-image: url(../img/application/logo@3x.png) !important;
}
}
.login-overlay .umb-modalcolumn {
background: none;
border: none;
@@ -62,7 +90,7 @@
}
#hrOr hr {
margin: 0px;
margin: 0;
border: none;
background-color: @gray;
height: 1px;
@@ -493,3 +493,66 @@ input.umb-panel-header-description {
.umb-editor-drawer-content__left-side {
margin-right: auto;
}
/* --- VARIATIONS --- */
.umb-variations-quick-switcher__toggle {
position: absolute;
top: 6px;
right: 10px;
font-size: 16px;
}
.umb-variations-quick-switcher_variations {
position: absolute;
top: 40px;
left: 0;
right: 0;
z-index: 20;
background-color: #ffffff;
max-height: 200px;
overflow-y: scroll;
}
.umb-variations-quick-switcher__variation {
display: flex;
flex-direction: row;
align-items: center;
padding: 10px 15px;
}
.umb-variations-quick-switcher__variation:last-child {
border-bottom: none;
}
.umb-variations-quick-switcher__variation:hover,
.umb-variations-quick-switcher__variation:focus {
background-color: @grayLighter;
text-decoration: none;
outline: none;
}
.umb-variations-quick-switcher__variation-published-state {
display: block;
width: 8px;
height: 8px;
border-radius: 50%;
background-color: @grayLight;
margin-right: 10px;
}
.umb-variations-quick-switcher__variation-published-state.-published {
background-color: @green;
}
.umb-variations-quick-switcher__variation-name {
font-size: 12px;
font-weight: bold;
}
.umb-variations-quick-switcher__variation-description {
font-size: 12px;
color: @gray;
margin-left: 10px;
}
@@ -81,6 +81,9 @@ div.umb-codeeditor .umb-btn-toolbar {
font-size:16px !important;
}
/* pre-value editor */
.rte-editor-preval .control-group .controls > div > label .mce-ico { line-height: 20px; }
//
// Color picker
@@ -275,11 +278,12 @@ ul.color-picker li a {
.umb-cropper{
position: relative;
padding: 10px;
}
.umb-cropper img, .umb-cropper-gravity img{
position: absolute;
position: relative;
max-width: 100%;
height: auto;
top: 0;
left: 0;
}
@@ -293,19 +297,22 @@ ul.color-picker li a {
left: 0;
cursor: move;
z-index: 6001;
position: absolute;
}
.umb-cropper .viewport{
overflow: hidden;
position: relative;
margin: auto;
max-width: 100%;
height: auto;
}
.umb-cropper-gravity .viewport{
overflow: hidden;
position: relative;
width: 400px;
height: 300px
width: 100%;
height: 100%;
}
@@ -335,27 +342,45 @@ ul.color-picker li a {
opacity: 0.8;
}
.umb-cropper-gravity .overlay i{
.umb-cropper-gravity .overlay i {
font-size: 26px;
line-height: 26px;
opacity: 0.8 !important;
}
.umb-cropper .crop-container{
.umb-cropper .crop-container {
text-align: center;
}
.umb-cropper .crop-slider{
vertical-align: middle;
padding: 10px 50px 10px 50px;
.umb-cropper .crop-slider {
padding: 10px;
border-top: 1px solid @grayLighter;
margin-top: 10px;
display: flex;
align-items: center;
justify-content: center;
flex-wrap: wrap;
@media (min-width: 769px) {
padding: 10px 50px 10px 50px;
}
}
.umb-cropper .crop-slider i{color: @gray;}
.umb-cropper .crop-slider input{
margin-top: 7px;
width: 320px;
.umb-cropper .crop-slider i {
color: @gray;
flex: 0 0 25px;
padding: 0 5px;
box-sizing: border-box;
}
.umb-cropper .crop-slider i:first-of-type {
text-align: right;
}
.umb-cropper .crop-slider input {
flex: 0 1 auto;
}
.umb-cropper-gravity .viewport, .umb-cropper-gravity, .umb-cropper-imageholder {
display: inline-block;
@@ -372,55 +397,98 @@ ul.color-picker li a {
}
.gravity-container .viewport {
width: 494px;
max-width: 600px;
}
.gravity-container .viewport:hover {
cursor: pointer;
}
.imagecropper {
display: flex;
align-items: flex-start;
flex-direction: row;
@media (max-width: 768px) {
flex-direction: column;
float: left;
max-width: 100%;
}
}
.imagecropper .umb-cropper__container {
position: relative;
margin-bottom: 10px;
max-width: 100%;
border: 1px solid #f8f8f8;
@media (min-width: 769px) {
width: 600px;
}
}
.umb-close-cropper {
position: absolute;
top: 3px;
right: 3px;
cursor: pointer;
}
.umb-close-cropper:hover {
opacity: .9;
background: @grayLighter;
}
.imagecropper .umb-sortable-thumbnails {
border-left: 2px solid #f8f8f8;
margin-left: 4px;
padding-left: 2px;
float: left;
width: 100px;
display: flex;
flex-direction: row;
flex-wrap: wrap;
}
.imagecropper .umb-sortable-thumbnails li {
display: block;
}
display: flex;
flex-direction: column;
justify-content: space-between;
.imagecropper .umb-sortable-thumbnails li.current a, .imagecropper .umb-sortable-thumbnails li.current a:hover {
background: #eeeeee;
text-decoration: none;
}
.imagecropper .umb-sortable-thumbnails li:first-of-type {
padding: 8px;
margin-top: 0;
padding-top: 0;
}
.imagecropper .umb-sortable-thumbnails li .crop-name, .imagecropper .umb-sortable-thumbnails li .crop-size {
.imagecropper .umb-sortable-thumbnails li.current {
border-color: @grayLight;
background: @grayLighter;
color: @black;
cursor: pointer;
}
.imagecropper .umb-sortable-thumbnails li:hover,
.imagecropper .umb-sortable-thumbnails li.current:hover {
border-color: @grayLight;
background: @grayLighter;
color: @black;
cursor: pointer;
opacity: .95;
}
.imagecropper .umb-sortable-thumbnails li .crop-name,
.imagecropper .umb-sortable-thumbnails li .crop-size {
display: block;
text-align: left;
font-size: 11px;
font-size: 13px;
line-height: 1;
}
.imagecropper .umb-sortable-thumbnails li .crop-name {
font-weight: bold;
margin: 10px 0 5px;
}
.imagecropper .umb-sortable-thumbnails li .crop-size {
font-size: 10px;
font-style: italic;
color: #666;
}
.imagecropper .umb-sortable-thumbnails li a {
display: block;
padding: 5px;
}
.imagecropper .umb-sortable-thumbnails li a:hover {
background: #f8f8f8;
text-decoration: none;
}
.imagecropper .umb-sortable-thumbnails li a:hover .crop-text {
text-decoration: none;
margin: 0 0 5px;
}
.btn-crop-delete {
@@ -428,20 +496,6 @@ ul.color-picker li a {
text-align: left;
}
.imagecropper .umb-sortable-thumbnails.many {
width: 210px;
}
.imagecropper .umb-sortable-thumbnails.many li {
width: 85px;
float: left;
}
.imagecropper .umb-sortable-thumbnails.many li:nth-child(2) {
margin-top: 0;
padding-top: 0;
}
//
// folder-browser
// --------------------------------------------------
@@ -19,7 +19,8 @@ ul.sections li {
}
ul.sections li [class^="icon-"]:before,
ul.sections li [class*=" icon-"]:before{
ul.sections li [class*=" icon-"]:before,
ul.sections li img.icon-section {
font-size: 30px;
margin: 1px 0 0 0;
opacity: 0.4;
@@ -29,7 +30,8 @@ ul.sections li [class*=" icon-"]:before{
}
ul.sections:hover li [class^="icon-"]:before,
ul.sections:hover li [class*=" icon-"]:before {
ul.sections:hover li [class*=" icon-"]:before,
ul.sections:hover li img.icon-section {
opacity: 1
}
@@ -2,55 +2,48 @@
<div class="umb-panel-header">
<div class="umb-el-wrap umb-panel-buttons">
<div class="form-search">
<i class="icon-search"></i>
<i class="icon-search"></i>
<input type="text"
style="width: 100%"
ng-model="searchTerm"
class="umb-search-field search-query input-block-level"
style="width: 100%"
ng-model="searchTerm"
class="umb-search-field search-query input-block-level"
placeholder="Filter...">
</div>
</div>
</div>
<div class="umb-panel-body with-footer">
<div class="umb-control-group">
<select ng-model="color" class="input-block-level">
<option value="">Black</option>
<option value="color-green">Green</option>
<option value="color-yellow">Yellow</option>
<option value="color-green">Green</option>
<option value="color-yellow">Yellow</option>
<option value="color-orange">Orange</option>
<option value="color-blue">Blue</option>
<option value="color-blue">Blue</option>
<option value="color-red">Red</option>
</select>
<!--
<select class="input-block-level">
<option value="">Black</option>
<option value="color-green">Green</option>
<option value="color-blue">Turquoise</option>
<option value="color-purple">Purple</option>
<option value="color-red">Red</option>
<option value="color-orange">Orange</option>
<option value="color-sky-blue">Sky blue</option>
<option value="color-yellow">Yellow</option>
</select>-->
</div>
<div class="umb-loader" ng-hide="icons"></div>
<umb-load-indicator ng-if="loading"></umb-load-indicator>
<div class="umb-control-group">
<ul class="umb-thumbnails thumbnails" ng-class="color">
<li class="span1" ng-repeat="icon in icons|filter: searchTerm">
<a href="#" title="{{icon}}" class="thumbnail" ng-click="submitClass(icon)" prevent-default>
<i class="{{icon}} large" style="font-size: 32px"></i>
<div class="umb-control-group" ng-show="!loading">
<ul class="umb-iconpicker" ng-class="color" ng-show="icons">
<li class="umb-iconpicker-item" ng-repeat="icon in filtered = (icons | filter: searchTerm) track by $id(icon)">
<a href="#" title="{{icon}}" ng-click="submitClass(icon)" prevent-default>
<i class="{{icon}} large"></i>
</a>
</li>
</ul>
</div>
<umb-empty-state
ng-if="filtered.length === 0"
position="center">
<localize key="defaultdialogs_noIconsFound">No icons were found.</localize>
</umb-empty-state>
</div>
<div class="umb-panel-footer" >
<div class="umb-el-wrap umb-panel-buttons">
<div class="btn-toolbar umb-btn-toolbar pull-right">

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