Compare commits

...

525 Commits

Author SHA1 Message Date
Sebastiaan Jansssen 1607e51270 Merge branch 'dev-v7' into master-v7 2018-02-19 14:21:16 +01:00
Sebastiaan Jansssen 2f31175db5 Bump version to 7.7.12 2018-02-19 14:20:47 +01:00
Sebastiaan Jansssen 044b43f6e1 Merge branch 'dev-v7' into master-v7 2018-02-19 14:10:09 +01:00
Sebastiaan Jansssen 9178e7afcf Whoops, no need to introduce a new method here, old method was still available 2018-02-14 12:13:01 +01:00
Sebastiaan Janssen b18945e630 Merge pull request #2447 from umbraco/temp-Fix-CDF-Version-Change
Updates the CDF version changer to to use a hash of the current versi…
2018-02-14 10:25:27 +01:00
Sebastiaan Jansssen 4640cf56d1 Make change non-breaking 2018-02-14 10:23:58 +01:00
Shannon eae1ce7012 fixes build 2018-02-14 12:05:05 +11:00
Shannon e900711180 Updates the CDF version changer to to use a hash of the current version and the date time so that it's not constantly updated if it's not changed. 2018-02-14 11:53:49 +11:00
Claus 93f4d65227 Merge pull request #2438 from umbraco/temp-U4-10958
Fixes broken MNTP by switching convert cases to the correct DataType
2018-02-09 14:42:08 +01:00
Robert a4c0342bda Fixes broken MNTP by switching convert cases to the correct DataType 2018-02-09 14:09:03 +01:00
Sebastiaan Jansssen 095633ba27 Test names were inverted 2018-02-09 13:27:25 +01:00
Sebastiaan Jansssen c63156fcd8 Bump version to 7.7.11
(cherry picked from commit 0c25c36af0)
2018-02-09 09:53:52 +01:00
Sebastiaan Jansssen c59a226d56 Merge remote-tracking branch 'origin/dev-v7' into master-v7 2018-02-09 09:51:39 +01:00
Sebastiaan Jansssen 0c25c36af0 Bump version to 7.7.11 2018-02-09 09:46:05 +01:00
Stephan 84a90884e3 Merge pull request #2433 from umbraco/temp-U4-10947
Fix for not being able to save decimal value
2018-02-09 08:14:51 +01:00
Shannon d29b7311fa reverts the convertible2 back to what it was before 2018-02-09 10:08:25 +11:00
Shannon 17b59cc20f Updates the ObjectExtensions TryConvertTo code and moved all unit tests to ObjectExtensionsTests which now all pass 2018-02-09 10:02:51 +11:00
Robert 4423571eaa Added ConvertToNullableDecimalTest and check that fixes the decimal save issue 2018-02-08 16:21:09 +01:00
Stephan e76c42f874 Merge pull request #2434 from umbraco/temp-U4-U4-10950
Fix checkbox in nested content
2018-02-08 13:42:42 +01:00
Robert 151c35bc47 Moving check to TryToConvertValueToCrlType 2018-02-08 13:15:43 +01:00
Robert 84265a9716 Fix checkbox in nested content 2018-02-08 12:18:51 +01:00
Robert 6618388973 Fix for not being able to save decimal value 2018-02-08 12:10:57 +01:00
Claus 527f98189a Merge pull request #2423 from umbraco/temp-u4-10897
temp U4-10897
2018-02-01 13:29:45 +01:00
Sebastiaan Janssen 78c289a559 Merge pull request #2425 from umbraco/mittonp-dev-v7
Mittonp dev v7
2018-02-01 08:59:35 +01:00
Sebastiaan Jansssen 646abb3aea Merge branch 'dev-v7' of https://github.com/mittonp/Umbraco-CMS into mittonp-dev-v7
# Conflicts:
#	src/Umbraco.Web.UI/umbraco/config/lang/da.xml
#	src/Umbraco.Web.UI/umbraco/config/lang/en.xml
#	src/Umbraco.Web.UI/umbraco/config/lang/en_us.xml
#	src/Umbraco.Web.UI/umbraco/config/lang/es.xml
#	src/Umbraco.Web.UI/umbraco/config/lang/fr.xml
#	src/Umbraco.Web.UI/umbraco/config/lang/nl.xml
#	src/Umbraco.Web.UI/umbraco/config/lang/pl.xml
#	src/Umbraco.Web.UI/umbraco/config/lang/ru.xml
#	src/Umbraco.Web.UI/umbraco/config/lang/zh.xml
2018-02-01 08:57:47 +01:00
Sebastiaan Janssen 2af59471a2 Merge pull request #973 from mattbrailsford/dev-v7-insertmacrofix
Updated insert macro dialog to prevent closing on enter key
2018-02-01 08:28:59 +01:00
Sebastiaan Janssen 090f89e5b6 Merge pull request #2223 from kgiszewski/fix/U4-6309
U4-6309: Fix black bars that appear on a RTE image resize
2018-01-31 10:43:29 +01:00
Stephan 4870afd2d3 U4-10897 - change enlisting priorities 2018-01-30 14:27:58 +01:00
Stephan 80257b6684 Revert "U4-10897 - change enlisting priorities"
This reverts commit 8f3a0b6919.
2018-01-30 14:26:59 +01:00
Stephan 8f3a0b6919 U4-10897 - change enlisting priorities 2018-01-30 14:25:43 +01:00
Stephan 9fd2f34343 U4-10897 - defer Examine indexing until scope is all done 2018-01-30 13:53:37 +01:00
Stephan e774717346 U4-10897 - expose enlisted mutable Xml in events 2018-01-30 13:14:01 +01:00
Sebastiaan Jansssen 7cd540c37e Remove additional premature uses of C#7 features 2018-01-29 14:35:30 +01:00
Sebastiaan Jansssen 83595ecaf5 Don't rely on C# 7 features 2018-01-29 14:06:25 +01:00
Stephan f2819f61e5 Merge pull request #2417 from umbraco/temp-u4-10846
U4-10846 - fix member group cache
2018-01-25 11:06:17 +01:00
Sebastiaan Janssen 2107e9d9e3 Merge pull request #2420 from PerplexDaniel/patch-1
Fix NullReferenceException when HttpContext is not available
2018-01-25 10:18:32 +01:00
Daniël Knippers c623b448ba Fix NullReferenceException when HttpContext is null
This method will throw a NullReferenceException in contexts without an HttpContext, like is the case in background threads. As HttpContext is only used to set an isDebug flag, it seems more sensible to not throw in cases without an HttpContext, but simply set isDebug to false instead. If this is not acceptable behavior, could we perhaps look at something other than HttpContext.Current.IsDebuggingEnabled to decide whether isDebug should be set?
2018-01-25 08:56:46 +01:00
Sebastiaan Janssen 8bb49f57e8 Merge pull request #2419 from umbraco/redmorello-U4-10864_close_back_office_search_results
Redmorello u4 10864 close back office search results
2018-01-24 17:47:44 +01:00
Sebastiaan Jansssen da0b1c2f23 Merge branch 'U4-10864_close_back_office_search_results' of https://github.com/redmorello/Umbraco-CMS into redmorello-U4-10864_close_back_office_search_results
# Conflicts:
#	src/Umbraco.Web.UI.Client/src/views/components/application/umb-navigation.html
2018-01-24 17:43:19 +01:00
Sebastiaan Jansssen a288fc62eb Workaround: keep the cache we used to have but clear all cache for membergroups when a member group changes 2018-01-24 17:26:21 +01:00
Sebastiaan Jansssen 82e50ccd3a Merge branch 'dev-v7' of https://github.com/umbraco/Umbraco-CMS into dev-v7 2018-01-24 16:13:31 +01:00
Sebastiaan Jansssen 15b0dc9f29 Merge branch 'dev-v7.8' of https://github.com/kristoffer-tvera/Umbraco-CMS into kristoffer-tvera-dev-v7.8 2018-01-24 16:12:06 +01:00
Sebastiaan Janssen 8057d09fc2 Merge pull request #2416 from PeteDuncanson/patch-1
Prevent Pinterest messing with media in the back office
2018-01-24 15:53:40 +01:00
Sebastiaan Jansssen 8877100bf0 Merge branch 'dev-v7' into temp-u4-10846 2018-01-24 15:50:08 +01:00
Stephan 41c96e6e26 Merge pull request #2398 from leekelleher/issue/U4-10756
Proposed patch for U4-10756 - Guid TypedContent performance
2018-01-24 15:27:43 +01:00
Sebastiaan Jansssen abdd117264 Fixes bug in MB 3.0.9 2018-01-24 15:26:40 +01:00
Sebastiaan Jansssen 6272dac698 Use string.Format instead of interpolation 2018-01-24 14:34:21 +01:00
Sebastiaan Jansssen 7a4b5fa796 Bump version to 7.7.10 2018-01-24 14:34:03 +01:00
Sebastiaan Jansssen c962132ee0 Update to ModelsBuilder 3.0.9 2018-01-24 14:33:32 +01:00
leekelleher 0780979469 Eagerly populating the Guid lookup
as per @Shazwazza's comment: https://github.com/umbraco/Umbraco-CMS/pull/2398#issuecomment-358752346

Tested against 12,000 nodes (in the XML cache), profiling showed it took 55ms.
2018-01-24 11:53:52 +00:00
leekelleher a42e568fdf Initialized the ConcurrentDictionary statically
as per @JimBobSquarePants's comment: https://github.com/umbraco/Umbraco-CMS/pull/2398#discussion_r162799543
2018-01-24 11:51:53 +00:00
Robert e62661cc6a Merge pull request #2397 from leekelleher/issue/U4-10845
U4-10845 MNTP value-converter - trashed content causes database lookups
2018-01-24 12:48:29 +01:00
leekelleher 6841b2ac61 Amended the lookup dictionary setter,
as per @JimBobSquarePants's comment: https://github.com/umbraco/Umbraco-CMS/pull/2398#discussion_r162522998
2018-01-24 10:29:23 +00:00
leekelleher f7f4276485 Removed the need for the UseLegacyXmlSchema check
The enhancement in PR #2367 removed the `"@isDoc"` check,
which was the main difference between the legacy and current XML schema.

Reducing the XPath to `"//*[@key=$guid]"` will perform the same for both types of schema.
_(and saves on a couple of allocations)_
2018-01-24 10:29:23 +00:00
leekelleher bb9e23ca3e Proposed patch for U4-10756 - Guid TypedContent performance
This is a proposal for a temporary workaround to issue U4-10756.

It uses a local static ConcurrentDictionary to store a lookup of Guid/int values.
If the Guid isn't in the lookup, then the traditional XPath is used, which would add the resulting node ID (int) to the lookup.
If the lookup contains the Guid, then the returned int value will be used to perform a more efficient retrieval.

<http://issues.umbraco.org/issue/U4-10756>
2018-01-24 10:29:23 +00:00
Sebastiaan Janssen 7d5d69e2e3 Merge pull request #2418 from abjerner/patch-36
Nested Content should use the new turquoise/purple colors as the rest of the backoffice
2018-01-23 22:02:16 +01:00
Anders Bjerner ee75158dd0 Nested Content should use the new turquoise/purple colors as the rest of the backoffice 2018-01-23 21:55:15 +01:00
Stephan c022397d86 U4-10846 - fix member group cache 2018-01-23 20:54:47 +01:00
Shannon d104525a50 Updates core to use latest CDF version 2018-01-23 11:15:37 -07:00
Sebastiaan Janssen b0a64aa4b5 Merge pull request #2384 from umbraco/temp-u4-10822
U4-10822 - refactor view models binding error handling
2018-01-23 16:24:08 +01:00
Pete Duncanson ca86385269 Prevent Pinterest messing with media in the back office
Fixes: http://issues.umbraco.org/issue/U4-10865
2018-01-23 15:10:09 +00:00
Claus ef4322a9b3 Merge pull request #2414 from umbraco/temp-u4-10844
U4-10844 - delete blueprints with content types
2018-01-23 15:15:15 +01:00
Sebastiaan Janssen 4ab1c51327 Merge pull request #2392 from umbraco/temp-u4-10829
U4-10829 - fix tree controller
2018-01-23 14:13:39 +01:00
Stephan e007a37c36 U4-10844 - delete blueprints with content types 2018-01-23 13:41:36 +01:00
Sebastiaan Janssen 2f67008987 Merge pull request #2407 from abjerner/patch-34
Removed unnecessary &nbsp;
2018-01-23 09:42:30 +01:00
Sebastiaan Janssen 1672e284c5 Merge pull request #2406 from abjerner/patch-33
Minor casing change
2018-01-23 09:41:46 +01:00
Ian Houghton 60ce36a7f2 U4-10864 add button when search returns no results, to clear the search 2018-01-22 22:03:35 +00:00
Anders Bjerner 72e2cacc87 Removed unnecessary &nbsp; 2018-01-22 18:16:42 +01:00
Anders Bjerner 4285102422 Minor casing change 2018-01-22 18:08:37 +01:00
Mads Rasmussen abbcf0e26b Merge pull request #2358 from abjerner/patch-28
Triggers the save button to momentarily show an error icon
2018-01-22 14:55:10 +01:00
Sebastiaan Janssen 347b25472f Merge pull request #2403 from JimBobSquarePants/housekeeping-gitattributes
Add default gitattributes and cleanup editorconfig
2018-01-22 14:38:40 +01:00
Mads Rasmussen b745948dc6 Merge pull request #2361 from bjarnef/dev-v7-U4-10791
U4-10791 - Fix collapsed columns listview settings
2018-01-22 13:48:58 +01:00
Mads Rasmussen 8007c8869f Merge pull request #2401 from umbraco/temp-U4-10835
U4-10835 Adds context menu items to the User tree
2018-01-22 13:25:59 +01:00
Stephan b51a328ead Merge pull request #2402 from JimBobSquarePants/perf-tryconvertto
Performance - 8x Faster TryConvertTo
2018-01-22 13:22:22 +01:00
James Jackson-South f3b8f2eb5f Add default gitattributes and cleanup editorconfig 2018-01-22 21:44:08 +11:00
James Jackson-South de4628f450 Add perf explanation 2018-01-22 20:58:15 +11:00
James Jackson-South b0a64655b4 Fastest dictionary lookups 2018-01-22 16:43:02 +11:00
Stephan 48d88ec8fa Deal fix FIXME 2018-01-21 10:29:06 +01:00
Stephan 7ca151a3fa Use concurrent dictionaries 2018-01-21 10:18:13 +01:00
Stephan 363c8fab2c Cleanup 2018-01-21 10:03:17 +01:00
Stephan 8d4fd9d1cf Merge branch 'perf-tryconvertto' of https://github.com/JimBobSquarePants/Umbraco-CMS into perf-tryconvertto 2018-01-21 10:01:12 +01:00
James Jackson-South 24071eb3b1 Faster TryConvertTo 2018-01-20 14:54:52 +11:00
James Jackson-South 62ffbe7cf0 Cleanup benchmarks and add TryCOnvertTo 2018-01-20 13:00:10 +11:00
Warren Buckley f2d6b47e47 Update labels for context menu items to be just 'Create' & 'Invite' to keep the same consistency throughout the UI as other context menu items do not include the verb 2018-01-19 14:24:57 +00:00
Warren Buckley f3541908c7 Update Users tree context menu to include two new items that navigate directly to an Angular Location/Path which loads the Invite or Create User views as needed 2018-01-19 14:07:23 +00:00
Sebastiaan Jansssen 4e57e1cc18 Nicer variable name, thank to Lee Kelleher! 2018-01-19 12:50:45 +01:00
Sebastiaan Jansssen 410afffaa9 Optimizing use of newlines array 2018-01-19 12:42:04 +01:00
Claus 936e94789d adding to tinyMceConfig.Release.config. 2018-01-19 12:21:57 +01:00
Claus 468a56e5de Merge branch 'karltynan-dev-v7' into dev-v7 2018-01-19 11:11:53 +01:00
Claus 468ec8824a Merge branch 'dev-v7' of git://github.com/karltynan/Umbraco-CMS into karltynan-dev-v7 2018-01-19 11:11:13 +01:00
Sebastiaan Jansssen cad913b7a1 U4-10857 Update to ClientDependency 1.9.5 2018-01-19 08:26:34 +01:00
Sebastiaan Jansssen 382103d99d Bump version to 7.7.9 2018-01-19 08:26:33 +01:00
Sebastiaan Janssen cbb6b9bca0 Merge pull request #2310 from matthew-darby/U4-10495
U4-10495 - Install and customize buttons disabled
2018-01-18 18:38:37 +01:00
Sebastiaan Janssen a1b90a50cd Merge pull request #2343 from soreng/patch-5
Fix for U4-10733
2018-01-18 18:28:34 +01:00
Sebastiaan Janssen 9ea5855073 Merge pull request #2360 from janvanhelvoort/U4-10785
U4-10785 - Filtering of Grid Editors
2018-01-18 18:20:11 +01:00
Sebastiaan Janssen 4a37433042 Merge pull request #2372 from bjarnef/dev-v7-U4-10809
Fix checkmark tree icon, when custom font icon is used for tree icon
2018-01-18 18:00:53 +01:00
Sebastiaan Janssen 91469812d3 Merge pull request #2383 from MMasey/U4-10727
U4 10727 - If nodes with an empty name exist, it's not possible to empty recycle bin
2018-01-18 17:54:40 +01:00
Sebastiaan Janssen 68a8eb7f3f Merge pull request #2375 from redmorello/U4-10762
U4-10762 Fix issue with empty name when registering new members from …
2018-01-18 17:40:05 +01:00
Sebastiaan Janssen 2e7baabb94 Merge pull request #2394 from umbraco/temp-u4-10813
U4-10813 - fix error with groups having a large number of permissions
2018-01-18 17:27:11 +01:00
Sebastiaan Janssen 57745fe71d Merge pull request #2396 from leekelleher/issue/U4-10842
U4-10842 LegacyMediaPickerPropertyConverter null-reference check
2018-01-18 17:17:45 +01:00
Sebastiaan Janssen de6f9236e7 Merge pull request #2399 from leekelleher/issue/U4-8712
U4-8712 MultipleTextstring value newline delimiter changes
2018-01-18 17:13:46 +01:00
Sebastiaan Janssen a00c59e8b5 Merge pull request #2393 from umbraco/temp-u4-10079
U4-10079 - remove default template
2018-01-18 16:54:22 +01:00
Stephan 05c2da807f U4-10079 - fix test 2018-01-18 15:58:51 +01:00
leekelleher 0fd8ca43d6 U4-8712 MultipleTextstring value newline delimiter changes
PR #2185 goes towards resolving this, but doesn't handle the impromptu switch between the `\r\n` and `\n` newline delimiters when republishing a content node.

Using an explicit array of newline chars will resolve this, e.g. `Split(new[] { "\r\n", "\r", "\n" }, StringSplitOptions.None)`

<http://issues.umbraco.org/issue/U4-8712>
2018-01-18 12:18:51 +00:00
leekelleher 87f09b2ee6 U4-10845 MultiNodeTreePickerPropertyConverter - trashed content causes database lookups
If the first ID in the MNTP value is a trashed content node, then the `ConvertSourceToObject` method would
check if the ID is a media or member node, both of these incur a database call.

This can cause a detrimental performance impact on the website.

This patch uses the `startNode.type` prevalue to detect the node type, (e.g. Content, Media or Member).
The prevalue is cached in a private `ConcurrentDictionary` and refreshed using the `DataTypeCacheRefresher` event.
> _Following the same caching-pattern as the Slider, Tags and MediaPicker value-converters._

<http://issues.umbraco.org/issue/U4-10845>
2018-01-18 10:49:18 +00:00
leekelleher e466878925 U4-10842 LegacyMediaPickerPropertyConverter ConvertDataToSource null-reference check
If a selected media node has been trashed on the source environment,
when Deploy comes to transfer the node ID, because it can't transfer the media dependency,
the node ID value is set to `null`.

This causes an issue for the `LegacyMediaPickerPropertyConverter`
and `ConvertDataToSource` throws a null-reference exception.

This patch adds in a null-reference check for the `source` value.

<http://issues.umbraco.org/issue/U4-10842>
2018-01-18 10:04:55 +00:00
Mikulas Tomanka 319acc199e Merge pull request #2391 from matthew-darby/U4-10825
U4-10825 Search member by email in member section
2018-01-17 14:18:43 +01:00
Stephan 2a982f21a7 U4-10813 - fix error with groups having a large number of permissions 2018-01-17 13:07:03 +01:00
Stephan 3ff455f11d U4-10079 - remove default template 2018-01-17 11:36:08 +01:00
Stephan 41ad1bf27b U4-10829 - fix tree controller 2018-01-17 10:47:35 +01:00
Matt Darby f49d939a2d U4-10825 Search member by email in member section 2018-01-16 23:06:15 +08:00
Shannon 7e1e83b493 Fixes PackageInstaller event args to make sure the package metadata is passed through 2018-01-16 19:18:08 +11:00
Stephan 42959a1db5 U4-10822 - fix breaking change 2018-01-12 13:51:06 +01:00
Kristoffer Tverå a1cd22208b Extra check before assigning value to currentColor
In version 7.7.7 with the latest version of LeBlender (1.0.9.2), colorpickers will throw a javascript error in console. Applying this small check will resolve that issue.
ref: https://our.umbraco.org/forum/contributing-to-umbraco-cms/88890-color-picker-cannot-read-property-hasownproperty-of-null
2018-01-12 10:45:59 +01:00
Mads Rasmussen c3116d5df7 remove moment resolution for bower.json 2018-01-12 08:52:13 +01:00
Shannon Deminick b0b874212e Merge pull request #2381 from umbraco/temp-U4-10803
U4-10803: remove dependency on angular-moment
2018-01-12 14:43:06 +11:00
Shannon 19086ab3a1 Merge remote-tracking branch 'origin/dev-v7.8' into temp-U4-10803
# Conflicts:
#	src/Umbraco.Web.UI.Client/bower.json
2018-01-12 14:32:54 +11:00
Shannon Deminick 069594c3ac Merge pull request #2380 from umbraco/U4-10815
U4-10815 Make DisposableObjectSlim
2018-01-12 12:43:47 +11:00
Stephan 0bc4c7e2aa U4-10822 - refactor view models binding error handling 2018-01-11 16:42:20 +01:00
Shannon 83294b6594 bump version 2018-01-12 00:32:00 +11:00
Shannon e0c89eb1ea Merge branch 'dev-v7.8' of https://github.com/umbraco/Umbraco-CMS into dev-v7.8 2018-01-12 00:20:21 +11:00
Shannon 9ad8e6a876 fixes nuspec for tour files 2018-01-12 00:20:06 +11:00
Mads Rasmussen 14b58386e5 fix tour backdropOpacity 2018-01-11 14:14:03 +01:00
Robert e26cbccfe0 Reverted DisposableObject.cs to its original state 2018-01-11 13:22:23 +01:00
Shannon 7dc06c1bea bumps version 2018-01-11 22:29:25 +11:00
Shannon Deminick effa984bdc Merge pull request #2371 from umbraco/temp-U4-10707
fixes: U4-10707 Config to order tour groups
2018-01-11 22:04:24 +11:00
Robert fa058f348d Forgot to removed TODO 2018-01-11 11:02:05 +01:00
Robert 9284269428 TODO's for DisposableObject and DisposableObjectSlim done 2018-01-11 10:53:45 +01:00
Shannon d7f2041ee9 Makes the TourFilterResolver a real resolver 2018-01-11 18:00:42 +11:00
Mike 9f6e6e4701 Add tests to SimilarNodeNameTests to check for null and "" values. 2018-01-10 20:58:10 +00:00
Mike 34ba3f3351 Merge remote-tracking branch 'upstream/dev-v7' into U4-10727 2018-01-10 20:48:28 +00:00
Mike dcfb8b94d8 Refactor SimilarNodeName to account for null nodeName values. 2018-01-10 20:44:30 +00:00
Mads Rasmussen 0876004d9a U4-10803: remove dependency on angular-moment 2018-01-10 16:00:32 +01:00
Stephan d3ad61835a Merge branch 'temp-U4-10789' into dev-v7.8 2018-01-10 15:59:07 +01:00
Stephan ad882ab5be Merge remote-tracking branch 'origin/dev-v7.8' into temp-U4-10789 2018-01-10 15:58:18 +01:00
Stephan 774f333c70 U4-10789 - cleanup + beta003 2018-01-10 15:24:58 +01:00
Robert bba58ea0c0 Replaced all usages of DisposableObject with DisposableObjectSlim 2018-01-10 13:48:55 +01:00
Robert d0d4885812 Created slim version of DisposableObject and fixed some code indentation
DisposableObjectSlim has no finalizer
2018-01-10 13:36:53 +01:00
Claus ce11a377e6 refactor 2018-01-10 11:37:37 +01:00
Claus c6443c477f no need to log when throwing - that gets logged. 2018-01-10 11:13:28 +01:00
Claus eb94572361 updating pr to fit with base. 2018-01-10 10:55:46 +01:00
Claus fd8317493e Merge branch 'dev-v7.8' into temp-U4-10707
# Conflicts:
#	src/Umbraco.Web/Editors/TourController.cs
#	src/Umbraco.Web/Umbraco.Web.csproj
2018-01-10 10:10:19 +01:00
Claus 22ff1bcaa0 Merge pull request #2378 from umbraco/temp-U4-10811
U4-10811 Store custom tours as json and load from App_Plugins/{MyPlug…
2018-01-10 09:46:47 +01:00
Shannon c3be9004f6 U4-10811 Store custom tours as json and load from App_Plugins/{MyPlugin}/backoffice/tours 2018-01-10 16:01:46 +11:00
Shannon 11fa015b64 Merge remote-tracking branch 'origin/dev-v7' into dev-v7.8
# Conflicts:
#	src/SolutionInfo.cs
#	src/Umbraco.Core/Configuration/UmbracoVersion.cs
#	src/Umbraco.Web.UI/Umbraco.Web.UI.csproj
2018-01-10 15:08:10 +11:00
Ian Houghton f5f3676a56 U4-10762 Fix issue with empty name when registering new members from snippet 2018-01-09 15:51:32 +00:00
Mads Rasmussen f69f68e2b5 Merge branch 'temp-U4-10707' of https://github.com/umbraco/Umbraco-CMS into temp-U4-10707 2018-01-09 16:17:07 +01:00
Mads Rasmussen 3858656015 clear tours before registering new tours 2018-01-09 16:15:38 +01:00
Claus a5ec5f46ac filtering out tours. 2018-01-09 15:49:19 +01:00
Mads Rasmussen ea70e18a91 set "Getting Started"-tour group to order 100 so it is possible be add groups before and after 2018-01-09 14:13:27 +01:00
Mads Rasmussen 0cfd5773c3 set groupOrder on group so we don't order the tours in each group 2018-01-09 14:12:33 +01:00
Mads Rasmussen b15def99c7 format as json 2018-01-09 11:53:21 +01:00
Stephan 8c8b6984c2 Merge branch origin/dev-v7.8 into temp-U4-10789 2018-01-09 09:06:01 +01:00
Mike dc7b83ca6c Add initial test fix for SimilarNodeName when a node has no name. 2018-01-08 17:30:11 +00:00
Bjarne Fyrstenborg fcf9dcd803 Fix checkmark tree icon, when custom font icon is used for tree icon, e.g. in UCommerce 2018-01-08 14:40:31 +01:00
Mads Rasmussen 070fa11f8c fixes: U4-10707 Config to order tour groups 2018-01-08 14:11:53 +01:00
Robert 7e9f55f517 Merge pull request #1760 from abjerner/patch-15
LinkPicker overlay: Added property for hiding the target option
2018-01-08 13:11:01 +01:00
Sebastiaan Jansssen 3556043b55 Update to latest modelsbuilder 2018-01-08 12:44:29 +01:00
Shannon 8c70578764 fix tests 2018-01-05 16:22:40 +11:00
Shannon 5cb2dd0036 Makes the features internal 2018-01-05 15:19:16 +11:00
Shannon a9713dc6fc Converts the xslt tree to a controller, ensures all config for trees is correct and transforms for upgrades applied 2018-01-05 13:44:57 +11:00
Shannon b32e7d4ccc running the build changed the bower.json file, i wonder if this will 'fix' vsts? 2018-01-05 10:45:06 +11:00
Shannon 8d4958e395 Changes the user controller saving extensions operation to use events instead 2018-01-05 10:22:46 +11:00
Stephan 9883757704 U4-10739 - cosmetics 2018-01-04 15:34:22 +01:00
Shannon 0310782d7d bumps version 2018-01-05 00:05:16 +11:00
Shannon c81e14758d make sure that the navigation index isn't reset 2018-01-04 22:57:38 +11:00
Shannon 9b33c94437 Merge remote-tracking branch 'origin/dev-v7.8' into temp-U4-10789 2018-01-04 22:23:48 +11:00
Shannon 2a30fd238e Merge branch 'dev-v7' into temp-U4-10789 2018-01-04 22:23:39 +11:00
Shannon 3cb4128c0f Merge branch 'temp-U4-10788' into temp-U4-10789 2018-01-04 22:08:03 +11:00
Claus 79958e0fe0 Merge pull request #2359 from umbraco/temp-u4-10739
U4-10739 - retry logic in physical filesystem
2018-01-04 11:57:36 +01:00
Claus f238f9fcea fixing bugs in retry stuff 2018-01-04 11:54:07 +01:00
Stephan 7c545410cc U4-10739 - retry logic in physical filesystem 2018-01-04 11:54:07 +01:00
Shannon dcf5fff3f0 Merge remote-tracking branch 'origin/dev-v7.8' into temp-U4-10789 2018-01-04 18:51:01 +11:00
Shannon 1dc88658e8 Updates how the user.controller saves a user and instead of using the contentEditingHelper we just call the code ourselves which is actually much simpler. Then once the user is saved we call any extendedSave methods that have been registered. 2018-01-04 18:32:25 +11:00
Warren Buckley e17f75a18a Update client build NPM dependancy for gulp-connect to use 5.0.0 as next/latest version required you to use CoffeeScript to compile their src code to use the module/component 2018-01-03 11:56:39 +00:00
Shannon 88c20c7c5f Allows for disabling of any umbraco based Controller on startup, this also takes into account disabled trees so if they are disabled, they will not be shown 2018-01-03 13:49:36 +11:00
Shannon bd9adffaa5 Converts macro tree to use a proper controller so we can disable it 2018-01-03 13:33:33 +11:00
Shannon 0ce059d5bd U4-10789 Headless User Editor extensibility 2018-01-02 17:28:16 +11:00
Shannon 773ef1d168 Merge branch 'dev-v7' into dev-v7.8
# Conflicts:
#	src/Umbraco.Web.UI.Client/src/views/propertyeditors/mediapicker/mediapicker.html
2018-01-02 15:28:30 +11:00
Shannon 1f7de81cd2 ignore file update 2018-01-02 15:25:42 +11:00
Bjarne Fyrstenborg fef9e3fde0 Ensure placeholder is same height as original rows 2017-12-29 22:49:06 +01:00
Bjarne Fyrstenborg e849d2d0d0 Add required ng-model to ui-sortable 2017-12-29 22:48:14 +01:00
Bjarne Fyrstenborg 9a6123579f Fix collapsed columns in row when sorting 2017-12-29 22:47:29 +01:00
Jan van Helvoort 591a881283 Filtering of Grid Editors
If there are more than 15 items, 5 rows of 3, then show the filter.
2017-12-24 15:48:16 +01:00
Anders Bjerner 1554d52ea9 Triggers the save button to momentarily show an error icon 2017-12-20 21:51:59 +01:00
Shannon 6f55b84c65 removes this. convention 2017-12-18 15:34:15 +11:00
Shannon Deminick 43f369f96f Merge pull request #2306 from Sam7/dev-v7
U4-10453 - Ability to Sync after each external login (using OWIN)
2017-12-18 14:42:25 +11:00
Shannon aed476de0a Merge branch 'dev-v7' into dev-v7.8 2017-12-14 19:26:45 +11:00
Shannon 9e2c7d16a6 Merge branch 'dev-v7' into dev-v7.8 2017-12-14 18:35:34 +11:00
Shannon 680d97c630 Make sure the back office tour files are included in the nuget release 2017-12-14 16:51:48 +11:00
Shannon 89347b359b fixes merge issues with DocumentBlueprint naming 2017-12-14 16:51:13 +11:00
Shannon 8053cea92d Merge branch 'dev-v7' into dev-v7.8
# Conflicts:
#	src/SolutionInfo.cs
#	src/Umbraco.Core/Configuration/UmbracoVersion.cs
#	src/Umbraco.Core/UdiEntityType.cs
#	src/Umbraco.Core/Umbraco.Core.csproj
#	src/Umbraco.Web.UI/Umbraco.Web.UI.csproj
#	src/umbraco.cms/umbraco.cms.csproj
2017-12-14 16:24:25 +11:00
Claus ae07f34215 seems this was missing from the merge commit? 2017-12-13 09:53:38 +01:00
Søren Gregersen 50335723b0 Fix for U4-10733 2017-12-06 10:09:40 +01:00
Mikkel Holck Madsen 6f1bd3fd71 Merge pull request #2341 from umbraco/temp-U4-10610-v78
U4-10610 Cannot restore content templates - v7.8
2017-12-05 13:48:16 +01:00
Claus 91e658c41c U4-10610 Cannot restore content templates 2017-12-05 10:37:23 +01:00
Warren Buckley 6939cc757e Merge pull request #2333 from umbraco/temp-U4-10670
fixes: U4-10670 7.8. Visual indication on the info-tab or page in whi…
2017-11-24 13:46:50 +00:00
Mads Rasmussen 2baec8a129 fixes: U4-10704 Restore Node - After restoring the restore button still stays 2017-11-24 13:26:54 +01:00
Mads Rasmussen 93a1fc1eba fixes: U4-10670 7.8. Visual indication on the info-tab or page in which state a page is 2017-11-24 11:32:34 +01:00
Mads Rasmussen 5d694a73a3 Merge pull request #2330 from umbraco/temp-U4-10312
Temp u4 10312
2017-11-22 12:42:06 +01:00
Mads Rasmussen af369fa6c7 when scrolling position element in the center of the scroll container 2017-11-21 21:40:22 +01:00
Mads Rasmussen 901036535d fix scrolling in document type 2017-11-21 21:39:58 +01:00
Mads Rasmussen 5d6cbee196 rename data attribute for editor container 2017-11-21 21:39:34 +01:00
Mads Rasmussen 9e9ae09ec2 add data attributes 2017-11-21 21:38:48 +01:00
Karl Tynan 58697eaa04 Merge pull request #1 from karltynan/karltynan-patch-1
Added small to allowed TinyMCE valid elements
2017-11-21 15:20:06 +00:00
Karl Tynan ce58ad91b5 Added `small` to allowed TinyMCE valid elements
We use ``small`` a lot in the RTE, and ``small`` is now considered a really useful tag in HTML5. I would like to see this in the default valid elements list for people to use out-of-the box.
2017-11-21 15:18:42 +00:00
Warren Buckley e49d14d687 Merge pull request #2325 from umbraco/temp-U4-10666
fixes: U4-10666 Publish nodes in the recycle bin
2017-11-21 13:57:55 +00:00
Mads Rasmussen e010ff2a8c fixes: U4-10663 7.8 - Save and Publish button styling - Firefox 2017-11-20 13:51:37 +01:00
Mads Rasmussen 00cec3267c Merge pull request #2318 from abjerner/patch-24
New Danish translation for "Dato for Fortryd udgivelse"
2017-11-16 12:07:01 +01:00
Mads Rasmussen 4bfb2d219b Merge branch 'dev-v7' into dev-v7.8
# Conflicts:
#	src/SolutionInfo.cs
#	src/Umbraco.Core/Configuration/UmbracoVersion.cs
#	src/Umbraco.Web.UI/Umbraco.Web.UI.csproj
2017-11-16 12:01:26 +01:00
Mads Rasmussen 80c61110df make sure you can't restore to items already in the recycle bin 2017-11-15 15:13:58 +01:00
Mads Rasmussen 8e47f91ba5 show "restore"-button instead of "save and publish"-button for trashed items 2017-11-15 13:36:10 +01:00
Mads Rasmussen 31f6bd4c02 fixes: U4-10665 7.8 - Log info on two lines is a bit off 2017-11-14 15:57:13 +01:00
Mads Rasmussen 3e5744dbb7 fixes: U4-10663 7.8 - Save and Publish button styling - Firefox 2017-11-14 13:38:18 +01:00
Mads Rasmussen cb0d8320e6 rename parameter 2017-11-14 10:47:34 +01:00
Mads Rasmussen 53d9b65e64 Merge branch 'dev-v7.8' into patch-27 2017-11-14 09:54:08 +01:00
Mads Rasmussen df0fe62fca Merge branch 'dev-v7.8' into patch-27 2017-11-14 09:50:05 +01:00
Mads Rasmussen 483a2c7c02 Merge pull request #2320 from abjerner/patch-26
"by" in the new Info tab is now localized
2017-11-13 15:44:17 +01:00
Mads Rasmussen 084fde885a Merge pull request #2319 from abjerner/patch-25
"Set date" and "Clear date" in the new Info tab can now be localized
2017-11-13 15:34:30 +01:00
Mads Rasmussen 50a5679b5c Merge pull request #2316 from abjerner/patch-22
Added Danish translations for the new "History" and "Scheduled Publishing" headers
2017-11-13 15:24:19 +01:00
Anders Bjerner 2c248791e1 Added Danish translation for "content_noChanges" 2017-11-13 15:05:20 +01:00
Mads Rasmussen 6b6a7fe231 Merge branch 'dev-v7' into dev-v7.8 2017-11-13 14:47:52 +01:00
Mads Rasmussen 6fd197d1bf fixes: U4-10667 7.8 Item not published is still a hyperlink 2017-11-13 13:32:03 +01:00
Anders Bjerner 00aa59c9c6 Dates in the "History" box is now also localized (1/2) 2017-11-11 20:15:27 +01:00
Anders Bjerner 06254ba462 Dates in the "History" box are now also localized (1/2) 2017-11-11 20:14:45 +01:00
Anders Bjerner 684cb19a7c Localized dates for the new "Info" tab 2017-11-11 19:57:11 +01:00
Anders Bjerner 9c5da12653 Updated the "umbContentNodeInfo" directive with localized dates 2017-11-11 19:53:48 +01:00
Anders Bjerner 83f229abc6 "by" in the new Info tab is now localized 2017-11-11 18:45:37 +01:00
Anders Bjerner 3405a1f600 Added Danish translation for "content_setDate" 2017-11-11 18:27:55 +01:00
Anders Bjerner 8be02ff7b0 Added English (US) translation for "content_setDate" 2017-11-11 18:26:41 +01:00
Anders Bjerner c371f00315 Added English translation for "content_setDate" 2017-11-11 18:25:57 +01:00
Anders Bjerner 0ccf798f14 "Set date" and "Clear date" in the new Info tab can now be localized 2017-11-11 18:23:47 +01:00
Anders Bjerner 6ca94074f3 And here as well 2017-11-11 17:40:49 +01:00
Anders Bjerner 8236eee7a6 And while we're at it... 2017-11-11 17:36:13 +01:00
Anders Bjerner 8bdeca6374 On second thought, this may be even better 2017-11-11 17:28:40 +01:00
Anders Bjerner e37bbdfcf4 New Danish translation for "Dato for Fortryd udgivelse" 2017-11-11 17:18:44 +01:00
Anders Bjerner dac882ce9f Added Danish translations for the new "History" and "Scheduled Publishing" headers 2017-11-11 17:10:25 +01:00
Shannon 2dc11f6fa1 Fixes new installation user login 2017-11-09 23:05:56 +11:00
Shannon fe2e689865 Merge branch 'dev-v7.8' of https://github.com/umbraco/Umbraco-CMS into dev-v7.8 2017-11-09 22:15:22 +11:00
Shannon ece5fecf12 fixes doc type conflict name so the tour uses "My Home Page" 2017-11-09 22:15:05 +11:00
Mads Rasmussen b21dea84d9 remove markup from tour step title 2017-11-08 15:38:15 +01:00
Shannon 492b0aadc8 ensure that the user login table is created 2017-11-09 01:14:00 +11:00
Shannon b399630202 bumps version 2017-11-09 01:02:09 +11:00
Shannon b9b1fc3a70 Adds a global config switch to enable/disable tours entirely 2017-11-09 00:57:05 +11:00
Shannon 1d52f59657 Puts tours on the file system and loads them from an api controller 2017-11-09 00:41:59 +11:00
Shannon 78f6b8d8bc Fixes up more the the session id validation, makes sure that the GetUserSecondsMiddleWare also validates the session since this is what keeps the user logged in if that option is being used. 2017-11-08 23:57:17 +11:00
Shannon 0afee71e9e Fixes locking issue with SessionIdValidator which was forcing a log out in some cases 2017-11-08 22:15:00 +11:00
Shannon ffa7b922e8 Merge branch 'dev-v7' into dev-v7.8 2017-11-08 19:48:34 +11:00
Shannon e6de9e0004 Merge branch 'dev-v7' into dev-v7.8 2017-11-08 19:25:22 +11:00
Shannon 08aff2654a updates installer image 2017-11-08 15:51:14 +11:00
Shannon Deminick cd0fdae47b Merge pull request #2254 from umbraco/temp-U4-10305
U4-10305 Back office Tour
2017-11-08 14:52:55 +11:00
Shannon 0f3a76809b Merge branch 'dev-v7.8' into temp-U4-10305
# Conflicts:
#	src/Umbraco.Core/Umbraco.Core.csproj
#	src/Umbraco.Web.UI.Client/src/common/directives/components/tree/umbtreeitem.directive.js
2017-11-08 14:52:21 +11:00
Shannon 4f88da2c26 Merge branch 'dev-v7' into dev-v7.8
# Conflicts:
#	src/Umbraco.Web.UI/umbraco/config/lang/en_us.xml
#	src/Umbraco.Web/Models/Mapping/TabsAndPropertiesResolver.cs
2017-11-08 14:51:27 +11:00
Mads Rasmussen 4ce0553630 add allowDisable flag on welcome tour 2017-11-07 14:53:44 +01:00
Mads Rasmussen b1b285b673 Merge pull request #2269 from umbraco/temp-tour-review-rune
Temp tour review rune - Introduction
2017-11-07 14:46:56 +01:00
Mads Rasmussen c773714e2d fix folder name validation 2017-11-07 14:11:57 +01:00
Mads Rasmussen 2a90478ba7 fixing typos and the properties tab 2017-11-07 14:00:39 +01:00
Matt Darby 77162e4b51 Move val-email attribute before required attribute 2017-11-07 19:17:42 +07:00
Rune Hem Strand 93756a62f4 Update popover width 2017-11-07 11:37:23 +01:00
Rune Hem Strand 2343004be1 Manual merge to init.js tour steps 2017-11-07 11:30:21 +01:00
Rune Hem Strand d6fe350a4a Merge branch temp-U4-10305 into temp-tour-review-rune 2017-11-07 11:28:26 +01:00
Warren Buckley 23321f8ac9 Merge pull request #2265 from umbraco/temp-U4-10544
fixes: U4-10544 SPIKE: Register tours
2017-11-07 10:23:58 +00:00
Rune Hem Strand 71902f3b9b Update Media library tour 2017-11-07 10:53:02 +01:00
Rune Hem Strand 13b544521d Update Media library tour 2017-11-07 10:52:39 +01:00
Rune Hem Strand 2cf8c1207d Update View Home Page step 2017-11-07 10:34:24 +01:00
Mads Rasmussen ab8653d3de manual merging 2017-11-06 14:26:55 +01:00
Mads Rasmussen 748a3c167e Merge branch 'temp-U4-10305' into temp-U4-10544
# Conflicts:
#	src/Umbraco.Web.UI.Client/src/common/services/tour.service.js
#	src/Umbraco.Web.UI.Client/src/views/dashboard/dashboard.tabs.controller.js
2017-11-06 13:58:07 +01:00
Mads Rasmussen 5b93b35882 Show "Other" as group title instead of "undefined" 2017-11-06 13:17:31 +01:00
Mads Rasmussen b29ee4df60 don't render tour markup if no tours are registered 2017-11-06 13:16:53 +01:00
Mads Rasmussen d8fe3c6faf adds basic validation to registering and starting tours 2017-11-06 13:09:16 +01:00
Sam Sperling 9260f943ff Merge branch 'dev-v7' of https://github.com/umbraco/Umbraco-CMS into HEAD 2017-11-06 15:35:19 +11:00
Sam Sperling dcdaa8d62d U4-10453 - Ability to Sync after each external login (using OWIN)
Added a new function OnExternalLogin for the ExternalSignInAutoLinkOptions to enable full syncing capabilities for external logins
2017-11-06 15:31:36 +11:00
Robert 9b7a9fc988 Merge remote-tracking branch 'origin/temp-U4-5896-2' into dev-v7.8 2017-11-03 15:38:08 +01:00
Claus 62485157ad Merge pull request #2270 from umbraco/temp-U4-10286
New cmsMedia database table to track media by media paths for fast lookups
2017-11-03 14:19:06 +01:00
Claus 4ce7b089ca cleanup... 2017-11-03 14:16:24 +01:00
Claus 9e91098ebd adding cmsMedia to the empty recyclebin query. 2017-11-03 14:15:54 +01:00
Claus 49356b31a1 Merge branch 'dev-v7.8' into temp-U4-10286
# Conflicts:
#	src/Umbraco.Core/Umbraco.Core.csproj
2017-11-03 14:08:46 +01:00
Robert 507c2353e9 Merge pull request #2274 from umbraco/temp-U4-10150
U4-10150 Process load balancing instructions on a background thread i…
2017-11-03 11:43:02 +01:00
Robert d02139bbcd Merge pull request #2273 from umbraco/temp-U4-9120
U4-9120 Add instruction count column on the db instructions table
2017-11-03 10:20:57 +01:00
Shannon 8a19b97900 removes unneeded mapping 2017-11-03 18:23:56 +11:00
Shannon 981fad1ec8 fixes test 2017-11-03 18:20:41 +11:00
Shannon 019147c1a1 Moves the session generation to the BackOfficeCookieAuthenticationProvider which is where it should be, so it only gets generated before the cookie is written. Writes the checking cookie inside of a lock to prevent multiple db and cookie writes that are unecessary. 2017-11-03 18:07:17 +11:00
Shannon 782d6100f0 Gets user session management tracking via the database including detecting stale sessions, generating and removing them along with cleaning them up. This takes into account legacy code too. The session is revalidated on a one minute threshold per user so that it's not hammering the databse on every request. 2017-11-03 17:27:23 +11:00
Robert e17690fbed Merge branch 'temp-U4-10601' into temp-U4-10305 2017-11-02 14:41:33 +01:00
Rune Hem Strand d7d1b3f2a0 Update template tour 2017-11-02 12:06:42 +01:00
Shannon 5b19d5e0d8 WIP on login ids 2017-11-02 15:04:54 +11:00
Claus 7c21889239 fixing comment causing confusion. 2017-11-01 19:41:50 +01:00
Rune Hem Strand 52d35c06eb Update tour validation to use valid JS 2017-11-01 17:36:49 +01:00
Rune Hem Strand 52c3ea24d5 Update validation in Create Content tour 2017-11-01 17:34:34 +01:00
Rune Hem Strand 03756ab894 Update Create Content Tour 2017-11-01 17:23:15 +01:00
Mads Rasmussen 8e35d904cb fixes: U4-10617 Update tour to work with new info tab 2017-11-01 13:28:44 +01:00
Rune Hem Strand 9808492509 Update validation on Create Content tour 2017-11-01 11:18:46 +01:00
Rune Hem Strand 81788338e3 Update Create content tour 2017-11-01 11:17:26 +01:00
Mads Rasmussen 3ffe1517e0 Merge pull request #2268 from umbraco/temp-U4-10597
U4-10597 Add attention to clickable element If it isn't clicked
2017-11-01 10:30:11 +01:00
Mads Rasmussen 641e74b747 Lower highlight pulse timeout to 1 sec 2017-11-01 10:20:14 +01:00
Claus 49c316e13d Merge pull request #2066 from arknu/U4-10191-tinymce46
U4-10191: Update to TinyMCE 4.6.x
2017-11-01 09:42:33 +01:00
Claus 5235053523 updating to latest tinymce 2017-11-01 09:27:04 +01:00
Shannon af6d2df823 Fixes % calc for tours since it now requires a promise 2017-11-01 15:54:47 +11:00
Shannon bbe80d882a Simplifies user tour models returned, fixes mapping so it's actually persisted. 2017-11-01 15:45:48 +11:00
Shannon 408ec17201 Merge branch 'temp-U4-10305' into temp-U4-10601 2017-11-01 15:25:50 +11:00
Shannon a4ef487fab Merge branch 'dev-v7.8' into temp-U4-10305
# Conflicts:
#	src/Umbraco.Web.UI.Client/src/less/belle.less
#	src/Umbraco.Web.UI.Client/src/views/components/content/edit.html
#	src/Umbraco.Web.UI.Client/src/views/media/edit.html
2017-11-01 15:24:49 +11:00
Shannon 8208f8de51 Updates codebase to store tour data for a user in the user table, adds new column to store json and adds migration to create the column 2017-11-01 15:11:13 +11:00
Shannon Deminick e8ea7f9d29 Merge pull request #2264 from umbraco/temp-U4-10542
fixes: U4-10542 Fix SVG backdrop bugs in Firefox (maybe other browser…
2017-11-01 13:13:00 +11:00
Shannon Deminick e431a41fc1 Merge pull request #2276 from umbraco/temp-U4-10599
U4-10599 Move "End tour"-button to another position
2017-11-01 12:08:43 +11:00
Mads Rasmussen 1f5c9d2e1b fixes: U4-10590 Saving a document with no tabs throws a javascript error 2017-10-31 14:12:40 +01:00
Rune Hem Strand 372f981d33 Lower Case name validation 2017-10-31 12:05:49 +01:00
Rune Hem Strand 6f03e221c6 Update Create Document Type tour 2017-10-31 12:03:39 +01:00
Rune Hem Strand 90a5adec8f Update Add a property step 2017-10-31 11:45:55 +01:00
Rune Hem Strand 62939385a0 Update Name the tab step 2017-10-31 11:42:41 +01:00
Mads Rasmussen d4729e1483 set highlight pulse timeout to 2 seconds 2017-10-31 11:38:45 +01:00
Rune Hem Strand 9de35f0202 Updated Document Type name to Home Page 2017-10-31 11:35:38 +01:00
Mads Rasmussen 773d249d36 fixes: U4-10600 Add "Don't show this tour again" option 2017-10-31 10:59:13 +01:00
Rune Hem Strand d12a492cb6 Update Create Document Type step 2017-10-31 10:40:03 +01:00
Rune Hem Strand ef0b521083 Update Create document type step 2017-10-31 10:38:46 +01:00
Rune Hem Strand 6261447923 Update Create document type step 2017-10-31 10:34:50 +01:00
Rune Hem Strand d18881c8ad Update Navigate to the Settings sections step 2017-10-31 10:29:23 +01:00
Rune Hem Strand 89596dbe0b Update Create your first Document Type step 2017-10-31 10:27:59 +01:00
Mads Rasmussen 358536ffaa fixes: U4-10599 Move "End tour"-button to another position 2017-10-31 10:20:24 +01:00
Mads Rasmussen 4592f8e8d8 Send app.ready event after tour is ready 2017-10-31 10:03:11 +01:00
Shannon 0038d173a2 U4-10150 Process load balancing instructions on a background thread instead of a request thread 2017-10-31 15:11:45 +11:00
Shannon 68e6ad76fb Make sure the count of instructions takes into account individual ids when using RefreshByIds 2017-10-31 12:39:08 +11:00
Shannon 6462329494 U4-9120 Add instruction count column on the db instructions table 2017-10-31 11:54:08 +11:00
Shannon 2fdd1c0bd2 bump version 2017-10-31 11:52:43 +11:00
Shannon 891bea81bf bumps version and updates DatabaseSchemaResult to check for cmsMedia table, fixes the bulk insert logic to ignore result columns 2017-10-31 11:20:01 +11:00
Shannon f71577f86e Adds data migrations for media path table 2017-10-31 11:20:01 +11:00
Shannon e3e88b3679 Gets the media path being stored in the db, the column is indexed and so is the property type alias, tests are passing for the lookup 2017-10-31 11:20:01 +11:00
Shannon 5dc993890d New cmsMedia database table to track media by media paths for fast lookups 2017-10-31 11:20:01 +11:00
Shannon a2025c14b1 Merge branch 'dev-v7' into dev-v7.8
# Conflicts:
#	src/Umbraco.Core/Umbraco.Core.csproj
2017-10-31 11:18:52 +11:00
Zsolt 34f811c128 Small alignment bug fix 2017-10-30 11:20:37 +01:00
Mads Rasmussen 7e4c284abb U4-10597 Add attention to clickable element If it isn't clicked 2017-10-30 10:45:38 +01:00
Mads Rasmussen 664d0c5160 add folder name validation in media section tour 2017-10-27 15:14:09 +02:00
Rune Hem Strand eb26fb901f Update User profile step 2017-10-27 14:41:26 +02:00
Rune Hem Strand 3141b04376 Update User profile step 2017-10-27 14:39:30 +02:00
Rune Hem Strand 201fb5dc01 Update Tree step 2017-10-27 14:38:11 +02:00
Rune Hem Strand 15e668c056 Update Search step 2017-10-27 14:24:28 +02:00
Rune Hem Strand a42f425971 Update dashboard step 2017-10-27 14:23:29 +02:00
Rune Hem Strand 3f4774855e Update tree step 2017-10-27 14:21:46 +02:00
Rune Hem Strand 28f995cea6 Add main menu step 2017-10-27 14:06:48 +02:00
Rune Hem Strand cfb14d7089 Adds info on how to acces the help drawer. 2017-10-27 13:53:17 +02:00
Mads Rasmussen ef4d41c80a fix type 2017-10-27 10:12:48 +02:00
Mads Rasmussen 584e47f51f update docs 2017-10-27 10:10:34 +02:00
Mads Rasmussen 66e40fcbb0 Merge branch 'temp-U4-10305' into temp-U4-10544
# Conflicts:
#	src/Umbraco.Web.UI.Client/src/common/services/tour.service.js
2017-10-27 10:08:04 +02:00
Mads Rasmussen 4ed236249a Merge pull request #2267 from umbraco/temp-U4-10550
U4-10550 Finalise tour layout in the drawer
2017-10-26 21:28:01 +02:00
Mads Rasmussen 00a4287945 add back class 2017-10-26 21:24:16 +02:00
Mads Rasmussen 92d52bf99b clean up list + remove unused files 2017-10-26 21:14:22 +02:00
Mads Rasmussen 2e611c20d4 fix text positioning in Firefox 2017-10-26 20:35:04 +02:00
Mads Rasmussen ae10f3d21f calculate progress circle font size instead of manually setting it + align colors 2017-10-26 20:10:22 +02:00
Mads Rasmussen 7a9b392f69 add validation to document type tab name 2017-10-26 15:57:00 +02:00
Mads Rasmussen 493d71dba9 open matching tour group if a tour is running 2017-10-26 15:41:43 +02:00
Mads Rasmussen 55d4e4072a add steps for dashboard and tours 2017-10-26 15:39:56 +02:00
Mads Rasmussen f687b34c14 add data elements to editor content 2017-10-26 15:36:45 +02:00
Mads Rasmussen 507517c1ad add data-elements to help drawer 2017-10-26 15:36:18 +02:00
Mads Rasmussen ae8cfb2b23 add getCurrentTour to tour.service 2017-10-26 15:35:46 +02:00
Mads Rasmussen 9048252826 make start tour button green 2017-10-26 14:20:11 +02:00
Zsolt e76819a570 Merge remote-tracking branch 'origin/temp-U4-10550' into temp-U4-10550 2017-10-26 12:58:50 +02:00
Zsolt 87c311d6e7 Fixing the hover on the groups 2017-10-26 12:58:36 +02:00
Mads Rasmussen 86d8eae984 remove unused code 2017-10-26 12:53:23 +02:00
Mads Rasmussen 6aac216763 update tour list when one is completed 2017-10-26 12:50:46 +02:00
Mads Rasmussen b7c3fb7f30 set text position in progress circle with css instead of js 2017-10-26 12:49:36 +02:00
Zsolt a0a3b7e9c9 Changing the css of umbProgressCircle 2017-10-26 12:02:46 +02:00
Mads Rasmussen d98db5e6bc updates to tour layout in drawer 2017-10-26 11:39:49 +02:00
Mads Rasmussen 48adc4c98d only load the getting started tours if the Get started dashboard is installed 2017-10-26 10:18:44 +02:00
Mads Rasmussen 79d4562cb1 fixes: U4-10544 SPIKE: Register tours 2017-10-25 21:59:37 +02:00
Mads Rasmussen f48263e5a2 fixes: U4-10542 Fix SVG backdrop bugs in Firefox (maybe other browser too?) 2017-10-25 20:24:04 +02:00
Mads Rasmussen 63196d7e53 Merge branch 'temp-U4-10305' into temp-U4-10550
# Conflicts:
#	src/Umbraco.Web.UI.Client/src/common/services/tour.service.js
2017-10-25 17:02:46 +02:00
Claus 72a0d614af Merge pull request #2261 from umbraco/temp-U4-10565
U4-10565 Add introduction tour to the overall Umbraco UI
2017-10-25 14:47:22 +02:00
Zsolt 4f8bb7fb51 Adding new components to the help drawer 2017-10-25 12:48:34 +02:00
Claus 1c883be16b Merge remote-tracking branch 'origin/temp-u4-8409' into dev-v7.8 2017-10-25 12:27:34 +02:00
Claus 73d681d674 Merge remote-tracking branch 'origin/dev-v7' into dev-v7.8
# Conflicts:
#	src/Umbraco.Web/Models/Mapping/ContentModelMapper.cs
2017-10-25 11:52:30 +02:00
Zsolt 8daa558997 Revert "adding components to the drawer"
This reverts commit b78fd0f6ac.
2017-10-25 11:46:52 +02:00
Zsolt b78fd0f6ac adding components to the drawer 2017-10-25 11:19:53 +02:00
Mads Rasmussen 831eb3ef5e add icon for link to document for better clarification 2017-10-24 15:17:14 +02:00
Claus fa68bee762 removing left over using statements and references to SharpZipLib. 2017-10-24 15:16:12 +02:00
Mads Rasmussen 796700b4fe fix end tour in custom step 2017-10-24 15:05:20 +02:00
Mads Rasmussen ab09042fdc add options to prevent click in backdrop highlighted area 2017-10-24 15:00:14 +02:00
Mads Rasmussen 041d4a4a8b fix issue in create media dialog where it sometimes refreshes whole page 2017-10-24 13:54:36 +02:00
Mads Rasmussen ee79d7ecdc add custom backdrop opacity to tour steps 2017-10-24 13:35:26 +02:00
Mads Rasmussen e33456d168 add alias to document type save button 2017-10-24 11:46:51 +02:00
Mads Rasmussen df2c104002 remove console.log 2017-10-23 20:15:48 +02:00
Mads Rasmussen f265fa683c don't use index in button group + update text in some tours 2017-10-23 19:58:44 +02:00
Mads Rasmussen 12093ae7ea fix tour steps with ng-if 2017-10-23 09:50:14 +02:00
pijemcolu 6a980e64eb zipPackage to disk 2017-10-23 09:02:28 +02:00
Mads Rasmussen 37071ada78 restyle step loader, fade in steps, fix custom view step positionen 2017-10-19 21:17:26 +02:00
pijemcolu 3c7e820773 remove the directory check 2017-10-19 19:50:27 +02:00
Mads Rasmussen 203837aa84 start intro tour on load (if it hasn't been completed) 2017-10-19 16:01:20 +02:00
Mads Rasmussen 5fe63c2c1a fix lost element header 2017-10-19 14:27:00 +02:00
pijemcolu 2c1d85989f Extract the zip in UnPack(), remove check for directory exists as it should not and that's what the method did previously 2017-10-19 13:14:06 +02:00
Mads Rasmussen d518ab908e add intro/outro step logic, start on intro tour, testing intro steps 2017-10-19 13:11:10 +02:00
pijemcolu bc32ff31d4 remove last 3 dependencies 2017-10-19 12:11:07 +02:00
Mads Rasmussen 7804677f2b use name instead of alias in editor picker element attribute because there can be many editors with the same alias 2017-10-19 11:41:12 +02:00
Mads Rasmussen 27c884f4eb add more data elements for navigating the UI 2017-10-19 09:10:13 +02:00
Mads Rasmussen a966f63bbd Merge pull request #2244 from umbraco/temp-U4-10541
fixes: U4-10541 Use local storage to store completed tours
2017-10-18 11:25:51 +02:00
Mads Rasmussen 76f9e6baee fix bug in step validation 2017-10-18 10:26:50 +02:00
Mads Rasmussen 49f17be9df fixes: U4-10540 Make it possible to run custom logic for a tour step 2017-10-18 08:46:13 +02:00
Stephan 8a114a105e U4-8409 - reduce sharpZipLib dependencies 2017-10-16 19:03:05 +02:00
Warren Buckley 5f9865cc73 Merge pull request #2228 from umbraco/temp-U4-10309
fixes: MBOGA: Redesign the properties tab
2017-10-16 14:57:45 +01:00
Mads Rasmussen b891b18b20 fixes: U4-10541 Use local storage to store completed tours 2017-10-16 13:52:34 +02:00
Mads Rasmussen bc461b1646 change id's to custom attr 2017-10-16 13:46:03 +02:00
Mads Rasmussen b0eeaecf1c remove unused files 2017-10-16 13:41:02 +02:00
Mads Rasmussen 2708f11fcd fix path to angular moment 2017-10-16 12:01:19 +02:00
Mads Rasmussen c59ac4ee0e moved tours from dashboard to service, option to group tours, added functions to get tours from service 2017-10-13 12:29:44 +02:00
Warren Buckley a03aa9cbab Fix in PowerShell build - The 7Zip tool download was giving two paths & thus break the build script 2017-10-13 11:20:45 +01:00
Zsolt 89b714c960 Merge remote-tracking branch 'origin/dev-v7.8' into temp-U4-10305 2017-10-12 10:15:22 +02:00
Mads Rasmussen d9b0b0112e fix upload step in tour 2017-10-12 09:53:41 +02:00
Mads Rasmussen 6640039cdf clean up tours + small fixes 2017-10-11 19:37:14 +02:00
Warren Buckley 70deffd418 Merge pull request #2235 from umbraco/temp-U4-10051
U4-10051 - Help Drawer in prep for Lessons
2017-10-11 14:51:01 +01:00
Mads Rasmussen f31d5b12da add null check to back drop element - fix js errors 2017-10-10 21:09:08 +02:00
Warren Buckley 7fd6155807 Bit too aggressive with the C# cleanup - adds back in HelpController but just with the method that is needed to load the videos in the help section 2017-10-10 16:05:21 +01:00
Warren Buckley 043c677ddc Merge branch 'dev-v7.8' into temp-U4-10051
# Conflicts:
#	src/Umbraco.Web.UI.Client/src/less/components/overlays/umb-overlay-backdrop.less
2017-10-10 13:09:06 +01:00
Warren Buckley f634d9f8b1 Remove the Help/Lessons Controller from the globaly Umbraco.Sys JS object 2017-10-10 12:53:15 +01:00
Warren Buckley db637d9c31 Remove HelpController for Lessons as we lift & shift it over to StarterKit 2017-10-10 12:20:11 +01:00
Mads Rasmussen 24b521881c also prevent clicks inside umb-tour component 2017-10-10 12:22:30 +02:00
Mads Rasmussen 0b3a38ec8f add option to disable all events on backdrop click to prevent dialogs, overlays, etc. form closing 2017-10-10 12:14:10 +02:00
Mads Rasmussen 330673bef9 Clear step custom view if none is set 2017-10-10 09:22:57 +02:00
Mads Rasmussen 661ff0e726 add drop shadow to popover 2017-10-09 21:42:06 +02:00
Mads Rasmussen e1c45fda9a compress the popover a bit more 2017-10-09 21:41:37 +02:00
Mads Rasmussen b45a4a18f2 make backdrop a little lighter 2017-10-09 21:41:14 +02:00
Zsolt 1456e7028a Merge remote-tracking branch 'origin/temp-U4-10305' into temp-U4-10305 2017-10-09 11:41:11 +02:00
Zsolt b38ee33e5a Fixing popover orientation so it is not off-screen 2017-10-09 11:40:57 +02:00
Mads Rasmussen 903a9f93c3 clean up backdrop component 2017-10-09 10:56:11 +02:00
Robert b08376651a Merge pull request #2225 from umbraco/temp-U4-10473
Moved documentType and mediaLink to root node for media section
2017-10-09 10:54:51 +02:00
Robert 75514c7c42 Changed angular to make sure the values are matching 2017-10-09 10:43:03 +02:00
Mads Rasmussen ea6f561c96 move backdrop to its own component 2017-10-09 10:19:49 +02:00
Shannon 053544a578 Changes the type of MediaItemDisplay.ContentType to be what it should be, removes non-required mapping 2017-10-09 15:02:27 +11:00
Zsolt 4308718c88 adedd positioning to the popover div 2017-10-06 14:46:27 +02:00
Mads Rasmussen 1b59ca0412 remove unused code 2017-10-06 11:11:52 +02:00
Mads Rasmussen 282cc0c722 testing scrolling, custom html in content and custom step views 2017-10-06 10:14:33 +02:00
Mads Rasmussen 4584abaa72 add a bunch of element navigation attributes 2017-10-05 13:42:51 +02:00
Zsolt c1ca0c9c2f Merge remote-tracking branch 'origin/temp-U4-10305' into temp-U4-10305 2017-10-04 15:20:15 +02:00
Zsolt 27c260cd03 Sticking the popoup to the highlight 2017-10-04 15:18:20 +02:00
Mads Rasmussen 73a5c55547 add data attribute to tree-item-options 2017-10-04 15:12:50 +02:00
Mads Rasmussen b8831c253e testing different tours 2017-10-04 15:09:26 +02:00
Zsolt b2d3e75566 rounding X and Y coordinate values for SVG 2017-10-04 13:12:53 +02:00
Zsolt cb526170e2 Merge remote-tracking branch 'origin/temp-U4-10305' into temp-U4-10305 2017-10-04 13:03:29 +02:00
Zsolt 93237bfdb8 Style of the Guided tour CSS + HTML 2017-10-04 13:03:24 +02:00
Mads Rasmussen 1c39c741b6 get outerWidth and outerHeight 2017-10-04 13:01:33 +02:00
Mads Rasmussen ec2589f517 add global data attribute to all main editors 2017-10-04 11:35:30 +02:00
Zsolt 2ca6e8be9a Implemented SVG backdrop 2017-10-04 11:17:44 +02:00
Mads Rasmussen b9d1a776cb init tour component 2017-10-04 09:19:33 +02:00
Robert 5eb609d8a0 Renamed a few properties and a class 2017-10-03 15:35:36 +02:00
Mads Rasmussen 4d5069726b Update client side unit tests 2017-09-29 10:44:18 +02:00
Mads Rasmussen 0da8644e77 Merge branch 'dev-v7' into temp-U4-10309 2017-09-29 09:55:32 +02:00
Robert e643189b10 Moved mediaLink mapping directly to autoMapper 2017-09-28 16:07:16 +02:00
Robert 97716d5570 Merge pull request #2205 from umbraco/temp-U4-10420
added event to load audit trail on Properties tab only
2017-09-28 15:32:19 +02:00
Robert 5517252200 Moved documentType and mediaLink to root node for media section
Created Map in MediaModelMapper to cater for the new property (DocumentType)
Wired front-end to match the new properties
2017-09-28 15:21:04 +02:00
Mads Rasmussen 92a5c31ce6 remove publish date in footer 2017-09-28 13:55:11 +02:00
Mads Rasmussen 345c038e8b make sure we don't have unwanted markup in the dom 2017-09-28 10:41:08 +02:00
Mads Rasmussen 59defa6b11 rename event to follow naming convention, fix missing tab id, change so the tab id matches the new "info"-tab 2017-09-28 10:12:01 +02:00
Mads Rasmussen 7e0d7ebbd4 Merge branch 'temp-U4-10309' into temp-U4-10420 2017-09-28 10:03:19 +02:00
Robert c13d4ed235 Merge pull request #2218 from umbraco/temp-U4-10421
fixes: U4-10421 Split up properties tab: One for umbraco properties a…
2017-09-28 09:55:55 +02:00
Robert a47b5035fe Merge pull request #2219 from umbraco/temp-U4-10311
U4-10311 Wire up angular with backend
2017-09-28 09:10:02 +02:00
Shannon f6be389f4f fixes tests 2017-09-28 16:13:50 +10:00
Shannon 252f0fe88e Fixes up the angular side of things to ensure the right property values are wired together correctly 2017-09-28 15:13:33 +10:00
Shannon 387faca71e Simplifies the model mapping, uses strongly typed values 2017-09-28 14:54:18 +10:00
Kevin Giszewski 6c172702be Fix for U4-6309 2017-09-27 11:32:36 -04:00
Robert 62cda02ded Some clean up in ContentModelMapper.cs 2017-09-27 16:02:32 +02:00
Mads Rasmussen 3e2a6424bd wire up audit trail log type colors 2017-09-27 14:08:29 +02:00
Mads Rasmussen c0f695bcf9 make grunt linter happy 2017-09-27 14:07:47 +02:00
Robert 2e1e2e4325 Properties tab will be removed if it has no properties 2017-09-27 13:58:33 +02:00
Mads Rasmussen 1316bb5d5b fixes: U4-10421 Split up properties tab: One for umbraco properties and one for user added properties 2017-09-27 12:56:43 +02:00
Robert fe97860694 Changed dataFormatter to work with values from the root node instead of values from properties tab 2017-09-27 11:56:11 +02:00
Robert 98b4aa6bae Cleared more of the not needed code 2017-09-27 10:56:45 +02:00
Robert eb7f4e74f2 Removed unused code as we dont have those properties in the properties tab anymore 2017-09-27 09:31:31 +02:00
Robert 4a9e326267 Remove the rest of umb properties 2017-09-27 09:28:51 +02:00
Robert 67edc6cf9a Deleted updateDate, createDate and createdBy from properties tab 2017-09-26 15:57:50 +02:00
Robert e740838ef7 Moved template and docType from properties tab to root node and linked the values back together in front-end 2017-09-26 15:44:41 +02:00
Robert dec44b1288 Moved templateConfig to root node 2017-09-26 09:20:38 +02:00
Sebastiaan Janssen 98a0729549 Merge pull request #2202 from umbraco/temp-U4-10382
U4-10382 Add end point to get a paginated audit trail
2017-09-25 10:55:09 +02:00
Robert 97868593f8 Tab check is now using id and hash instead of innerHtml 2017-09-21 15:50:22 +02:00
Robert dcdfb074af Forgot to clean after myself :) 2017-09-21 14:09:14 +02:00
Robert a36b1097c5 added event to load audit trail on Properties tab only 2017-09-21 13:56:03 +02:00
Mads Rasmussen e268a05f6e remove client side lesson functions from core - these will be moved to the starter-kit 2017-09-21 11:14:31 +02:00
Mads Rasmussen fb7d22dca8 polish 2017-09-20 20:58:52 +02:00
Mads Rasmussen bac53bc241 rename dynamic user dashboards to "user-dialog" so they aren't confused with the user profiles in the new user section 2017-09-20 20:39:05 +02:00
Mads Rasmussen ce690acda0 move drawer width to less variable + fix backdrops when drawer is open 2017-09-20 20:30:44 +02:00
Mads Rasmussen cb8157dfca Start on a fresh help drawer branch - the other branch was a mess of testing data and nested content merges 2017-09-20 15:46:33 +02:00
Robert 4c7c6e37d1 Forgot to clean after myself :) 2017-09-19 12:02:29 +02:00
Robert 116e53e07d Custom serialization attribute added to AuditType property 2017-09-19 11:49:32 +02:00
Robert a74c4433f7 Mapping the DateStamp and UserName to AuditLog
Refactored how the the Username is displayed due to some misunderstanding on my part.
2017-09-19 11:01:07 +02:00
Robert 2ccf74a921 Adding the userName to the audit comment
Before the
2017-09-19 09:29:24 +02:00
Robert f3a81d82be Merge pull request #2184 from umbraco/temp-U4-10405
fixes: U4-10405 When scheduled publishing it set, change the default …
2017-09-18 13:24:47 +02:00
Sebastiaan Janssen 5451d28fe4 Update unit tests to account for the new AuditMapper 2017-09-14 21:29:24 +02:00
Mads Rasmussen db57268440 add prototype for media properties tab 2017-09-14 21:00:26 +02:00
Mads Rasmussen ac265067e8 move media node info component to media subfolder 2017-09-14 15:41:47 +02:00
Mads Rasmussen 5330830362 Merge branch 'dev-v7.7' into temp-U4-10309
# Conflicts:
#	src/Umbraco.Web.UI.Client/bower.json
#	src/Umbraco.Web.UI.Client/gruntFile.js
2017-09-14 15:28:21 +02:00
Mads Rasmussen 4b6b24b2f5 add empty state to history 2017-09-12 11:56:39 +02:00
Mads Rasmussen 7d5d89e9cb reuse styles for schedule dates 2017-09-12 11:56:13 +02:00
Mads Rasmussen ab85cbf599 remove unused code + clean up styles in general box 2017-09-12 10:24:44 +02:00
Mads Rasmussen c6937618c2 fixes: U4-10405 When scheduled publishing it set, change the default button to "Save and schedule" 2017-09-11 20:02:46 +02:00
Zsolt ef84d63982 Merge remote-tracking branch 'origin/temp-U4-10309' into temp-U4-10309 2017-09-11 13:06:49 +02:00
Zsolt 280a7445f4 media sections properties tab 2017-09-11 13:05:57 +02:00
Mads Rasmussen 5ae8a47f4b wire up audit trail 2017-09-10 22:58:45 +02:00
Shannon bc148d08fa maps avatars in log 2017-09-07 22:24:18 +10:00
Shannon 57a1e73383 Updates endpoints for both c# and js 2017-09-07 22:03:49 +10:00
Shannon c7b9a57795 U4-10382 Add end point to get a paginated audit trail 2017-09-07 17:27:37 +10:00
Shannon eb1edf94d3 Merge branch 'dev-v7.7' into temp-U4-10309 2017-09-06 15:51:01 +10:00
Zsolt c0b230a95e document type now openable + formatted the create date 2017-09-05 15:15:11 +02:00
Zsolt 607c2cc8e7 used localization and language keys on properties tab 2017-09-05 13:38:34 +02:00
Zsolt 48d3a3defd Made timeline more responsive + restructured the date in the footer 2017-09-05 11:57:22 +02:00
Mads Rasmussen 8509285aae move properties/info tab to it's own component 2017-09-04 21:12:47 +02:00
Mads Rasmussen 2413e9951f load in moment with locales globally + remove lazy loading from date picker 2017-09-04 14:04:06 +02:00
Mads Rasmussen 1a444fd703 add date pickers 2017-09-04 12:58:04 +02:00
Zsolt bd68a140ba Merge remote-tracking branch 'origin/temp-U4-10309' into temp-U4-10309 2017-09-01 15:10:50 +02:00
Zsolt 7b34211bb1 bit more responsive + changed the colors to variables in less 2017-09-01 15:09:53 +02:00
Mads Rasmussen fa78223229 make doc type + go to doc type work 2017-08-31 14:00:20 +02:00
Zsolt 39c19dc1d4 Merge remote-tracking branch 'origin/temp-U4-10309' into temp-U4-10309 2017-08-31 12:52:30 +02:00
Zsolt 7b4b6357cb changed more <h> tags + realigned them 2017-08-31 12:47:01 +02:00
Mads Rasmussen 4454290820 make link to document block element, add hover state + open in new tab 2017-08-31 11:56:03 +02:00
Mads Rasmussen d94cd9dc8d Merge branch 'temp-U4-10309' of https://github.com/umbraco/Umbraco-CMS into temp-U4-10309
# Conflicts:
#	src/Umbraco.Web.UI.Client/src/views/components/content/edit.html
2017-08-31 11:34:25 +02:00
Mads Rasmussen 8c07af9505 fake loading the auditTrail 2017-08-31 11:31:41 +02:00
Zsolt d32fb44187 Merge remote-tracking branch 'origin/temp-U4-10309' into temp-U4-10309 2017-08-31 11:29:08 +02:00
Zsolt dd38480ce2 changing <h> tags to span + adding extra description to timeline 2017-08-31 11:29:03 +02:00
Mads Rasmussen 08e8e3918e make template selector work 2017-08-31 11:23:10 +02:00
Zsolt 7a3591d1bd last line of the timeline is not there anymore 2017-08-31 10:20:49 +02:00
Zsolt 59ab7f5c8d Changed the order of meta data 2017-08-31 10:01:36 +02:00
Zsolt c2b2182182 Merge remote-tracking branch 'origin/temp-U4-10309' into temp-U4-10309 2017-08-31 09:51:54 +02:00
Zsolt 66b656f058 added the icon to the link, also the link functions as a link 2017-08-31 09:51:20 +02:00
Mads Rasmussen c8f7ecabf4 add avatar + set correct color on badges for history 2017-08-30 20:32:40 +02:00
Zsolt 9137249510 properties tab UI prototype with dummy data 2017-08-30 16:42:20 +02:00
Asbjørn Riis-Knudsen 841074fc27 U4-10191: Update to TinyMCE 4.6.x 2017-07-24 09:31:47 +02:00
Anders Bjerner 64f477f90e Added property for hiding the target option (2/2) 2017-02-16 18:45:01 +01:00
Anders Bjerner 813741bc3d Added property for hiding the target option (1/2) 2017-02-16 18:41:32 +01:00
Mitton 7c72e70967 Added grid editor names for localization. 2016-05-05 05:42:33 +02:00
Mitton 75b74a6687 Enabled localization of grid editor names 2016-05-05 05:12:33 +02:00
mattbrailsford 7dcb4435d8 Updated insert macro dialog to prevent closing on enter key 2015-12-22 11:18:32 +00:00
110 changed files with 2665 additions and 1411 deletions
+11 -5
View File
@@ -1,10 +1,16 @@
root=true
# editorconfig.org
# top-most EditorConfig file
root = true
# Default settings:
# A newline ending every file
# Use 4 spaces as indentation
[*]
end_of_line = lf
insert_final_newline = true
indent_style = space
indent_size = 4
trim_trailing_whitespace = true
[*.{cs,cshtml,csx,vb,vbx,vbhtml,fs,fsx,txt,ps1,sql}]
indent_size = 4
# Trim trailing whitespace, limited support.
# https://github.com/editorconfig/editorconfig/wiki/Property-research:-Trim-trailing-spaces
trim_trailing_whitespace = true
+49
View File
@@ -0,0 +1,49 @@
*.doc diff=astextplain
*.DOC diff=astextplain
*.docx diff=astextplain
*.DOCX diff=astextplain
*.dot diff=astextplain
*.DOT diff=astextplain
*.pdf diff=astextplain
*.PDF diff=astextplain
*.rtf diff=astextplain
*.RTF diff=astextplain
*.jpg binary
*.png binary
*.gif binary
*.cs text=auto diff=csharp
*.vb text=auto
*.c text=auto
*.cpp text=auto
*.cxx text=auto
*.h text=auto
*.hxx text=auto
*.py text=auto
*.rb text=auto
*.java text=auto
*.html text=auto
*.htm text=auto
*.css text=auto
*.scss text=auto
*.sass text=auto
*.less text=auto
*.js text=auto
*.lisp text=auto
*.clj text=auto
*.sql text=auto
*.php text=auto
*.lua text=auto
*.m text=auto
*.asm text=auto
*.erl text=auto
*.fs text=auto
*.fsx text=auto
*.hs text=auto
*.csproj text=auto merge=union
*.vbproj text=auto merge=union
*.fsproj text=auto merge=union
*.dbproj text=auto merge=union
*.sln text=auto eol=crlf merge=union
+1 -1
View File
@@ -29,7 +29,7 @@
<dependency id="Lucene.Net" version="[2.9.4.1, 3.0.0.0)" />
<dependency id="SharpZipLib" version="[0.86.0, 1.0.0)" />
<dependency id="MySql.Data" version="[6.9.9, 7.0.0)" />
<dependency id="ClientDependency" version="[1.9.4, 2.0.0)" />
<dependency id="ClientDependency" version="[1.9.6, 2.0.0)" />
<dependency id="ClientDependency-Mvc5" version="[1.8.0.0, 2.0.0)" />
<dependency id="AutoMapper" version="[3.3.1, 4.0.0)" />
<dependency id="Newtonsoft.Json" version="[10.0.2, 11.0.0)" />
+1 -1
View File
@@ -17,7 +17,7 @@
<dependencies>
<dependency id="UmbracoCms.Core" version="[$version$]" />
<dependency id="Newtonsoft.Json" version="[10.0.2, 11.0.0)" />
<dependency id="Umbraco.ModelsBuilder" version="[3.0.8, 4.0.0)" />
<dependency id="Umbraco.ModelsBuilder" version="[3.0.10, 4.0.0)" />
<dependency id="Microsoft.AspNet.SignalR.Core" version="[2.2.1, 3.0.0)" />
<dependency id="ImageProcessor.Web.Config" version="[2.3.1, 3.0.0)" />
</dependencies>
+2 -2
View File
@@ -11,5 +11,5 @@ using System.Resources;
[assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyFileVersion("7.7.8")]
[assembly: AssemblyInformationalVersion("7.7.8")]
[assembly: AssemblyFileVersion("7.7.12")]
[assembly: AssemblyInformationalVersion("7.7.12")]
@@ -0,0 +1,61 @@
using System;
namespace Umbraco.Core.Collections
{
/// <summary>
/// Represents a composite key of (Type, Type) for fast dictionaries.
/// </summary>
internal struct CompositeTypeTypeKey : IEquatable<CompositeTypeTypeKey>
{
/// <summary>
/// Initializes a new instance of the <see cref="CompositeTypeTypeKey"/> struct.
/// </summary>
public CompositeTypeTypeKey(Type type1, Type type2) : this()
{
Type1 = type1;
Type2 = type2;
}
/// <summary>
/// Gets the first type.
/// </summary>
public Type Type1 { get; private set; }
/// <summary>
/// Gets the second type.
/// </summary>
public Type Type2 { get; private set; }
/// <inheritdoc/>
public bool Equals(CompositeTypeTypeKey other)
{
return Type1 == other.Type1 && Type2 == other.Type2;
}
/// <inheritdoc/>
public override bool Equals(object obj)
{
var other = obj is CompositeTypeTypeKey ? (CompositeTypeTypeKey)obj : default(CompositeTypeTypeKey);
return Type1 == other.Type1 && Type2 == other.Type2;
}
public static bool operator ==(CompositeTypeTypeKey key1, CompositeTypeTypeKey key2)
{
return key1.Type1 == key2.Type1 && key1.Type2 == key2.Type2;
}
public static bool operator !=(CompositeTypeTypeKey key1, CompositeTypeTypeKey key2)
{
return key1.Type1 != key2.Type1 || key1.Type2 != key2.Type2;
}
/// <inheritdoc/>
public override int GetHashCode()
{
unchecked
{
return (Type1.GetHashCode() * 397) ^ Type2.GetHashCode();
}
}
}
}
@@ -1,10 +1,14 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Web;
using System.Xml.Linq;
using ClientDependency.Core.CompositeFiles.Providers;
using ClientDependency.Core.Config;
using Semver;
using Umbraco.Core.IO;
using Umbraco.Core.Logging;
@@ -24,10 +28,74 @@ namespace Umbraco.Core.Configuration
_logger = logger;
_fileName = IOHelper.MapPath(string.Format("{0}/ClientDependency.config", SystemDirectories.Config));
}
/// <summary>
/// Changes the version number in ClientDependency.config to a hashed value for the version and the DateTime.Day
/// </summary>
/// <param name="version">The <see cref="SemVersion">version</see> of Umbraco we're upgrading to</param>
/// <param name="date">A <see cref="DateTime">date</see> value to use in the hash to prevent this method from updating the version on each startup</param>
/// <param name="dateFormat">Allows the developer to specify the <see cref="string">date precision</see> for the hash (i.e. "yyyyMMdd" would be a precision for the day)</param>
/// <returns>Boolean to indicate succesful update of the ClientDependency.config file</returns>
public bool UpdateVersionNumber(SemVersion version, DateTime date, string dateFormat)
{
var byteContents = Encoding.Unicode.GetBytes(version + date.ToString(dateFormat));
//This is a way to convert a string to a long
//see https://www.codeproject.com/Articles/34309/Convert-String-to-bit-Integer
//We could much more easily use MD5 which would create us an INT but since that is not compliant with
//hashing standards we have to use SHA
int intHash;
using (var hash = SHA256.Create())
{
var bytes = hash.ComputeHash(byteContents);
var longResult = new[] { 0, 8, 16, 24 }
.Select(i => BitConverter.ToInt64(bytes, i))
.Aggregate((x, y) => x ^ y);
//CDF requires an INT, and although this isn't fail safe, it will work for our purposes. We are not hashing for crypto purposes
//so there could be some collisions with this conversion but it's not a problem for our purposes
//It's also important to note that the long.GetHashCode() implementation in .NET is this: return (int) this ^ (int) (this >> 32);
//which means that this value will not change per appdomain like some GetHashCode implementations.
intHash = longResult.GetHashCode();
}
try
{
var clientDependencyConfigXml = XDocument.Load(_fileName, LoadOptions.PreserveWhitespace);
if (clientDependencyConfigXml.Root != null)
{
var versionAttribute = clientDependencyConfigXml.Root.Attribute("version");
//Set the new version to the hashcode of now
var oldVersion = versionAttribute.Value;
var newVersion = Math.Abs(intHash).ToString();
//don't update if it's the same version
if (oldVersion == newVersion)
return false;
versionAttribute.SetValue(newVersion);
clientDependencyConfigXml.Save(_fileName, SaveOptions.DisableFormatting);
_logger.Info<ClientDependencyConfiguration>(string.Format("Updated version number from {0} to {1}", oldVersion, newVersion));
return true;
}
}
catch (Exception ex)
{
_logger.Error<ClientDependencyConfiguration>("Couldn't update ClientDependency version number", ex);
}
return false;
}
/// <summary>
/// Changes the version number in ClientDependency.config to a random value to avoid stale caches
/// </summary>
/// <seealso cref="UpdateVersionNumber(SemVersion, DateTime, string)" />
[Obsolete("Use the UpdateVersionNumber method specifying the version, date and dateFormat instead")]
public bool IncreaseVersionNumber()
{
try
@@ -107,4 +175,4 @@ namespace Umbraco.Core.Configuration
return success;
}
}
}
}
@@ -6,7 +6,7 @@ namespace Umbraco.Core.Configuration
{
public class UmbracoVersion
{
private static readonly Version Version = new Version("7.7.8");
private static readonly Version Version = new Version("7.7.12");
/// <summary>
/// Gets the current version of Umbraco.
+34 -34
View File
@@ -21,9 +21,9 @@ namespace Umbraco.Core
public static DateTime TruncateTo(this DateTime dt, DateTruncate truncateTo)
{
if (truncateTo == DateTruncate.Year)
return new DateTime(dt.Year, 0, 0);
return new DateTime(dt.Year, 1, 1);
if (truncateTo == DateTruncate.Month)
return new DateTime(dt.Year, dt.Month, 0);
return new DateTime(dt.Year, dt.Month, 1);
if (truncateTo == DateTruncate.Day)
return new DateTime(dt.Year, dt.Month, dt.Day);
if (truncateTo == DateTruncate.Hour)
@@ -41,43 +41,43 @@ namespace Umbraco.Core
Hour,
Minute,
Second
}
}
/// <summary>
/// Calculates the number of minutes from a date time, on a rolling daily basis (so if
/// Calculates the number of minutes from a date time, on a rolling daily basis (so if
/// date time is before the time, calculate onto next day)
/// </summary>
/// <param name="fromDateTime">Date to start from</param>
/// <param name="scheduledTime">Time to compare against (in Hmm form, e.g. 330, 2200)</param>
/// <returns></returns>
public static int PeriodicMinutesFrom(this DateTime fromDateTime, string scheduledTime)
{
// Ensure time provided is 4 digits long
if (scheduledTime.Length == 3)
{
scheduledTime = "0" + scheduledTime;
}
var scheduledHour = int.Parse(scheduledTime.Substring(0, 2));
var scheduledMinute = int.Parse(scheduledTime.Substring(2));
DateTime scheduledDateTime;
if (IsScheduledInRemainingDay(fromDateTime, scheduledHour, scheduledMinute))
{
scheduledDateTime = new DateTime(fromDateTime.Year, fromDateTime.Month, fromDateTime.Day, scheduledHour, scheduledMinute, 0);
}
else
{
var nextDay = fromDateTime.AddDays(1);
scheduledDateTime = new DateTime(nextDay.Year, nextDay.Month, nextDay.Day, scheduledHour, scheduledMinute, 0);
}
return (int)(scheduledDateTime - fromDateTime).TotalMinutes;
}
private static bool IsScheduledInRemainingDay(DateTime fromDateTime, int scheduledHour, int scheduledMinute)
{
return scheduledHour > fromDateTime.Hour || (scheduledHour == fromDateTime.Hour && scheduledMinute >= fromDateTime.Minute);
/// <returns></returns>
public static int PeriodicMinutesFrom(this DateTime fromDateTime, string scheduledTime)
{
// Ensure time provided is 4 digits long
if (scheduledTime.Length == 3)
{
scheduledTime = "0" + scheduledTime;
}
var scheduledHour = int.Parse(scheduledTime.Substring(0, 2));
var scheduledMinute = int.Parse(scheduledTime.Substring(2));
DateTime scheduledDateTime;
if (IsScheduledInRemainingDay(fromDateTime, scheduledHour, scheduledMinute))
{
scheduledDateTime = new DateTime(fromDateTime.Year, fromDateTime.Month, fromDateTime.Day, scheduledHour, scheduledMinute, 0);
}
else
{
var nextDay = fromDateTime.AddDays(1);
scheduledDateTime = new DateTime(nextDay.Year, nextDay.Month, nextDay.Day, scheduledHour, scheduledMinute, 0);
}
return (int)(scheduledDateTime - fromDateTime).TotalMinutes;
}
private static bool IsScheduledInRemainingDay(DateTime fromDateTime, int scheduledHour, int scheduledMinute)
{
return scheduledHour > fromDateTime.Hour || (scheduledHour == fromDateTime.Hour && scheduledMinute >= fromDateTime.Minute);
}
}
}
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using Umbraco.Core.Packaging.Models;
namespace Umbraco.Core.Events
@@ -7,18 +8,27 @@ namespace Umbraco.Core.Events
public class ImportPackageEventArgs<TEntity> : CancellableEnumerableObjectEventArgs<TEntity>, IEquatable<ImportPackageEventArgs<TEntity>>
{
private readonly MetaData _packageMetaData;
[EditorBrowsable(EditorBrowsableState.Never)]
[Obsolete("Use the overload specifying packageMetaData instead")]
public ImportPackageEventArgs(TEntity eventObject, bool canCancel)
: base(new[] { eventObject }, canCancel)
{
}
public ImportPackageEventArgs(TEntity eventObject, MetaData packageMetaData)
: base(new[] { eventObject })
public ImportPackageEventArgs(TEntity eventObject, MetaData packageMetaData, bool canCancel)
: base(new[] { eventObject }, canCancel)
{
if (packageMetaData == null) throw new ArgumentNullException("packageMetaData");
_packageMetaData = packageMetaData;
}
public ImportPackageEventArgs(TEntity eventObject, MetaData packageMetaData)
: this(eventObject, packageMetaData, true)
{
}
public MetaData PackageMetaData
{
get { return _packageMetaData; }
+4 -2
View File
@@ -95,8 +95,10 @@ namespace Umbraco.Core.Models
get { return _allowedTemplates; }
set
{
SetPropertyValueAndDetectChanges(value, ref _allowedTemplates, Ps.Value.AllowedTemplatesSelector,
Ps.Value.TemplateComparer);
SetPropertyValueAndDetectChanges(value, ref _allowedTemplates, Ps.Value.AllowedTemplatesSelector, Ps.Value.TemplateComparer);
if (_allowedTemplates.Any(x => x.Id == _defaultTemplate) == false)
DefaultTemplateId = 0;
}
}
File diff suppressed because it is too large Load Diff
@@ -132,7 +132,7 @@ namespace Umbraco.Core.Persistence.Repositories
public IMemberGroup GetByName(string name)
{
return IsolatedCache.GetCacheItem<IMemberGroup>(
string.Format("{0}.{1}", typeof (IMemberGroup).FullName, name),
string.Format("{0}.{1}", typeof(IMemberGroup).FullName, name),
() =>
{
var qry = new Query<IMemberGroup>().Where(group => group.Name.Equals(name));
@@ -140,7 +140,7 @@ namespace Umbraco.Core.Persistence.Repositories
return result.FirstOrDefault();
},
//cache for 5 mins since that is the default in the RuntimeCacheProvider
TimeSpan.FromMinutes(5),
TimeSpan.FromMinutes(5),
//sliding is true
true);
}
@@ -337,4 +337,4 @@ namespace Umbraco.Core.Persistence.Repositories
/// </summary>
internal static event TypedEventHandler<IMemberGroupRepository, SaveEventArgs<IMemberGroup>> SavedMemberGroup;
}
}
}
@@ -20,6 +20,12 @@ namespace Umbraco.Core.Persistence.Repositories
var name = Name;
// cater for instances where node has no name.
if(string.IsNullOrWhiteSpace(name))
{
return _numPos;
}
if (name[name.Length - 1] != ')')
return _numPos = -1;
@@ -106,7 +112,7 @@ namespace Umbraco.Core.Persistence.Repositories
}
}
return uniqueing ? string.Concat(nodeName, " (", uniqueNumber.ToString(), ")") : nodeName;
return uniqueing || string.IsNullOrWhiteSpace(nodeName) ? string.Concat(nodeName, " (", uniqueNumber.ToString(), ")") : nodeName;
}
}
}
@@ -1,9 +1,9 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Xml.Linq;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Umbraco.Core.Logging;
using Umbraco.Core.Manifest;
using Umbraco.Core.Models;
@@ -176,6 +176,12 @@ namespace Umbraco.Core.PropertyEditors
/// <returns></returns>
internal Attempt<object> TryConvertValueToCrlType(object value)
{
var jv = value as JValue;
if (jv != null)
{
value = value.ToString();
}
//this is a custom check to avoid any errors, if it's a string and it's empty just make it null
var s = value as string;
if (s != null)
@@ -391,4 +397,4 @@ namespace Umbraco.Core.PropertyEditors
}
}
}
}
}
@@ -40,12 +40,13 @@ namespace Umbraco.Core.PropertyEditors.ValueConverters
//TODO: Change all singleton access to use ctor injection in v8!!!
//TODO: That would mean that property value converters would need to be request lifespan, hrm....
bool isDebug = HttpContext.Current != null && HttpContext.Current.IsDebuggingEnabled;
var gridConfig = UmbracoConfig.For.GridConfig(
ApplicationContext.Current.ProfilingLogger.Logger,
ApplicationContext.Current.ApplicationCache.RuntimeCache,
new DirectoryInfo(IOHelper.MapPath(SystemDirectories.AppPlugins)),
new DirectoryInfo(IOHelper.MapPath(SystemDirectories.Config)),
HttpContext.Current.IsDebuggingEnabled);
isDebug);
var sections = GetArray(obj, "sections");
foreach (var section in sections.Cast<JObject>())
@@ -112,4 +113,4 @@ namespace Umbraco.Core.PropertyEditors.ValueConverters
}
}
}
}
@@ -18,6 +18,8 @@ namespace Umbraco.Core.PropertyEditors.ValueConverters
return Constants.PropertyEditors.MultipleTextstringAlias.Equals(propertyType.PropertyEditorAlias);
}
private static readonly string[] NewLineDelimiters = { "\r\n", "\r", "\n" };
public override object ConvertDataToSource(PublishedPropertyType propertyType, object source, bool preview)
{
// data is (both in database and xml):
@@ -53,7 +55,7 @@ namespace Umbraco.Core.PropertyEditors.ValueConverters
// Fall back on normal behaviour
if (values.Any() == false)
{
return sourceString.Split(new string[] { Environment.NewLine }, StringSplitOptions.None);
return sourceString.Split(NewLineDelimiters, StringSplitOptions.None);
}
return values.ToArray();
+14
View File
@@ -116,5 +116,19 @@ namespace Umbraco.Core.Scoping
Enlisted[key] = enlistedOfT;
return enlistedOfT.Item;
}
public T GetEnlisted<T>(string key)
{
var enlistedObjects = _enlisted;
if (enlistedObjects == null) return default (T);
IEnlistedObject enlisted;
if (enlistedObjects.TryGetValue(key, out enlisted) == false)
return default (T);
var enlistedAs = enlisted as EnlistedObject<T>;
if (enlistedAs == null) throw new InvalidOperationException("An item with the key exists, but with a different type.");
return enlistedAs.Item;
}
}
}
@@ -1344,6 +1344,40 @@ namespace Umbraco.Core.Services
return content;
}
public void DeleteBlueprintsOfTypes(IEnumerable<int> contentTypeIds, int userId = 0)
{
using (new WriteLock(Locker))
using (var uow = UowProvider.GetUnitOfWork())
{
var repository = RepositoryFactory.CreateContentBlueprintRepository(uow);
var contentTypeIdsA = contentTypeIds.ToArray();
var query = new Query<IContent>();
if (contentTypeIdsA.Length > 0)
{
query.Where(x => contentTypeIdsA.Contains(x.ContentTypeId));
}
var blueprints = repository.GetByQuery(query).Select(x =>
{
((Content) x).IsBlueprint = true;
return x;
}).ToArray();
foreach (var blueprint in blueprints)
{
repository.Delete(blueprint);
}
uow.Events.Dispatch(DeletedBlueprint, this, new DeleteEventArgs<IContent>(blueprints), "DeletedBlueprint");
uow.Commit();
}
}
public void DeleteBlueprintsOfType(int contentTypeId, int userId = 0)
{
DeleteBlueprintsOfTypes(new[] {contentTypeId}, userId);
}
/// <summary>
/// Saves a single <see cref="IContent"/> object
/// </summary>
@@ -920,7 +920,9 @@ namespace Umbraco.Core.Services
var deletedContentTypes = new List<IContentType> { contentType };
deletedContentTypes.AddRange(GetDescendants(contentType));
_contentService.DeleteContentOfTypes(deletedContentTypes.Select(x => x.Id), userId);
var ids = deletedContentTypes.Select(x => x.Id).ToArray();
_contentService.DeleteContentOfTypes(ids, userId);
_contentService.DeleteBlueprintsOfTypes(ids);
repository.Delete(contentType);
deleteEventArgs.DeletedEntities = deletedContentTypes.DistinctBy(x => x.Id);
+3 -1
View File
@@ -101,7 +101,9 @@ namespace Umbraco.Core.Services
IContent GetBlueprintById(Guid id);
void SaveBlueprint(IContent content, int userId = 0);
void DeleteBlueprint(IContent content, int userId = 0);
IContent CreateContentFromBlueprint(IContent blueprint, string name, int userId = 0);
IContent CreateContentFromBlueprint(IContent blueprint, string name, int userId = 0);
void DeleteBlueprintsOfType(int contentTypeId, int userId = 0);
void DeleteBlueprintsOfTypes(IEnumerable<int> contentTypeIds, int userId = 0);
/// <summary>
/// Gets all XML entries found in the cmsContentXml table based on the given path
+1 -1
View File
@@ -695,7 +695,7 @@ namespace Umbraco.Core.Services
IQuery<IMember> filterQuery = null;
if (filter.IsNullOrWhiteSpace() == false)
{
filterQuery = Query<IMember>.Builder.Where(x => x.Name.Contains(filter) || x.Username.Contains(filter));
filterQuery = Query<IMember>.Builder.Where(x => x.Name.Contains(filter) || x.Username.Contains(filter) || x.Email.Contains(filter));
}
var repository = RepositoryFactory.CreateMemberRepository(uow);
@@ -1748,9 +1748,10 @@ namespace Umbraco.Core.Services
internal InstallationSummary InstallPackage(string packageFilePath, int userId = 0, bool raiseEvents = false)
{
var metaData = GetPackageMetaData(packageFilePath);
if (raiseEvents)
{
var metaData = GetPackageMetaData(packageFilePath);
{
if (ImportingPackage.IsRaisedEventCancelled(new ImportPackageEventArgs<string>(packageFilePath, metaData), this))
{
var initEmpty = new InstallationSummary().InitEmpty();
@@ -1762,7 +1763,7 @@ namespace Umbraco.Core.Services
if (raiseEvents)
{
ImportedPackage.RaiseEvent(new ImportPackageEventArgs<InstallationSummary>(installationSummary, false), this);
ImportedPackage.RaiseEvent(new ImportPackageEventArgs<InstallationSummary>(installationSummary, metaData, false), this);
}
return installationSummary;
@@ -70,7 +70,7 @@ namespace Umbraco.Core.Strings
{
foreach (var node in _umbracoSettings.RequestHandler.CharCollection)
{
if(string.IsNullOrEmpty(node.Char) == false)
if (string.IsNullOrEmpty(node.Char) == false)
_urlReplaceCharacters[node.Char] = node.Replacement;
}
}
@@ -109,7 +109,7 @@ namespace Umbraco.Core.Strings
private void EnsureNotFrozen()
{
if (_frozen)
throw new InvalidOperationException("Cannot configure the helper once it is frozen.");
throw new InvalidOperationException("Cannot configure the helper once it is frozen.");
}
/// <summary>
@@ -176,7 +176,7 @@ namespace Umbraco.Core.Strings
}).WithConfig(CleanStringType.Alias, new Config
{
PreFilter = ApplyUrlReplaceCharacters,
IsTerm = (c, leading) => leading
IsTerm = (c, leading) => leading
? char.IsLetter(c) // only letters
: (char.IsLetterOrDigit(c) || c == '_'), // letter, digit or underscore
StringType = CleanStringType.Ascii | CleanStringType.UmbracoCase,
@@ -215,12 +215,12 @@ namespace Umbraco.Core.Strings
return new Config
{
PreFilter = PreFilter,
PostFilter = PostFilter,
PostFilter = PostFilter,
IsTerm = IsTerm,
StringType = StringType,
BreakTermsOnUpper = BreakTermsOnUpper,
CutAcronymOnNonUpper = CutAcronymOnNonUpper,
GreedyAcronyms = GreedyAcronyms,
CutAcronymOnNonUpper = CutAcronymOnNonUpper,
GreedyAcronyms = GreedyAcronyms,
Separator = Separator
};
}
@@ -338,9 +338,9 @@ function validateSafeAlias(input, value, immediate, callback) {{
/// Gets the JavaScript code defining client-side short string services.
/// </summary>
public string GetShortStringServicesJavaScript(string controllerPath)
{
return string.Format(SssjsFormat,
_umbracoSettings.Content.ForceSafeAliases ? "true" : "false", controllerPath);
{
return string.Format(SssjsFormat,
_umbracoSettings.Content.ForceSafeAliases ? "true" : "false", controllerPath);
}
#endregion
@@ -467,7 +467,7 @@ function validateSafeAlias(input, value, immediate, callback) {{
/// Cleans a string.
/// </summary>
/// <param name="text">The text to clean.</param>
/// <param name="stringType">A flag indicating the target casing and encoding of the string. By default,
/// <param name="stringType">A flag indicating the target casing and encoding of the string. By default,
/// strings are cleaned up to camelCase and Ascii.</param>
/// <returns>The clean string.</returns>
/// <remarks>The string is cleaned in the context of the default culture.</remarks>
@@ -480,7 +480,7 @@ function validateSafeAlias(input, value, immediate, callback) {{
/// Cleans a string, using a specified separator.
/// </summary>
/// <param name="text">The text to clean.</param>
/// <param name="stringType">A flag indicating the target casing and encoding of the string. By default,
/// <param name="stringType">A flag indicating the target casing and encoding of the string. By default,
/// strings are cleaned up to camelCase and Ascii.</param>
/// <param name="separator">The separator.</param>
/// <returns>The clean string.</returns>
@@ -494,7 +494,7 @@ function validateSafeAlias(input, value, immediate, callback) {{
/// Cleans a string in the context of a specified culture.
/// </summary>
/// <param name="text">The text to clean.</param>
/// <param name="stringType">A flag indicating the target casing and encoding of the string. By default,
/// <param name="stringType">A flag indicating the target casing and encoding of the string. By default,
/// strings are cleaned up to camelCase and Ascii.</param>
/// <param name="culture">The culture.</param>
/// <returns>The clean string.</returns>
@@ -507,7 +507,7 @@ function validateSafeAlias(input, value, immediate, callback) {{
/// Cleans a string in the context of a specified culture, using a specified separator.
/// </summary>
/// <param name="text">The text to clean.</param>
/// <param name="stringType">A flag indicating the target casing and encoding of the string. By default,
/// <param name="stringType">A flag indicating the target casing and encoding of the string. By default,
/// strings are cleaned up to camelCase and Ascii.</param>
/// <param name="separator">The separator.</param>
/// <param name="culture">The culture.</param>
@@ -554,7 +554,7 @@ function validateSafeAlias(input, value, immediate, callback) {{
text = Utf8ToAsciiConverter.ToAsciiString(text);
break;
case CleanStringType.TryAscii:
const char ESC = (char) 27;
const char ESC = (char)27;
var ctext = Utf8ToAsciiConverter.ToAsciiString(text, ESC);
if (ctext.Contains(ESC) == false) text = ctext;
break;
@@ -568,8 +568,8 @@ function validateSafeAlias(input, value, immediate, callback) {{
// apply post-filter
if (config.PostFilter != null)
text = config.PostFilter(text);
text = config.PostFilter(text);
return text;
}
@@ -839,7 +839,7 @@ function validateSafeAlias(input, value, immediate, callback) {{
{
term = term.Substring(i);
term.CopyTo(0, output, opos, term.Length);
opos += term.Length;
opos += term.Length;
}
break;
@@ -914,21 +914,22 @@ function validateSafeAlias(input, value, immediate, callback) {{
/// <returns>The filtered string.</returns>
public virtual string ReplaceMany(string text, IDictionary<string, string> replacements)
{
// be safe
if (text == null)
{
throw new ArgumentNullException("text");
}
if (replacements == null)
{
throw new ArgumentNullException("replacements");
}
// Have done various tests, implementing my own "super fast" state machine to handle
// replacement of many items, or via regexes, but on short strings and not too
// many replacements (which prob. is going to be our case) nothing can beat this...
// (at least with safe and checked code -- we don't want unsafe/unchecked here)
foreach (KeyValuePair<string, string> item in replacements)
{
text = text.Replace(item.Key, item.Value);
}
// Note that it will do chained-replacements ie replaced items can be replaced
// in turn by another replacement (ie the order of replacements is important)
return replacements.Aggregate(text, (current, kvp) => current.Replace(kvp.Key, kvp.Value));
return text;
}
/// <summary>
@@ -940,15 +941,22 @@ function validateSafeAlias(input, value, immediate, callback) {{
/// <returns>The filtered string.</returns>
public virtual string ReplaceMany(string text, char[] chars, char replacement)
{
// be safe
if (text == null)
{
throw new ArgumentNullException("text");
}
if (chars == null)
{
throw new ArgumentNullException("chars");
}
// see note above
for (int i = 0; i < chars.Length; i++)
{
text = text.Replace(chars[i], replacement);
}
return chars.Aggregate(text, (current, c) => current.Replace(c, replacement));
return text;
}
#endregion
@@ -55,7 +55,7 @@ namespace Umbraco.Core.Sync
if (newApplicationUrl)
{
appContext._umbracoApplicationDomains.Add(applicationUrl);
LogHelper.Info(typeof(ApplicationUrlHelper), $"New ApplicationUrl detected: {applicationUrl}");
LogHelper.Info(typeof(ApplicationUrlHelper), string.Format("New ApplicationUrl detected: {0}", applicationUrl));
}
}
@@ -169,4 +169,4 @@ namespace Umbraco.Core.Sync
return url.TrimEnd('/');
}
}
}
}
+3 -2
View File
@@ -43,8 +43,8 @@
<Reference Include="AutoMapper.Net4, Version=3.3.1.0, Culture=neutral, PublicKeyToken=be96cd2c38ef1005, processorArchitecture=MSIL">
<HintPath>..\packages\AutoMapper.3.3.1\lib\net40\AutoMapper.Net4.dll</HintPath>
</Reference>
<Reference Include="ClientDependency.Core, Version=1.9.4.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\ClientDependency.1.9.4\lib\net45\ClientDependency.Core.dll</HintPath>
<Reference Include="ClientDependency.Core, Version=1.9.6.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\ClientDependency.1.9.6\lib\net45\ClientDependency.Core.dll</HintPath>
</Reference>
<Reference Include="HtmlAgilityPack, Version=1.4.9.5, Culture=neutral, PublicKeyToken=bd319b19eaf3b43a, processorArchitecture=MSIL">
<HintPath>..\packages\HtmlAgilityPack.1.4.9.5\lib\Net45\HtmlAgilityPack.dll</HintPath>
@@ -1531,6 +1531,7 @@
<Compile Include="ReadLock.cs" />
<Compile Include="TypeFinder.cs" />
<Compile Include="TypeHelper.cs" />
<Compile Include="Collections\CompositeTypeTypeKey.cs" />
<Compile Include="Udi.cs" />
<Compile Include="UdiDefinitionAttribute.cs" />
<Compile Include="UdiEntityType.cs" />
+1 -1
View File
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="AutoMapper" version="3.3.1" targetFramework="net45" />
<package id="ClientDependency" version="1.9.4" targetFramework="net45" />
<package id="ClientDependency" version="1.9.6" targetFramework="net45" />
<package id="HtmlAgilityPack" version="1.4.9.5" targetFramework="net45" />
<package id="ImageProcessor" version="2.5.6" targetFramework="net45" />
<package id="log4net" version="2.0.8" targetFramework="net45" />
@@ -3,43 +3,24 @@ using System.Collections.Generic;
using System.Data.SqlServerCe;
using System.IO;
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Configs;
using BenchmarkDotNet.Diagnostics.Windows;
using BenchmarkDotNet.Jobs;
using Umbraco.Core;
using Umbraco.Core.Logging;
using Umbraco.Core.Models.Rdbms;
using Umbraco.Core.Persistence;
using Umbraco.Core.Persistence.Migrations.Initial;
using Umbraco.Core.Persistence.SqlSyntax;
using Umbraco.Tests.Benchmarks.Config;
using Umbraco.Tests.TestHelpers;
using ILogger = Umbraco.Core.Logging.ILogger;
namespace Umbraco.Tests.Benchmarks
{
[Config(typeof(Config))]
[QuickRunWithMemoryDiagnoserConfig]
public class BulkInsertBenchmarks
{
private class Config : ManualConfig
{
public Config()
{
Add(new MemoryDiagnoser());
//Add(ExecutionValidator.FailOnError);
//The 'quick and dirty' settings, so it runs a little quicker
// see benchmarkdotnet FAQ
Add(Job.Default
.WithLaunchCount(1) // benchmark process will be launched only once
.WithIterationTime(100) // 100ms per iteration
.WithWarmupCount(3) // 3 warmup iteration
.WithTargetCount(3)); // 3 target iteration
}
}
private static byte[] _initDbBytes = null;
[Setup]
[GlobalSetup]
public void Setup()
{
var logger = new DebugDiagnosticsLogger();
@@ -51,8 +32,8 @@ namespace Umbraco.Tests.Benchmarks
SetupSqlCe(path, logger);
SetupSqlServer(logger);
}
}
private void SetupSqlServer(ILogger logger)
{
@@ -75,7 +56,7 @@ namespace Umbraco.Tests.Benchmarks
[lastNotifiedDate] [datetime] NOT NULL,
[isActive] [bit] NOT NULL,
[isMaster] [bit] NOT NULL,
CONSTRAINT [PK_umbracoServer] PRIMARY KEY CLUSTERED
CONSTRAINT [PK_umbracoServer] PRIMARY KEY CLUSTERED
(
[id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
@@ -87,7 +68,7 @@ namespace Umbraco.Tests.Benchmarks
var dbName = string.Concat("Umb", Guid.NewGuid(), ".sdf");
AppDomain.CurrentDomain.SetData("DataDirectory", path);
var sqlCeConnectionString = $"Datasource=|DataDirectory|\\{dbName};Flush Interval=1;";
_dbFile = Path.Combine(path, dbName);
//only create the db one time
@@ -107,12 +88,12 @@ namespace Umbraco.Tests.Benchmarks
var creation = new DatabaseSchemaCreation(_dbSqlCe, logger, _sqlCeSyntax);
creation.InitializeDatabaseSchema();
}
_initDbBytes = File.ReadAllBytes(_dbFile);
_initDbBytes = File.ReadAllBytes(_dbFile);
}
else
{
File.WriteAllBytes(_dbFile, _initDbBytes);
}
}
//create the db
_dbSqlCe = new UmbracoDatabase(
@@ -138,7 +119,7 @@ namespace Umbraco.Tests.Benchmarks
return data;
}
[Cleanup]
[GlobalCleanup]
public void Cleanup()
{
_dbSqlCe.Dispose();
@@ -0,0 +1,153 @@
using BenchmarkDotNet.Attributes;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Umbraco.Core.Collections;
namespace Umbraco.Tests.Benchmarks
{
[MemoryDiagnoser]
public class ConcurrentDictionaryBenchmarks
{
private static readonly ConcurrentDictionary<CompositeTypeTypeKey, bool> AssignableTypeCache = new ConcurrentDictionary<CompositeTypeTypeKey, bool>();
private static object input = new Bar();
private static Type source = typeof(Bar);
private static Type target = typeof(Foo);
[Benchmark(Baseline = true)]
public bool GetCachedCanAssignFactory()
{
return AssignableTypeCache.GetOrAdd(new CompositeTypeTypeKey(source, target), k =>
{
var ksource = k.Type1;
var ktarget = k.Type2;
return ktarget.IsAssignableFrom(ksource) && typeof(IConvertible).IsAssignableFrom(ksource);
});
}
[Benchmark]
public bool GetCachedCanAssignNoFactory()
{
// This method is 10% faster
var key = new CompositeTypeTypeKey(source, target);
bool canConvert;
if (AssignableTypeCache.TryGetValue(key, out canConvert))
{
return canConvert;
}
// "is" is faster than "IsAssignableFrom"
if (input is IConvertible && target.IsAssignableFrom(source))
{
return AssignableTypeCache[key] = true;
}
return AssignableTypeCache[key] = false;
}
private class Foo : IConvertible
{
public TypeCode GetTypeCode()
{
return TypeCode.Object;
}
public bool ToBoolean(IFormatProvider provider)
{
throw new NotImplementedException();
}
public byte ToByte(IFormatProvider provider)
{
throw new NotImplementedException();
}
public char ToChar(IFormatProvider provider)
{
throw new NotImplementedException();
}
public DateTime ToDateTime(IFormatProvider provider)
{
throw new NotImplementedException();
}
public decimal ToDecimal(IFormatProvider provider)
{
throw new NotImplementedException();
}
public double ToDouble(IFormatProvider provider)
{
throw new NotImplementedException();
}
public short ToInt16(IFormatProvider provider)
{
throw new NotImplementedException();
}
public int ToInt32(IFormatProvider provider)
{
throw new NotImplementedException();
}
public long ToInt64(IFormatProvider provider)
{
throw new NotImplementedException();
}
public sbyte ToSByte(IFormatProvider provider)
{
throw new NotImplementedException();
}
public float ToSingle(IFormatProvider provider)
{
throw new NotImplementedException();
}
public string ToString(IFormatProvider provider)
{
throw new NotImplementedException();
}
public object ToType(Type conversionType, IFormatProvider provider)
{
if (conversionType == typeof(Foo))
{
return new Foo();
}
throw new NotImplementedException();
}
public ushort ToUInt16(IFormatProvider provider)
{
throw new NotImplementedException();
}
public uint ToUInt32(IFormatProvider provider)
{
throw new NotImplementedException();
}
public ulong ToUInt64(IFormatProvider provider)
{
throw new NotImplementedException();
}
}
private class Bar : Foo
{
}
}
}
@@ -0,0 +1,33 @@
using BenchmarkDotNet.Configs;
using BenchmarkDotNet.Horology;
using BenchmarkDotNet.Jobs;
using System;
namespace Umbraco.Tests.Benchmarks.Config
{
/// <summary>
/// Configures the benchmark to run with less warmup and a shorter iteration time than the standard benchmark.
/// </summary>
public class QuickRunConfigAttribute : Attribute, IConfigSource
{
/// <summary>
/// Initializes a new instance of the <see cref="QuickRunConfigAttribute"/> class.
/// </summary>
public QuickRunConfigAttribute()
{
Config = (ManualConfig) ManualConfig.CreateEmpty()
.With(Job.Default.WithLaunchCount(1) // benchmark process will be launched only once
.WithIterationTime(new TimeInterval(100, TimeUnit.Millisecond)) // 100ms per iteration
.WithWarmupCount(3) // 3 warmup iteration
.WithTargetCount(3)); // 3 target iteration
}
/// <summary>
/// Gets the manual configuration.
/// </summary>
protected ManualConfig Config { get; }
/// <inheritdoc/>
IConfig IConfigSource.Config => Config;
}
}
@@ -0,0 +1,20 @@
using BenchmarkDotNet.Configs;
using BenchmarkDotNet.Diagnosers;
namespace Umbraco.Tests.Benchmarks.Config
{
/// <summary>
/// Configures the benchmark to run with less warmup and a shorter iteration time than the standard benchmark,
/// and include memory usage diagnosis.
/// </summary>
public class QuickRunWithMemoryDiagnoserConfigAttribute : QuickRunConfigAttribute
{
/// <summary>
/// Initializes a new instance of the <see cref="QuickRunWithMemoryDiagnoserConfigAttribute"/> class.
/// </summary>
public QuickRunWithMemoryDiagnoserConfigAttribute()
{
Config.Add(new MemoryDiagnoser());
}
}
}
@@ -1,25 +1,16 @@
using System.Collections.Generic;
using System.Linq;
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Configs;
using BenchmarkDotNet.Diagnostics.Windows;
using BenchmarkDotNet.Diagnosers;
namespace Umbraco.Tests.Benchmarks
{
/// <summary>
/// Want to check what is faster OfType or Cast when a enurable all has the same items
/// </summary>
[Config(typeof(Config))]
[MemoryDiagnoser]
public class LinqCastBenchmarks
{
private class Config : ManualConfig
{
public Config()
{
Add(new MemoryDiagnoser());
}
}
public LinqCastBenchmarks()
{
_array = new List<object>();
@@ -1,47 +1,19 @@
using System;
using System.Collections.Generic;
using System.Data.SqlServerCe;
using System.Diagnostics;
using System.IO;
using System.Linq.Expressions;
using System.Threading;
using System.Xml;
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Columns;
using BenchmarkDotNet.Configs;
using BenchmarkDotNet.Diagnosers;
using BenchmarkDotNet.Diagnostics.Windows;
using BenchmarkDotNet.Jobs;
using BenchmarkDotNet.Loggers;
using BenchmarkDotNet.Reports;
using BenchmarkDotNet.Running;
using BenchmarkDotNet.Validators;
using Moq;
using Umbraco.Core;
using Umbraco.Core.Logging;
using Umbraco.Core.Models;
using Umbraco.Core.Models.Rdbms;
using Umbraco.Core.Persistence;
using Umbraco.Core.Persistence.Mappers;
using Umbraco.Core.Persistence.Migrations.Initial;
using Umbraco.Core.Persistence.Querying;
using Umbraco.Core.Persistence.SqlSyntax;
using Umbraco.Tests.TestHelpers;
using ILogger = Umbraco.Core.Logging.ILogger;
namespace Umbraco.Tests.Benchmarks
{
[Config(typeof(Config))]
[MemoryDiagnoser]
public class ModelToSqlExpressionHelperBenchmarks
{
private class Config : ManualConfig
{
public Config()
{
Add(new MemoryDiagnoser());
}
}
public ModelToSqlExpressionHelperBenchmarks()
{
var contentMapper = new ContentMapper(_syntaxProvider);
@@ -51,7 +23,7 @@ namespace Umbraco.Tests.Benchmarks
mappingResolver.Setup(resolver => resolver.ResolveMapperByType(It.IsAny<Type>())).Returns(contentMapper);
_mappingResolver = mappingResolver.Object;
}
private readonly ISqlSyntaxProvider _syntaxProvider = new SqlCeSyntaxProvider();
private readonly CachedExpression _cachedExpression;
private readonly MappingResolver _mappingResolver;
@@ -62,18 +34,15 @@ namespace Umbraco.Tests.Benchmarks
for (int i = 0; i < 100; i++)
{
var a = i;
var b = i*10;
var b = i * 10;
Expression<Func<IContent, bool>> predicate = content =>
content.Path.StartsWith("-1") && content.Published && (content.ContentTypeId == a || content.ContentTypeId == b);
var modelToSqlExpressionHelper = new ModelToSqlExpressionVisitor<IContent>(_syntaxProvider, _mappingResolver);
var result = modelToSqlExpressionHelper.Visit(predicate);
}
}
[Benchmark()]
public void WithCachedExpression()
{
@@ -83,7 +52,7 @@ namespace Umbraco.Tests.Benchmarks
var b = i * 10;
Expression<Func<IContent, bool>> predicate = content =>
content.Path.StartsWith("-1") && content.Published && (content.ContentTypeId == a || content.ContentTypeId == b);
var modelToSqlExpressionHelper = new ModelToSqlExpressionVisitor<IContent>(_syntaxProvider, _mappingResolver);
//wrap it!
@@ -92,6 +61,5 @@ namespace Umbraco.Tests.Benchmarks
var result = modelToSqlExpressionHelper.Visit(_cachedExpression);
}
}
}
}
+1 -11
View File
@@ -6,17 +6,7 @@ namespace Umbraco.Tests.Benchmarks
{
public static void Main(string[] args)
{
var switcher = new BenchmarkSwitcher(new[]
{
typeof(BulkInsertBenchmarks),
typeof(ModelToSqlExpressionHelperBenchmarks),
typeof(XmlBenchmarks),
typeof(LinqCastBenchmarks),
//typeof(DeepCloneBenchmarks),
typeof(XmlPublishedContentInitBenchmarks),
});
switcher.Run(args);
new BenchmarkSwitcher(typeof(Program).Assembly).Run(args);
}
}
}
@@ -0,0 +1,138 @@
using BenchmarkDotNet.Attributes;
using System;
using System.Collections.Generic;
using System.Linq;
using Umbraco.Tests.Benchmarks.Config;
namespace Umbraco.Tests.Benchmarks
{
[QuickRunWithMemoryDiagnoserConfig]
public class StringReplaceManyBenchmarks
{
/*
short text, short replacement:
Method | Mean | Error | StdDev | Scaled | ScaledSD | Gen 0 | Allocated |
--------------------------------------------- |---------:|----------:|----------:|-------:|---------:|-------:|----------:|
'String.ReplaceMany w/chars - Aggregate' | 236.0 ns | 40.92 ns | 2.312 ns | 1.00 | 0.00 | 0.0461 | 200 B |
'String.ReplaceMany w/chars - For Loop' | 166.7 ns | 70.51 ns | 3.984 ns | 0.71 | 0.01 | 0.0420 | 180 B |
'String.ReplaceMany w/dictionary - Aggregate' | 606.5 ns | 342.94 ns | 19.377 ns | 2.57 | 0.07 | 0.0473 | 212 B |
'String.ReplaceMany w/dictionary - For Each' | 571.8 ns | 232.33 ns | 13.127 ns | 2.42 | 0.05 | 0.0458 | 212 B |
long text, short replacement:
Method | Mean | Error | StdDev | Scaled | ScaledSD | Gen 0 | Allocated |
--------------------------------------------- |----------:|----------:|----------:|-------:|---------:|-------:|----------:|
'String.ReplaceMany w/chars - Aggregate' | 5.771 us | 9.963 us | 0.5630 us | 1.00 | 0.00 | 1.6798 | 6.94 KB |
'String.ReplaceMany w/chars - For Loop' | 4.962 us | 2.121 us | 0.1199 us | 0.87 | 0.08 | 1.6840 | 6.92 KB |
'String.ReplaceMany w/dictionary - Aggregate' | 14.514 us | 8.189 us | 0.4627 us | 2.53 | 0.22 | 1.6447 | 6.96 KB |
'String.ReplaceMany w/dictionary - For Each' | 15.445 us | 24.745 us | 1.3981 us | 2.69 | 0.30 | 1.5696 | 6.96 KB |
short text, long replacements dictionary:
Method | Mean | Error | StdDev | Scaled | ScaledSD | Gen 0 | Allocated |
--------------------------------------------- |-----------:|-----------:|----------:|-------:|---------:|-------:|----------:|
'String.ReplaceMany w/chars - Aggregate' | 257.0 ns | 200.0 ns | 11.30 ns | 1.00 | 0.00 | 0.0452 | 200 B |
'String.ReplaceMany w/chars - For Loop' | 182.4 ns | 221.0 ns | 12.49 ns | 0.71 | 0.05 | 0.0425 | 180 B |
'String.ReplaceMany w/dictionary - Aggregate' | 7,273.8 ns | 2,747.1 ns | 155.22 ns | 28.34 | 1.12 | 0.0714 | 464 B |
'String.ReplaceMany w/dictionary - For Each' | 6,981.0 ns | 5,500.7 ns | 310.80 ns | 27.20 | 1.38 | 0.0775 | 464 B |
long text, long replacements dictionary:
Method | Mean | Error | StdDev | Scaled | ScaledSD | Gen 0 | Allocated |
--------------------------------------------- |-----------:|-----------:|-----------:|-------:|---------:|-------:|----------:|
'String.ReplaceMany w/chars - Aggregate' | 4.868 us | 3.420 us | 0.1932 us | 1.00 | 0.00 | 1.6816 | 6.94 KB |
'String.ReplaceMany w/chars - For Loop' | 4.958 us | 2.633 us | 0.1487 us | 1.02 | 0.04 | 1.6791 | 6.92 KB |
'String.ReplaceMany w/dictionary - Aggregate' | 181.309 us | 210.177 us | 11.8754 us | 37.29 | 2.32 | 5.3571 | 24.28 KB |
'String.ReplaceMany w/dictionary - For Each' | 174.567 us | 113.733 us | 6.4262 us | 35.90 | 1.57 | 5.8594 | 24.28 KB |
*/
// don't use constants
// ReSharper disable ConvertToConstant.Local
// input text for ReplaceMany
private static readonly string Text;
// replaced chars for ReplaceMany with chars
private static readonly char[] ReplacedChars = { ',', '.', ':', '&', '#' };
// replacement char for ReplaceMany with chars
private static readonly char ReplacementChar = '*';
// replacements for ReplaceMany with dictionary
private static readonly IDictionary<string, string> Replacements;
// ReSharper restore ConvertToConstant.Local
static StringReplaceManyBenchmarks()
{
// pick what you want to benchmark
// short
Text = "1,2.3:4&5#6";
// long
//Text = "Sed ut perspiciatis unde omnis iste natus &error sit voluptatem accusantium doloremque l:audantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et &quasi architecto beatae vitae ::dicta sunt explicabo. Nemo enim ipsam volupta:tem quia voluptas sit aspernatur aut o&dit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciun&t. Neque porro quisquam est, qui dolorem: ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem. Ut e:nim ad minima veniam, quis nostrum exercitationem ullam corporis suscipit laboriosam, nisi ut aliquid ex ea commodi co&&nsequatur? Quis autem vel eum iure reprehenderit qui in ea voluptate velit esse: quam nihil molestiae consequatur, vel illum qui dolorem eum fugiat quo voluptas nulla pariatur?";
// short
Replacements = new Dictionary<string, string>
{
{ ",", "*" },
{ ".", "*" },
{ ":", "*" },
{ "&", "*" },
{ "#", "*" },
};
// long
//Replacements = new Dictionary<string, string>();
//for (var i = 2; i < 100; i++)
// Replacements[Convert.ToChar(i).ToString()] = "*";
}
// this is what v7 originally did
[Benchmark(Description = "String.ReplaceMany w/chars - Aggregate", Baseline = true)]
public string ReplaceManyAggregate()
{
var result = Text;
return ReplacedChars.Aggregate(result, (current, c) => current.Replace(c, ReplacementChar));
}
[Benchmark(Description = "String.ReplaceMany w/chars - For Loop")]
public string ReplaceManyForLoop()
{
var result = Text;
// ReSharper disable once LoopCanBeConvertedToQuery
// ReSharper disable once ForCanBeConvertedToForeach
for (var i = 0; i < ReplacedChars.Length; i++)
{
result = result.Replace(ReplacedChars[i], ReplacementChar);
}
return result;
}
// this is what v7 originally did
[Benchmark(Description = "String.ReplaceMany w/dictionary - Aggregate")]
public string ReplaceManyDictionaryAggregate()
{
return Replacements.Aggregate(Text, (current, kvp) => current.Replace(kvp.Key, kvp.Value));
}
[Benchmark(Description = "String.ReplaceMany w/dictionary - For Each")]
public string ReplaceManyDictionaryForEach()
{
var result = Text;
// ReSharper disable once LoopCanBeConvertedToQuery
foreach (var item in Replacements)
{
result = result.Replace(item.Key, item.Value);
}
return result;
}
}
}
@@ -0,0 +1,44 @@
using System;
using System.Collections.Generic;
using BenchmarkDotNet.Attributes;
using Umbraco.Core;
namespace Umbraco.Tests.Benchmarks
{
[MemoryDiagnoser]
public class TryConvertToBenchmarks
{
private static readonly List<string> List = new List<string>() { "hello", "world", "awesome" };
private static readonly string Date = "Saturday 10, November 2012";
[Benchmark(Description = "List<string> to IEnumerable<string>")]
public IEnumerable<string> TryConvertToEnumerable()
{
return List.TryConvertTo<IEnumerable<string>>().Result;
}
[Benchmark(Description = "Int to Double")]
public double TryConvertToDouble()
{
return 1.TryConvertTo<double>().Result;
}
[Benchmark(Description = "Float to Decimal")]
public decimal TryConvertToDecimal()
{
return 1F.TryConvertTo<decimal>().Result;
}
[Benchmark(Description = "String to Boolean")]
public bool TryConvertToBoolean()
{
return "1".TryConvertTo<bool>().Result;
}
[Benchmark(Description = "String to DateTime")]
public DateTime TryConvertToDateTime()
{
return Date.TryConvertTo<DateTime>().Result;
}
}
}
@@ -9,11 +9,12 @@
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>Umbraco.Tests.Benchmarks</RootNamespace>
<AssemblyName>Umbraco.Tests.Benchmarks</AssemblyName>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<TargetFrameworkVersion>v4.6</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<NuGetPackageImportStamp>
</NuGetPackageImportStamp>
<TargetFrameworkProfile />
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
@@ -38,38 +39,55 @@
<RunPostBuildEvent>Always</RunPostBuildEvent>
</PropertyGroup>
<ItemGroup>
<Reference Include="BenchmarkDotNet, Version=0.9.9.0, Culture=neutral, PublicKeyToken=aa0ca2f9092cefc4, processorArchitecture=MSIL">
<HintPath>..\packages\BenchmarkDotNet.0.9.9\lib\net45\BenchmarkDotNet.dll</HintPath>
<Reference Include="BenchmarkDotNet, Version=0.10.12.0, Culture=neutral, PublicKeyToken=aa0ca2f9092cefc4, processorArchitecture=MSIL">
<HintPath>..\packages\BenchmarkDotNet.0.10.12\lib\net46\BenchmarkDotNet.dll</HintPath>
</Reference>
<Reference Include="BenchmarkDotNet.Core, Version=0.9.9.0, Culture=neutral, PublicKeyToken=aa0ca2f9092cefc4, processorArchitecture=MSIL">
<HintPath>..\packages\BenchmarkDotNet.Core.0.9.9\lib\net45\BenchmarkDotNet.Core.dll</HintPath>
<Reference Include="BenchmarkDotNet.Core, Version=0.10.12.0, Culture=neutral, PublicKeyToken=aa0ca2f9092cefc4, processorArchitecture=MSIL">
<HintPath>..\packages\BenchmarkDotNet.Core.0.10.12\lib\net46\BenchmarkDotNet.Core.dll</HintPath>
</Reference>
<Reference Include="BenchmarkDotNet.Diagnostics.Windows, Version=0.9.9.0, Culture=neutral, PublicKeyToken=aa0ca2f9092cefc4, processorArchitecture=MSIL">
<HintPath>..\packages\BenchmarkDotNet.Diagnostics.Windows.0.9.9\lib\net45\BenchmarkDotNet.Diagnostics.Windows.dll</HintPath>
</Reference>
<Reference Include="BenchmarkDotNet.Toolchains.Roslyn, Version=0.9.9.0, Culture=neutral, PublicKeyToken=aa0ca2f9092cefc4, processorArchitecture=MSIL">
<HintPath>..\packages\BenchmarkDotNet.Toolchains.Roslyn.0.9.9\lib\net45\BenchmarkDotNet.Toolchains.Roslyn.dll</HintPath>
<Reference Include="BenchmarkDotNet.Toolchains.Roslyn, Version=0.10.12.0, Culture=neutral, PublicKeyToken=aa0ca2f9092cefc4, processorArchitecture=MSIL">
<HintPath>..\packages\BenchmarkDotNet.Toolchains.Roslyn.0.10.12\lib\net46\BenchmarkDotNet.Toolchains.Roslyn.dll</HintPath>
</Reference>
<Reference Include="Castle.Core, Version=4.0.0.0, Culture=neutral, PublicKeyToken=407dd0808d44fbdc, processorArchitecture=MSIL">
<HintPath>..\packages\Castle.Core.4.0.0\lib\net45\Castle.Core.dll</HintPath>
</Reference>
<Reference Include="Microsoft.CodeAnalysis, Version=1.3.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.CodeAnalysis.Common.1.3.2\lib\net45\Microsoft.CodeAnalysis.dll</HintPath>
<Reference Include="Microsoft.CodeAnalysis, Version=2.4.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.CodeAnalysis.Common.2.4.0\lib\netstandard1.3\Microsoft.CodeAnalysis.dll</HintPath>
</Reference>
<Reference Include="Microsoft.CodeAnalysis.CSharp, Version=1.3.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.CodeAnalysis.CSharp.1.3.2\lib\net45\Microsoft.CodeAnalysis.CSharp.dll</HintPath>
<Reference Include="Microsoft.CodeAnalysis.CSharp, Version=2.4.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.CodeAnalysis.CSharp.2.4.0\lib\netstandard1.3\Microsoft.CodeAnalysis.CSharp.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Diagnostics.Tracing.TraceEvent, Version=1.0.41.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.Diagnostics.Tracing.TraceEvent.1.0.41\lib\net40\Microsoft.Diagnostics.Tracing.TraceEvent.dll</HintPath>
</Reference>
<Reference Include="Microsoft.DotNet.InternalAbstractions, Version=1.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.DotNet.InternalAbstractions.1.0.0\lib\net451\Microsoft.DotNet.InternalAbstractions.dll</HintPath>
</Reference>
<Reference Include="Microsoft.DotNet.PlatformAbstractions, Version=1.1.1.0, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.DotNet.PlatformAbstractions.1.1.1\lib\net451\Microsoft.DotNet.PlatformAbstractions.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Win32.Registry, Version=4.0.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.Win32.Registry.4.3.0\lib\net46\Microsoft.Win32.Registry.dll</HintPath>
</Reference>
<Reference Include="Moq, Version=4.1.1309.919, Culture=neutral, PublicKeyToken=69f491c39445e920, processorArchitecture=MSIL">
<HintPath>..\packages\Moq.4.1.1309.0919\lib\net40\Moq.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Collections.Immutable, Version=1.2.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.Collections.Immutable.1.2.0\lib\portable-net45+win8+wp8+wpa81\System.Collections.Immutable.dll</HintPath>
<Reference Include="System.AppContext, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.AppContext.4.3.0\lib\net46\System.AppContext.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System.Collections.Immutable, Version=1.2.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.Collections.Immutable.1.3.1\lib\portable-net45+win8+wp8+wpa81\System.Collections.Immutable.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System.ComponentModel.Composition" />
<Reference Include="System.Console, Version=4.0.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.Console.4.3.0\lib\net46\System.Console.dll</HintPath>
</Reference>
<Reference Include="System.Core" />
<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>
@@ -77,13 +95,52 @@
<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>
</Reference>
<Reference Include="System.Diagnostics.FileVersionInfo, Version=4.0.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.Diagnostics.FileVersionInfo.4.3.0\lib\net46\System.Diagnostics.FileVersionInfo.dll</HintPath>
</Reference>
<Reference Include="System.Diagnostics.StackTrace, Version=4.0.3.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.Diagnostics.StackTrace.4.3.0\lib\net46\System.Diagnostics.StackTrace.dll</HintPath>
</Reference>
<Reference Include="System.IO.Compression, Version=4.1.2.0, Culture=neutral, PublicKeyToken=b77a5c561934e089, processorArchitecture=MSIL">
<HintPath>..\packages\System.IO.Compression.4.3.0\lib\net46\System.IO.Compression.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System.IO.FileSystem, Version=4.0.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.IO.FileSystem.4.3.0\lib\net46\System.IO.FileSystem.dll</HintPath>
</Reference>
<Reference Include="System.IO.FileSystem.Primitives, Version=4.0.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.IO.FileSystem.Primitives.4.3.0\lib\net46\System.IO.FileSystem.Primitives.dll</HintPath>
</Reference>
<Reference Include="System.Management" />
<Reference Include="System.Numerics" />
<Reference Include="System.Reflection.Metadata, Version=1.3.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.Reflection.Metadata.1.3.0\lib\portable-net45+win8\System.Reflection.Metadata.dll</HintPath>
<Reference Include="System.Reflection.Metadata, Version=1.4.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.Reflection.Metadata.1.4.2\lib\portable-net45+win8\System.Reflection.Metadata.dll</HintPath>
</Reference>
<Reference Include="System.Threading.Tasks.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>..\packages\System.Threading.Tasks.Extensions.4.0.0\lib\portable-net45+win8+wp8+wpa81\System.Threading.Tasks.Extensions.dll</HintPath>
<Reference Include="System.Security.Cryptography.Algorithms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.Security.Cryptography.Algorithms.4.3.0\lib\net46\System.Security.Cryptography.Algorithms.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System.Security.Cryptography.Encoding, Version=4.0.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.Security.Cryptography.Encoding.4.3.0\lib\net46\System.Security.Cryptography.Encoding.dll</HintPath>
</Reference>
<Reference Include="System.Security.Cryptography.Primitives, Version=4.0.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.Security.Cryptography.Primitives.4.3.0\lib\net46\System.Security.Cryptography.Primitives.dll</HintPath>
</Reference>
<Reference Include="System.Security.Cryptography.X509Certificates, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.Security.Cryptography.X509Certificates.4.3.0\lib\net46\System.Security.Cryptography.X509Certificates.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System.Text.Encoding.CodePages, Version=4.0.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.Text.Encoding.CodePages.4.3.0\lib\net46\System.Text.Encoding.CodePages.dll</HintPath>
</Reference>
<Reference Include="System.Threading.Tasks.Extensions, Version=4.1.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>..\packages\System.Threading.Tasks.Extensions.4.3.0\lib\portable-net45+win8+wp8+wpa81\System.Threading.Tasks.Extensions.dll</HintPath>
</Reference>
<Reference Include="System.Threading.Thread, Version=4.0.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.Threading.Thread.4.3.0\lib\net46\System.Threading.Thread.dll</HintPath>
</Reference>
<Reference Include="System.ValueTuple, Version=4.0.1.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>..\packages\System.ValueTuple.4.3.0\lib\netstandard1.0\System.ValueTuple.dll</HintPath>
</Reference>
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
@@ -91,20 +148,38 @@
<Reference Include="System.Data" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Xml" />
<Reference Include="System.Xml.ReaderWriter, Version=4.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.Xml.ReaderWriter.4.3.0\lib\net46\System.Xml.ReaderWriter.dll</HintPath>
</Reference>
<Reference Include="System.Xml.XmlDocument, Version=4.0.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.Xml.XmlDocument.4.3.0\lib\net46\System.Xml.XmlDocument.dll</HintPath>
</Reference>
<Reference Include="System.Xml.XPath, Version=4.0.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.Xml.XPath.4.3.0\lib\net46\System.Xml.XPath.dll</HintPath>
</Reference>
<Reference Include="System.Xml.XPath.XDocument, Version=4.0.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.Xml.XPath.XDocument.4.3.0\lib\net46\System.Xml.XPath.XDocument.dll</HintPath>
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="ConcurrentDictionaryBenchmarks.cs" />
<Compile Include="Config\QuickRunConfigAttribute.cs" />
<Compile Include="Config\QuickRunWithMemoryDiagnoserConfigAttribute.cs" />
<Compile Include="LinqCastBenchmarks.cs" />
<Compile Include="ModelToSqlExpressionHelperBenchmarks.cs" />
<Compile Include="BulkInsertBenchmarks.cs" />
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="StringReplaceManyBenchmarks.cs" />
<Compile Include="TryConvertToBenchmarks.cs" />
<Compile Include="XmlBenchmarks.cs" />
<Compile Include="XmlPublishedContentInitBenchmarks.cs" />
</ItemGroup>
<ItemGroup>
<None Include="App.config" />
<None Include="packages.config" />
<None Include="_TraceEventProgrammersGuide.docx" />
<None Include="app.config" />
<None Include="packages.config">
<SubType>Designer</SubType>
</None>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Umbraco.Core\Umbraco.Core.csproj">
@@ -120,10 +195,6 @@
<Name>Umbraco.Web</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<Content Include="TraceEvent.ReadMe.txt" />
<Content Include="TraceEvent.ReleaseNotes.txt" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<PropertyGroup>
<PostBuildEvent>
+8 -31
View File
@@ -1,42 +1,19 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml;
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Configs;
using BenchmarkDotNet.Diagnostics.Windows;
using BenchmarkDotNet.Jobs;
using Umbraco.Tests.Benchmarks.Config;
namespace Umbraco.Tests.Benchmarks
{
[Config(typeof(Config))]
[QuickRunWithMemoryDiagnoserConfig]
public class XmlBenchmarks
{
private class Config : ManualConfig
{
public Config()
{
Add(new MemoryDiagnoser());
//Add(ExecutionValidator.FailOnError);
//The 'quick and dirty' settings, so it runs a little quicker
// see benchmarkdotnet FAQ
Add(Job.Default
.WithLaunchCount(1) // benchmark process will be launched only once
.WithIterationTime(100) // 100ms per iteration
.WithWarmupCount(3) // 3 warmup iteration
.WithTargetCount(3)); // 3 target iteration
}
}
[Setup]
[GlobalSetup]
public void Setup()
{
var templateId = 0;
var xmlText = @"<?xml version=""1.0"" encoding=""utf-8""?>
<!DOCTYPE root[
<!DOCTYPE root[
<!ELEMENT Home ANY>
<!ATTLIST Home id ID #REQUIRED>
<!ELEMENT CustomDocument ANY>
@@ -49,7 +26,7 @@ namespace Umbraco.Tests.Benchmarks
<umbracoNaviHide>1</umbracoNaviHide>
<Home id=""1173"" parentID=""1046"" level=""2"" writerID=""0"" creatorID=""0"" nodeType=""1044"" template=""" + templateId + @""" sortOrder=""2"" createDate=""2012-07-20T18:06:45"" updateDate=""2012-07-20T19:07:31"" nodeName=""Sub1"" urlName=""sub1"" writerName=""admin"" creatorName=""admin"" path=""-1,1046,1173"" isDoc="""">
<content><![CDATA[<div>This is some content</div>]]></content>
<umbracoUrlAlias><![CDATA[page2/alias, 2ndpagealias]]></umbracoUrlAlias>
<umbracoUrlAlias><![CDATA[page2/alias, 2ndpagealias]]></umbracoUrlAlias>
<Home id=""1174"" parentID=""1173"" level=""3"" writerID=""0"" creatorID=""0"" nodeType=""1044"" template=""" + templateId + @""" sortOrder=""2"" createDate=""2012-07-20T18:07:54"" updateDate=""2012-07-20T19:10:27"" nodeName=""Sub2"" urlName=""sub2"" writerName=""admin"" creatorName=""admin"" path=""-1,1046,1173,1174"" isDoc="""">
<content><![CDATA[]]></content>
<umbracoUrlAlias><![CDATA[only/one/alias]]></umbracoUrlAlias>
@@ -70,7 +47,7 @@ namespace Umbraco.Tests.Benchmarks
_xml.LoadXml(xmlText);
}
[Cleanup]
[GlobalCleanup]
public void Cleanup()
{
_xml = null;
@@ -90,7 +67,7 @@ namespace Umbraco.Tests.Benchmarks
public void XmlWithNavigation()
{
var elt = _xml.DocumentElement;
var id = NavigateElementRoute(elt, new[] {"home", "sub1", "sub2"});
var id = NavigateElementRoute(elt, new[] { "home", "sub1", "sub2" });
if (id <= 0) Console.WriteLine("ERR");
}
@@ -120,4 +97,4 @@ namespace Umbraco.Tests.Benchmarks
return found ? int.Parse(elt.GetAttribute("id")) : -1;
}
}
}
}
@@ -3,37 +3,17 @@ using System.Collections.Generic;
using System.Linq;
using System.Xml;
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Configs;
using BenchmarkDotNet.Diagnostics.Windows;
using BenchmarkDotNet.Jobs;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Umbraco.Core;
using Umbraco.Core.Configuration;
using Umbraco.Core.Models;
using Umbraco.Core.Models.PublishedContent;
using Umbraco.Tests.Benchmarks.Config;
using Umbraco.Web.PublishedCache.XmlPublishedCache;
namespace Umbraco.Tests.Benchmarks
{
[Config(typeof(Config))]
[QuickRunWithMemoryDiagnoserConfig]
public class XmlPublishedContentInitBenchmarks
{
private class Config : ManualConfig
{
public Config()
{
Add(new MemoryDiagnoser());
//The 'quick and dirty' settings, so it runs a little quicker
// see benchmarkdotnet FAQ
Add(Job.Default
.WithLaunchCount(1) // benchmark process will be launched only once
.WithIterationTime(100) // 100ms per iteration
.WithWarmupCount(3) // 3 warmup iteration
.WithTargetCount(3)); // 3 target iteration
}
}
public XmlPublishedContentInitBenchmarks()
{
_xml10 = Build(10);
@@ -281,7 +261,7 @@ namespace Umbraco.Tests.Benchmarks
var nodes = xmlNode.SelectNodes(dataXPath);
contentType = GetPublishedContentType(PublishedItemType.Content, docTypeAlias);
var propertyNodes = new Dictionary<string, XmlNode>();
if (nodes != null)
foreach (XmlNode n in nodes)
@@ -307,8 +287,8 @@ namespace Umbraco.Tests.Benchmarks
private static PublishedContentType GetPublishedContentType(PublishedItemType type, string alias)
{
return new PublishedContentType(alias, new string[] {},
new List<PublishedPropertyType>(Enumerable.Range(0, 10).Select(x => new PublishedPropertyType("prop" + x, 0, "test", initConverters:false))));
return new PublishedContentType(alias, new string[] { },
new List<PublishedPropertyType>(Enumerable.Range(0, 10).Select(x => new PublishedPropertyType("prop" + x, 0, "test", initConverters: false))));
}
}
@@ -1,16 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
</startup>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Data.SqlServerCe" publicKeyToken="89845dcd8080cc91" />
<bindingRedirect oldVersion="0.0.0.0-4.0.0.1" newVersion="4.0.0.1" />
<assemblyIdentity name="System.IO.Compression" publicKeyToken="b77a5c561934e089" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.1.2.0" newVersion="4.1.2.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Collections.Immutable" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-1.2.1.0" newVersion="1.2.1.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="log4net" publicKeyToken="669e0ddf0bb1aa2a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-2.0.8.0" newVersion="2.0.8.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Microsoft.Owin" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-3.1.0.0" newVersion="3.1.0.0" />
@@ -27,6 +30,10 @@
<assemblyIdentity name="Microsoft.Owin.Security.Cookies" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-3.1.0.0" newVersion="3.1.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-10.0.0.0" newVersion="10.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-5.2.3.0" newVersion="5.2.3.0" />
@@ -36,45 +43,25 @@
<bindingRedirect oldVersion="0.0.0.0-3.0.0.0" newVersion="3.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Web.Http" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-5.2.3.0" newVersion="5.2.3.0" />
<assemblyIdentity name="BenchmarkDotNet.Core" publicKeyToken="aa0ca2f9092cefc4" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-0.10.12.0" newVersion="0.10.12.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Net.Http.Formatting" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-5.2.3.0" newVersion="5.2.3.0" />
<assemblyIdentity name="System.IO.FileSystem" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.2.0" newVersion="4.0.2.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-10.0.0.0" newVersion="10.0.0.0" />
<assemblyIdentity name="System.IO.FileSystem.Primitives" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.2.0" newVersion="4.0.2.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Collections.Immutable" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-1.2.0.0" newVersion="1.2.0.0" />
<assemblyIdentity name="System.Security.Cryptography.Primitives" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.1.0" newVersion="4.0.1.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Runtime" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.1.0.0" newVersion="4.1.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Runtime.InteropServices" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.1.0.0" newVersion="4.1.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Reflection.Metadata" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-1.3.0.0" newVersion="1.3.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Reflection" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.1.0.0" newVersion="4.1.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Runtime.Extensions" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.1.0.0" newVersion="4.1.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="log4net" publicKeyToken="669e0ddf0bb1aa2a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-2.0.8.0" newVersion="2.0.8.0" />
<assemblyIdentity name="System.Xml.XPath.XDocument" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.2.0" newVersion="4.0.2.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>
</configuration>
+50 -29
View File
@@ -1,40 +1,61 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="BenchmarkDotNet" version="0.9.9" targetFramework="net45" />
<package id="BenchmarkDotNet.Core" version="0.9.9" targetFramework="net45" />
<package id="BenchmarkDotNet" version="0.10.12" targetFramework="net46" />
<package id="BenchmarkDotNet.Core" version="0.10.12" targetFramework="net46" />
<package id="BenchmarkDotNet.Diagnostics.Windows" version="0.9.9" targetFramework="net45" />
<package id="BenchmarkDotNet.Toolchains.Roslyn" version="0.9.9" targetFramework="net45" />
<package id="BenchmarkDotNet.Toolchains.Roslyn" version="0.10.12" targetFramework="net46" />
<package id="Castle.Core" version="4.0.0" targetFramework="net45" />
<package id="Microsoft.CodeAnalysis.Analyzers" version="1.1.0" targetFramework="net45" />
<package id="Microsoft.CodeAnalysis.Common" version="1.3.2" targetFramework="net45" />
<package id="Microsoft.CodeAnalysis.CSharp" version="1.3.2" targetFramework="net45" />
<package id="Microsoft.CodeAnalysis.Common" version="2.4.0" targetFramework="net46" />
<package id="Microsoft.CodeAnalysis.CSharp" version="2.4.0" targetFramework="net46" />
<package id="Microsoft.Diagnostics.Tracing.TraceEvent" version="1.0.41" targetFramework="net45" />
<package id="Microsoft.DotNet.InternalAbstractions" version="1.0.0" targetFramework="net46" />
<package id="Microsoft.DotNet.PlatformAbstractions" version="1.1.1" targetFramework="net46" />
<package id="Microsoft.SqlServer.Compact" version="4.0.8854.1" targetFramework="net45" />
<package id="Microsoft.Win32.Registry" version="4.3.0" targetFramework="net46" />
<package id="Moq" version="4.1.1309.0919" targetFramework="net45" />
<package id="SqlServerCE" version="4.0.0.1" targetFramework="net45" />
<package id="System.Collections" version="4.0.11" targetFramework="net45" />
<package id="System.Collections.Concurrent" version="4.0.12" targetFramework="net45" />
<package id="System.Collections.Immutable" version="1.2.0" targetFramework="net45" />
<package id="System.Diagnostics.Debug" version="4.0.11" targetFramework="net45" />
<package id="System.Diagnostics.Tools" version="4.0.1" targetFramework="net45" />
<package id="System.Dynamic.Runtime" version="4.0.11" targetFramework="net45" />
<package id="System.Globalization" version="4.0.11" targetFramework="net45" />
<package id="System.Linq" version="4.1.0" targetFramework="net45" />
<package id="System.Linq.Expressions" version="4.1.0" targetFramework="net45" />
<package id="System.Reflection" version="4.1.0" targetFramework="net45" />
<package id="System.Reflection.Metadata" version="1.3.0" targetFramework="net45" />
<package id="System.AppContext" version="4.3.0" targetFramework="net46" />
<package id="System.Collections" version="4.3.0" targetFramework="net46" />
<package id="System.Collections.Concurrent" version="4.3.0" targetFramework="net46" />
<package id="System.Collections.Immutable" version="1.3.1" targetFramework="net46" />
<package id="System.Console" version="4.3.0" targetFramework="net46" />
<package id="System.Diagnostics.Debug" version="4.3.0" targetFramework="net46" />
<package id="System.Diagnostics.FileVersionInfo" version="4.3.0" targetFramework="net46" />
<package id="System.Diagnostics.StackTrace" version="4.3.0" targetFramework="net46" />
<package id="System.Diagnostics.Tools" version="4.3.0" targetFramework="net46" />
<package id="System.Dynamic.Runtime" version="4.3.0" targetFramework="net46" />
<package id="System.Globalization" version="4.3.0" targetFramework="net46" />
<package id="System.IO.Compression" version="4.3.0" targetFramework="net46" />
<package id="System.IO.FileSystem" version="4.3.0" targetFramework="net46" />
<package id="System.IO.FileSystem.Primitives" version="4.3.0" targetFramework="net46" />
<package id="System.Linq" version="4.3.0" targetFramework="net46" />
<package id="System.Linq.Expressions" version="4.3.0" targetFramework="net46" />
<package id="System.Reflection" version="4.3.0" targetFramework="net46" />
<package id="System.Reflection.Metadata" version="1.4.2" targetFramework="net46" />
<package id="System.Reflection.Primitives" version="4.0.1" targetFramework="net45" />
<package id="System.Resources.ResourceManager" version="4.0.1" targetFramework="net45" />
<package id="System.Runtime" version="4.1.0" targetFramework="net45" />
<package id="System.Runtime.Extensions" version="4.1.0" targetFramework="net45" />
<package id="System.Runtime.InteropServices" version="4.1.0" targetFramework="net45" />
<package id="System.Runtime.Numerics" version="4.0.1" targetFramework="net45" />
<package id="System.Text.Encoding" version="4.0.11" targetFramework="net45" />
<package id="System.Text.Encoding.Extensions" version="4.0.11" targetFramework="net45" />
<package id="System.Threading" version="4.0.11" targetFramework="net45" />
<package id="System.Threading.Tasks" version="4.0.11" targetFramework="net45" />
<package id="System.Threading.Tasks.Extensions" version="4.0.0" targetFramework="net45" />
<package id="System.Threading.Tasks.Parallel" version="4.0.1" targetFramework="net45" />
<package id="System.Xml.ReaderWriter" version="4.0.11" targetFramework="net45" />
<package id="System.Xml.XDocument" version="4.0.11" targetFramework="net45" />
<package id="System.Resources.ResourceManager" version="4.3.0" targetFramework="net46" />
<package id="System.Runtime" version="4.3.0" targetFramework="net46" />
<package id="System.Runtime.Extensions" version="4.3.0" targetFramework="net46" />
<package id="System.Runtime.InteropServices" version="4.3.0" targetFramework="net46" />
<package id="System.Runtime.Numerics" version="4.3.0" targetFramework="net46" />
<package id="System.Security.Cryptography.Algorithms" version="4.3.0" targetFramework="net46" />
<package id="System.Security.Cryptography.Encoding" version="4.3.0" targetFramework="net46" />
<package id="System.Security.Cryptography.Primitives" version="4.3.0" targetFramework="net46" />
<package id="System.Security.Cryptography.X509Certificates" version="4.3.0" targetFramework="net46" />
<package id="System.Text.Encoding" version="4.3.0" targetFramework="net46" />
<package id="System.Text.Encoding.CodePages" version="4.3.0" targetFramework="net46" />
<package id="System.Text.Encoding.Extensions" version="4.3.0" targetFramework="net46" />
<package id="System.Threading" version="4.3.0" targetFramework="net46" />
<package id="System.Threading.Tasks" version="4.3.0" targetFramework="net46" />
<package id="System.Threading.Tasks.Extensions" version="4.3.0" targetFramework="net46" />
<package id="System.Threading.Tasks.Parallel" version="4.3.0" targetFramework="net46" />
<package id="System.Threading.Thread" version="4.3.0" targetFramework="net46" />
<package id="System.ValueTuple" version="4.3.0" targetFramework="net46" />
<package id="System.Xml.ReaderWriter" version="4.3.0" targetFramework="net46" />
<package id="System.Xml.XDocument" version="4.3.0" targetFramework="net46" />
<package id="System.Xml.XmlDocument" version="4.3.0" targetFramework="net46" />
<package id="System.Xml.XmlSerializer" version="4.3.0" targetFramework="net46" />
<package id="System.Xml.XPath" version="4.3.0" targetFramework="net46" />
<package id="System.Xml.XPath.XDocument" version="4.3.0" targetFramework="net46" />
</packages>
+153 -11
View File
@@ -6,6 +6,10 @@ using System.Threading;
using System.Web.UI.WebControls;
using NUnit.Framework;
using Umbraco.Core;
using Umbraco.Core.ObjectResolution;
using Umbraco.Core.PropertyEditors;
using Umbraco.Core.Strings;
using Umbraco.Tests.TestHelpers;
namespace Umbraco.Tests
{
@@ -155,16 +159,151 @@ namespace Umbraco.Tests
Assert.AreEqual("Hello world", result.Result);
}
[Test]
[Test]
public virtual void CanConvertObjectToSameObject()
{
var obj = new MyTestObject();
var result = obj.TryConvertTo<object>();
Assert.AreEqual(obj, result.Result);
Assert.AreEqual(obj, result.Result);
}
private CultureInfo savedCulture;
[Test]
public void ConvertToIntegerTest()
{
var conv = "100".TryConvertTo<int>();
Assert.IsTrue(conv);
Assert.AreEqual(100, conv.Result);
conv = "100.000".TryConvertTo<int>();
Assert.IsTrue(conv);
Assert.AreEqual(100, conv.Result);
conv = "100,000".TryConvertTo<int>();
Assert.IsTrue(conv);
Assert.AreEqual(100, conv.Result);
// oops
conv = "100.001".TryConvertTo<int>();
Assert.IsTrue(conv);
Assert.AreEqual(100, conv.Result);
conv = 100m.TryConvertTo<int>();
Assert.IsTrue(conv);
Assert.AreEqual(100, conv.Result);
conv = 100.000m.TryConvertTo<int>();
Assert.IsTrue(conv);
Assert.AreEqual(100, conv.Result);
// oops
conv = 100.001m.TryConvertTo<int>();
Assert.IsTrue(conv);
Assert.AreEqual(100, conv.Result);
}
[Test]
public void ConvertToDecimalTest()
{
var conv = "100".TryConvertTo<decimal>();
Assert.IsTrue(conv);
Assert.AreEqual(100m, conv.Result);
conv = "100.000".TryConvertTo<decimal>();
Assert.IsTrue(conv);
Assert.AreEqual(100m, conv.Result);
conv = "100,000".TryConvertTo<decimal>();
Assert.IsTrue(conv);
Assert.AreEqual(100m, conv.Result);
conv = "100.001".TryConvertTo<decimal>();
Assert.IsTrue(conv);
Assert.AreEqual(100.001m, conv.Result);
conv = 100m.TryConvertTo<decimal>();
Assert.IsTrue(conv);
Assert.AreEqual(100m, conv.Result);
conv = 100.000m.TryConvertTo<decimal>();
Assert.IsTrue(conv);
Assert.AreEqual(100m, conv.Result);
conv = 100.001m.TryConvertTo<decimal>();
Assert.IsTrue(conv);
Assert.AreEqual(100.001m, conv.Result);
conv = 100.TryConvertTo<decimal>();
Assert.IsTrue(conv);
Assert.AreEqual(100m, conv.Result);
}
[Test]
public void ConvertToNullableDecimalTest()
{
var conv = "100".TryConvertTo<decimal?>();
Assert.IsTrue(conv);
Assert.AreEqual(100m, conv.Result);
conv = "100.000".TryConvertTo<decimal?>();
Assert.IsTrue(conv);
Assert.AreEqual(100m, conv.Result);
conv = "100,000".TryConvertTo<decimal?>();
Assert.IsTrue(conv);
Assert.AreEqual(100m, conv.Result);
conv = "100.001".TryConvertTo<decimal?>();
Assert.IsTrue(conv);
Assert.AreEqual(100.001m, conv.Result);
conv = 100m.TryConvertTo<decimal?>();
Assert.IsTrue(conv);
Assert.AreEqual(100m, conv.Result);
conv = 100.000m.TryConvertTo<decimal?>();
Assert.IsTrue(conv);
Assert.AreEqual(100m, conv.Result);
conv = 100.001m.TryConvertTo<decimal?>();
Assert.IsTrue(conv);
Assert.AreEqual(100.001m, conv.Result);
conv = 100.TryConvertTo<decimal?>();
Assert.IsTrue(conv);
Assert.AreEqual(100m, conv.Result);
}
[Test]
public void ConvertToDateTimeTest()
{
var conv = "2016-06-07".TryConvertTo<DateTime>();
Assert.IsTrue(conv);
Assert.AreEqual(new DateTime(2016, 6, 7), conv.Result);
}
[Test]
public void ConvertToNullableDateTimeTest()
{
var conv = "2016-06-07".TryConvertTo<DateTime?>();
Assert.IsTrue(conv);
Assert.AreEqual(new DateTime(2016, 6, 7), conv.Result);
}
[Test]
public void Value_Editor_Can_Convert_Decimal_To_Decimal_Clr_Type()
{
var valueEditor = new PropertyValueEditor
{
ValueType = PropertyEditorValueTypes.Decimal
};
var result = valueEditor.TryConvertValueToCrlType(12.34d);
Assert.IsTrue(result.Success);
Assert.AreEqual(12.34d, result.Result);
}
private CultureInfo _savedCulture;
/// <summary>
/// Run once before each test in derived test fixtures.
@@ -172,10 +311,13 @@ namespace Umbraco.Tests
[SetUp]
public void TestSetup()
{
savedCulture = Thread.CurrentThread.CurrentCulture;
_savedCulture = Thread.CurrentThread.CurrentCulture;
Thread.CurrentThread.CurrentCulture = new CultureInfo("en-GB"); // make sure the dates parse correctly
return;
}
var settings = SettingsForTests.GetDefault();
ShortStringHelperResolver.Current = new ShortStringHelperResolver(new DefaultShortStringHelper(settings).WithDefaultConfig());
Resolution.Freeze();
}
/// <summary>
/// Run once after each test in derived test fixtures.
@@ -183,9 +325,9 @@ namespace Umbraco.Tests
[TearDown]
public void TestTearDown()
{
Thread.CurrentThread.CurrentCulture = savedCulture;
return;
}
Thread.CurrentThread.CurrentCulture = _savedCulture;
ShortStringHelperResolver.Reset();
}
private class MyTestObject
{
@@ -195,4 +337,4 @@ namespace Umbraco.Tests
}
}
}
}
}
@@ -332,6 +332,9 @@ namespace Umbraco.Tests.Persistence.Repositories
var contentType = (IContentType)MockedContentTypes.CreateSimpleContentType2("test", "Test", propertyGroupName: "testGroup");
Assert.AreEqual(4, contentType.PropertyTypes.Count());
// remove all templates - since they are not saved, they would break the (wtf) mapping code
contentType.AllowedTemplates = new ITemplate[0];
// there is NO mapping from display to contentType, but only from save
// to contentType, so if we want to test, let's to it properly!
@@ -24,7 +24,9 @@ namespace Umbraco.Tests.Persistence.Repositories
[TestCase("Alpha (10)", "Alpha (2)", +1)] // this is the real stuff
[TestCase("Kilo", "Golf (2)", +1)]
[TestCase("Kilo (1)", "Golf (2)", +1)]
public void ComparerTest(string name1, string name2, int expected)
[TestCase("", "", 0)]
[TestCase(null, null, 0)]
public void ComparerTest(string name1, string name2, int expected)
{
var comparer = new SimilarNodeName.Comparer();
@@ -76,7 +78,9 @@ namespace Umbraco.Tests.Persistence.Repositories
[TestCase(0, "Alpha", "Alpha (3)")]
[TestCase(0, "Kilo (1)", "Kilo (1) (1)")] // though... we might consider "Kilo (2)"
[TestCase(6, "Kilo (1)", "Kilo (1)")] // because of the id
public void Test(int nodeId, string nodeName, string expected)
[TestCase(0, "", " (1)")]
[TestCase(0, null, " (1)")]
public void Test(int nodeId, string nodeName, string expected)
{
var names = new[]
{
-105
View File
@@ -1,105 +0,0 @@
using System;
using NUnit.Framework;
using Umbraco.Core;
using Umbraco.Core.ObjectResolution;
using Umbraco.Core.Strings;
using Umbraco.Tests.TestHelpers;
namespace Umbraco.Tests
{
[TestFixture]
public class TryConvertToTests
{
[SetUp]
public void SetUp()
{
var settings = SettingsForTests.GetDefault();
ShortStringHelperResolver.Current = new ShortStringHelperResolver(new DefaultShortStringHelper(settings).WithDefaultConfig());
Resolution.Freeze();
}
[TearDown]
public void TearDown()
{
ShortStringHelperResolver.Reset();
}
[Test]
public void ConvertToIntegerTest()
{
var conv = "100".TryConvertTo<int>();
Assert.IsTrue(conv);
Assert.AreEqual(100, conv.Result);
conv = "100.000".TryConvertTo<int>();
Assert.IsTrue(conv);
Assert.AreEqual(100, conv.Result);
conv = "100,000".TryConvertTo<int>();
Assert.IsTrue(conv);
Assert.AreEqual(100, conv.Result);
// oops
conv = "100.001".TryConvertTo<int>();
Assert.IsTrue(conv);
Assert.AreEqual(100, conv.Result);
conv = 100m.TryConvertTo<int>();
Assert.IsTrue(conv);
Assert.AreEqual(100, conv.Result);
conv = 100.000m.TryConvertTo<int>();
Assert.IsTrue(conv);
Assert.AreEqual(100, conv.Result);
// oops
conv = 100.001m.TryConvertTo<int>();
Assert.IsTrue(conv);
Assert.AreEqual(100, conv.Result);
}
[Test]
public void ConvertToDecimalTest()
{
var conv = "100".TryConvertTo<decimal>();
Assert.IsTrue(conv);
Assert.AreEqual(100m, conv.Result);
conv = "100.000".TryConvertTo<decimal>();
Assert.IsTrue(conv);
Assert.AreEqual(100m, conv.Result);
conv = "100,000".TryConvertTo<decimal>();
Assert.IsTrue(conv);
Assert.AreEqual(100m, conv.Result);
conv = "100.001".TryConvertTo<decimal>();
Assert.IsTrue(conv);
Assert.AreEqual(100.001m, conv.Result);
conv = 100m.TryConvertTo<decimal>();
Assert.IsTrue(conv);
Assert.AreEqual(100m, conv.Result);
conv = 100.000m.TryConvertTo<decimal>();
Assert.IsTrue(conv);
Assert.AreEqual(100m, conv.Result);
conv = 100.001m.TryConvertTo<decimal>();
Assert.IsTrue(conv);
Assert.AreEqual(100.001m, conv.Result);
conv = 100.TryConvertTo<decimal>();
Assert.IsTrue(conv);
Assert.AreEqual(100m, conv.Result);
}
[Test]
public void ConvertToDateTimeTest()
{
var conv = "2016-06-07".TryConvertTo<DateTime>();
Assert.IsTrue(conv);
Assert.AreEqual(new DateTime(2016, 6, 7), conv.Result);
}
}
}
-1
View File
@@ -231,7 +231,6 @@
<Compile Include="Services\CachedDataTypeServiceTests.cs" />
<Compile Include="TestHelpers\Entities\MockedPropertyTypes.cs" />
<Compile Include="TestHelpers\Entities\MockedUserGroup.cs" />
<Compile Include="TryConvertToTests.cs" />
<Compile Include="UdiTests.cs" />
<Compile Include="UmbracoExamine\RandomIdRAMDirectory.cs" />
<Compile Include="UmbracoExamine\UmbracoContentIndexerTests.cs" />
@@ -185,6 +185,8 @@
$scope.page.buttonGroupState = "success";
}, function(err) {
$scope.page.buttonGroupState = 'error';
});
}
@@ -14,7 +14,6 @@ function SearchController($scope, searchService, $log, $location, navigationServ
$scope.isSearching = false;
$scope.selectedResult = -1;
$scope.navigateResults = function (ev) {
//38: up 40: down, 13: enter
@@ -34,12 +33,14 @@ function SearchController($scope, searchService, $log, $location, navigationServ
}
};
var group = undefined;
var groupIndex = -1;
var itemIndex = -1;
$scope.selectedItem = undefined;
$scope.clearSearch = function () {
$scope.searchTerm = null;
};
function iterateResults(up) {
//default group
@@ -18,7 +18,7 @@
<div class="control-group">
<label class="control-label" for="email">Email</label>
<div class="controls">
<input type="email" id="email" name="email" placeholder="you@example.com" required ng-model="installer.current.model.email" val-email />
<input type="email" id="email" name="email" placeholder="you@example.com" val-email required ng-model="installer.current.model.email" />
<small class="inline-help">Your email will be used as your login</small>
</div>
</div>
@@ -31,13 +31,13 @@
.nested-content__item--active:not(.nested-content__item--single)
{
background: #f8f8f8;
background: @gray-10;
}
.nested-content__item.ui-sortable-placeholder
{
background: #f8f8f8;
border: 1px dashed #d9d9d9;
background: @gray-10;
border-bottom: 1px dashed @purple-l3;
visibility: visible !important;
height: 55px;
margin-top: -1px;
@@ -56,7 +56,7 @@
.nested-content__header-bar
{
padding: 15px 20px;
border-bottom: 1px dashed #e0e0e0;
border-bottom: 1px dashed @purple-l3;
text-align: right;
cursor: pointer;
background-color: white;
@@ -113,8 +113,8 @@
.nested-content__icon--active
{
color: white;
background: #2e8aea;
border-color: #2e8aea;
background: @turquoise-d1;
border-color: @turquoise-d1;
text-decoration: none;
}
@@ -146,7 +146,7 @@
.nested-content__content
{
border-bottom: 1px dashed #e0e0e0;
border-bottom: 1px dashed @purple-l3;
}
.nested-content__content .umb-control-group {
@@ -165,7 +165,7 @@
clear: both;
font-size: 14px;
color: #555;
background: #f8f8f8;
background: @gray-10;
border-radius: 15px;
}
@@ -240,6 +240,7 @@
.umb-tree .umb-tree-node-checked i:before {
/*check box*/
content: "\e165" !important;
font-family: inherit;
}
a.umb-options {
@@ -1,4 +1,4 @@
<form novalidate name="insertMacroForm" ng-submit="submitForm()" ng-controller="Umbraco.Dialogs.InsertMacroController" val-form-manager>
<form novalidate name="insertMacroForm" ng-controller="Umbraco.Dialogs.InsertMacroController" val-form-manager>
<div class="umb-panel">
<div class="umb-panel-footer">
@@ -6,8 +6,8 @@
<a href class="btn btn-link" ng-click="close()">
<localize key="cancel" />
</a>
<button type="submit" class="btn btn-primary">
<localize key="buttons_select"/>
<button type="button" ng-click="submitForm()" class="btn btn-primary">
<localize key="buttons_select" />
</button>
</div>
</div>
@@ -36,9 +36,14 @@
<umb-load-indicator ng-if="isSearching"></umb-load-indicator>
<umb-empty-state ng-if="!hasResults && !isSearching"
position="center">
<umb-empty-state ng-if="!hasResults && !isSearching" position="center">
<localize key="general_searchNoResult"></localize>
<br />
<button type="button" class="btn umb-button__button btn-info umb-button--" ng-click="clearSearch()" hotkey="" hotkey-when-hidden="">
<span class="umb-button__content">
<localize key="general_clearSearch" class="ng-isolate-scope ng-scope ng-binding">Clear Search</localize>
</span>
</button>
</umb-empty-state>
<ul class="umb-tree" ng-if="!isSearching && hasResults">
@@ -8,7 +8,7 @@
<a href="" ng-click="createMediaType()" umb-auto-focus>
<i class="large icon-item-arrangement"></i>
<span class="menu-label">
<localize key="general_new">New</localize>&nbsp;
<localize key="general_new">New</localize>
<localize key="content_mediatype">Media type</localize>
</span>
</a>
@@ -1,46 +1,46 @@
function ColorPickerController($scope) {
$scope.isConfigured = $scope.model.config && $scope.model.config.items && _.keys($scope.model.config.items).length > 0;
if ($scope.isConfigured) {
for (var key in $scope.model.config.items) {
if (!$scope.model.config.items[key].hasOwnProperty("value"))
$scope.model.config.items[key] = { value: $scope.model.config.items[key], label: $scope.model.config.items[key] };
}
$scope.model.useLabel = isTrue($scope.model.config.useLabel);
initActiveColor();
}
function ColorPickerController($scope) {
$scope.isConfigured = $scope.model.config && $scope.model.config.items && _.keys($scope.model.config.items).length > 0;
if ($scope.isConfigured) {
for (var key in $scope.model.config.items) {
if (!$scope.model.config.items[key].hasOwnProperty("value"))
$scope.model.config.items[key] = { value: $scope.model.config.items[key], label: $scope.model.config.items[key] };
}
$scope.model.useLabel = isTrue($scope.model.config.useLabel);
initActiveColor();
}
$scope.toggleItem = function (color) {
var currentColor = ($scope.model.value && $scope.model.value.hasOwnProperty("value"))
? $scope.model.value.value
: $scope.model.value;
$scope.toggleItem = function (color) {
var currentColor = $scope.model.value.hasOwnProperty("value")
? $scope.model.value.value
: $scope.model.value;
var newColor;
if (currentColor === color.value) {
// deselect
$scope.model.value = $scope.model.useLabel ? { value: "", label: "" } : "";
newColor = "";
}
else {
if (currentColor === color.value) {
// deselect
$scope.model.value = $scope.model.useLabel ? { value: "", label: "" } : "";
newColor = "";
}
else {
// select
$scope.model.value = $scope.model.useLabel ? { value: color.value, label: color.label } : color.value;
$scope.model.value = $scope.model.useLabel ? { value: color.value, label: color.label } : color.value;
newColor = color.value;
}
// this is required to re-validate
$scope.propertyForm.modelValue.$setViewValue(newColor);
};
}
// this is required to re-validate
$scope.propertyForm.modelValue.$setViewValue(newColor);
};
// Method required by the valPropertyValidator directive (returns true if the property editor has at least one color selected)
$scope.validateMandatory = function () {
var isValid = !$scope.model.validation.mandatory || (
$scope.model.value != null
&& $scope.model.value != ""
&& (!$scope.model.value.hasOwnProperty("value") || $scope.model.value.value !== "")
$scope.validateMandatory = function () {
var isValid = !$scope.model.validation.mandatory || (
$scope.model.value != null
&& $scope.model.value != ""
&& (!$scope.model.value.hasOwnProperty("value") || $scope.model.value.value !== "")
);
return {
isValid: isValid,
@@ -48,83 +48,83 @@ function ColorPickerController($scope) {
errorKey: "required"
};
}
$scope.isConfigured = $scope.model.config && $scope.model.config.items && _.keys($scope.model.config.items).length > 0;
// A color is active if it matches the value and label of the model.
// If the model doesn't store the label, ignore the label during the comparison.
$scope.isActiveColor = function (color) {
// no value
if (!$scope.model.value)
return false;
// Complex color (value and label)?
if (!$scope.model.value.hasOwnProperty("value"))
return $scope.model.value === color.value;
return $scope.model.value.value === color.value && $scope.model.value.label === color.label;
};
// Finds the color best matching the model's color,
// and sets the model color to that one. This is useful when
// either the value or label was changed on the data type.
function initActiveColor() {
// no value
if (!$scope.model.value)
return;
// Complex color (value and label)?
if (!$scope.model.value.hasOwnProperty("value"))
return;
var modelColor = $scope.model.value.value;
var modelLabel = $scope.model.value.label;
// Check for a full match or partial match.
var foundItem = null;
// Look for a fully matching color.
for (var key in $scope.model.config.items) {
var item = $scope.model.config.items[key];
if (item.value == modelColor && item.label == modelLabel) {
foundItem = item;
break;
}
}
// Look for a color with a matching value.
if (!foundItem) {
for (var key in $scope.model.config.items) {
var item = $scope.model.config.items[key];
if (item.value == modelColor) {
foundItem = item;
break;
}
}
}
// Look for a color with a matching label.
if (!foundItem) {
for (var key in $scope.model.config.items) {
var item = $scope.model.config.items[key];
if (item.label == modelLabel) {
foundItem = item;
break;
}
}
}
// If a match was found, set it as the active color.
if (foundItem) {
$scope.model.value.value = foundItem.value;
$scope.model.value.label = foundItem.label;
}
}
// figures out if a value is trueish enough
function isTrue(bool) {
return !!bool && bool !== "0" && angular.lowercase(bool) !== "false";
$scope.isConfigured = $scope.model.config && $scope.model.config.items && _.keys($scope.model.config.items).length > 0;
// A color is active if it matches the value and label of the model.
// If the model doesn't store the label, ignore the label during the comparison.
$scope.isActiveColor = function (color) {
// no value
if (!$scope.model.value)
return false;
// Complex color (value and label)?
if (!$scope.model.value.hasOwnProperty("value"))
return $scope.model.value === color.value;
return $scope.model.value.value === color.value && $scope.model.value.label === color.label;
};
// Finds the color best matching the model's color,
// and sets the model color to that one. This is useful when
// either the value or label was changed on the data type.
function initActiveColor() {
// no value
if (!$scope.model.value)
return;
// Complex color (value and label)?
if (!$scope.model.value.hasOwnProperty("value"))
return;
var modelColor = $scope.model.value.value;
var modelLabel = $scope.model.value.label;
// Check for a full match or partial match.
var foundItem = null;
// Look for a fully matching color.
for (var key in $scope.model.config.items) {
var item = $scope.model.config.items[key];
if (item.value == modelColor && item.label == modelLabel) {
foundItem = item;
break;
}
}
// Look for a color with a matching value.
if (!foundItem) {
for (var key in $scope.model.config.items) {
var item = $scope.model.config.items[key];
if (item.value == modelColor) {
foundItem = item;
break;
}
}
}
// Look for a color with a matching label.
if (!foundItem) {
for (var key in $scope.model.config.items) {
var item = $scope.model.config.items[key];
if (item.label == modelLabel) {
foundItem = item;
break;
}
}
}
// If a match was found, set it as the active color.
if (foundItem) {
$scope.model.value.value = foundItem.value;
$scope.model.value.label = foundItem.label;
}
}
// figures out if a value is trueish enough
function isTrue(bool) {
return !!bool && bool !== "0" && angular.lowercase(bool) !== "false";
}
}
@@ -261,7 +261,7 @@ angular.module("umbraco")
$scope.openEditorOverlay = function(event, area, index, key) {
$scope.editorOverlay = {
view: "itempicker",
filter: false,
filter: area.$allowedEditors.length > 15,
title: localizationService.localize("grid_insertControl"),
availableItems: area.$allowedEditors,
event: event,
@@ -860,6 +860,14 @@ angular.module("umbraco")
gridService.getGridEditors().then(function (response) {
$scope.availableEditors = response.data;
//Localize the grid editor names
angular.forEach($scope.availableEditors, function (value, key) {
//If no translation is provided, keep using the editor name from the manifest
if (localizationService.dictionary.hasOwnProperty("grid_" + value.alias)) {
value.name = localizationService.localize("grid_" + value.alias);
}
});
$scope.contentReady = true;
// *********************************************
@@ -77,14 +77,14 @@ function includePropsPreValsController($rootScope, $scope, localizationService,
// Return a helper with preserved width of cells
var fixHelper = function (e, ui) {
var h = ui.clone();
h.children().each(function () {
$(this).width($(this).width());
ui.children().each(function () {
$(this).width($(this).width());
});
h.css("background-color", "lightgray");
return h;
var row = ui.clone();
row.css("background-color", "lightgray");
return row;
};
$scope.sortableOptions = {
@@ -96,6 +96,10 @@ function includePropsPreValsController($rootScope, $scope, localizationService,
cursor: 'move',
items: '> tr',
tolerance: 'pointer',
forcePlaceholderSize: true,
start: function(e, ui){
ui.placeholder.height(ui.item.height());
},
update: function (e, ui) {
// Get the new and old index for the moved element (using the text as the identifier)
@@ -20,7 +20,7 @@
<td style="width:100px;"></td>
</tr>
</thead>
<tbody ui-sortable="sortableOptions">
<tbody ui-sortable="sortableOptions" ng-model="model.value">
<tr ng-repeat="val in model.value">
<td>
<i class="icon icon-navigation handle"></i>
@@ -257,7 +257,7 @@ angular.module("umbraco")
editor.on('ObjectResized', function (e) {
var qs = "?width=" + e.width + "&height=" + e.height;
var qs = "?width=" + e.width + "&height=" + e.height + "&mode=max";
var srcAttr = $(e.target).attr("src");
var path = srcAttr.split("?")[0];
$(e.target).attr("data-mce-src", path + qs);
@@ -1,7 +1,7 @@
(function () {
"use strict";
function UsersController($scope, $timeout, $location, usersResource, userGroupsResource, userService, localizationService, contentEditingHelper, usersHelper, formHelper, notificationsService, dateHelper) {
function UsersController($scope, $timeout, $location, $routeParams, usersResource, userGroupsResource, userService, localizationService, contentEditingHelper, usersHelper, formHelper, notificationsService, dateHelper) {
var vm = this;
var localizeSaving = localizationService.localize("general_saving");
@@ -124,6 +124,13 @@
vm.usersOptions.orderBy = "Name";
vm.usersOptions.orderDirection = "Ascending";
if ($routeParams.create) {
setUsersViewState("createUser");
}
else if ($routeParams.invite) {
setUsersViewState("inviteUser");
}
// Get users
getUsers();
@@ -168,6 +175,17 @@
if (state === "createUser") {
clearAddUserForm();
$location.search("create", "true");
$location.search("invite", null);
}
else if (state === "inviteUser") {
$location.search("create", null);
$location.search("invite", "true");
}
else if (state === "overview") {
$location.search("create", null);
$location.search("invite", null);
}
vm.usersViewState = state;
+6 -6
View File
@@ -116,8 +116,8 @@
<HintPath>..\packages\AutoMapper.3.3.1\lib\net40\AutoMapper.Net4.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="ClientDependency.Core, Version=1.9.4.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\ClientDependency.1.9.4\lib\net45\ClientDependency.Core.dll</HintPath>
<Reference Include="ClientDependency.Core, Version=1.9.6.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\ClientDependency.1.9.6\lib\net45\ClientDependency.Core.dll</HintPath>
</Reference>
<Reference Include="ClientDependency.Core.Mvc, Version=1.8.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\ClientDependency-Mvc5.1.8.0.0\lib\net45\ClientDependency.Core.Mvc.dll</HintPath>
@@ -332,8 +332,8 @@
<Name>umbraco.providers</Name>
</ProjectReference>
<Reference Include="System.Xml.Linq" />
<Reference Include="Umbraco.ModelsBuilder, Version=3.0.8.100, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\Umbraco.ModelsBuilder.3.0.8\lib\Umbraco.ModelsBuilder.dll</HintPath>
<Reference Include="Umbraco.ModelsBuilder, Version=3.0.10.102, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\Umbraco.ModelsBuilder.3.0.10\lib\Umbraco.ModelsBuilder.dll</HintPath>
</Reference>
</ItemGroup>
<ItemGroup>
@@ -1023,9 +1023,9 @@ xcopy "$(ProjectDir)"..\packages\SqlServerCE.4.0.0.1\x86\*.* "$(TargetDir)x86\"
<WebProjectProperties>
<UseIIS>True</UseIIS>
<AutoAssignPort>True</AutoAssignPort>
<DevelopmentServerPort>7780</DevelopmentServerPort>
<DevelopmentServerPort>7712</DevelopmentServerPort>
<DevelopmentServerVPath>/</DevelopmentServerVPath>
<IISUrl>http://localhost:7780</IISUrl>
<IISUrl>http://localhost:7712</IISUrl>
<NTLMAuthentication>False</NTLMAuthentication>
<UseCustomServer>False</UseCustomServer>
<CustomServerUrl>
@@ -848,6 +848,12 @@
<key alias="template">Šablona</key>
</area>
<area alias="grid">
<key alias="rte">Rich Text Editor</key>
<key alias="media">Image</key>
<key alias="macro">Macro</key>
<key alias="embed">Embed</key>
<key alias="headline">Headline</key>
<key alias="quote">Quote</key>
<key alias="insertControl">Choose type of content</key>
<key alias="chooseLayout">Choose a layout</key>
<key alias="addRows">Add a row</key>
@@ -830,6 +830,12 @@ Vennlig hilsen Umbraco roboten
<key alias="template">Mal</key>
</area>
<area alias="grid">
<key alias="rte">Rich Text Editor</key>
<key alias="media">Image</key>
<key alias="macro">Macro</key>
<key alias="embed">Embed</key>
<key alias="headline">Headline</key>
<key alias="quote">Quote</key>
<key alias="insertControl">Sett inn element</key>
<key alias="chooseLayout">Velg layout</key>
<key alias="addRows">Legg til rad</key>
@@ -995,6 +995,12 @@
<key alias="template">範本</key>
</area>
<area alias="grid">
<key alias="rte">Rich Text Editor</key>
<key alias="media">Image</key>
<key alias="macro">Macro</key>
<key alias="embed">Embed</key>
<key alias="headline">Headline</key>
<key alias="quote">Quote</key>
<key alias="insertControl">選擇內容類別</key>
<key alias="chooseLayout">選擇排列方式</key>
<key alias="addRows">新增一行</key>
@@ -248,7 +248,7 @@ img[id|dir|lang|longdesc|usemap|style|class|src|onmouseover|onmouseout|border|al
thead[id|class],tfoot[id|class],#td[id|lang|dir|class|colspan|rowspan|width|height|align|valign|style|bgcolor|background|bordercolor|scope],
-th[id|lang|dir|class|colspan|rowspan|width|height|align|valign|style|scope],caption[id|lang|dir|class|style],-div[id|dir|class|align|style],
-span[class|align|style],-pre[class|align|style],address[class|align|style],-h1[id|dir|class|align|style],-h2[id|dir|class|align|style],
-h3[id|dir|class|align|style],-h4[id|dir|class|align|style],-h5[id|dir|class|align|style],-h6[id|style|dir|class|align|style],hr[class|style],
-h3[id|dir|class|align|style],-h4[id|dir|class|align|style],-h5[id|dir|class|align|style],-h6[id|style|dir|class|align|style],hr[class|style],small[class|style],
dd[id|class|title|style|dir|lang],dl[id|class|title|style|dir|lang],dt[id|class|title|style|dir|lang],object[class|id|width|height|codebase|*],
param[name|value|_value|class],embed[type|width|height|src|class|*],map[name|class],area[shape|coords|href|alt|target|class],bdo[class],button[class],iframe[*]]]>
</validElements>
@@ -248,7 +248,7 @@ img[id|dir|lang|longdesc|usemap|style|class|src|onmouseover|onmouseout|border|al
thead[id|class],tfoot[id|class],#td[id|lang|dir|class|colspan|rowspan|width|height|align|valign|style|bgcolor|background|bordercolor|scope],
-th[id|lang|dir|class|colspan|rowspan|width|height|align|valign|style|scope],caption[id|lang|dir|class|style],-div[id|dir|class|align|style],
-span[class|align|style],-pre[class|align|style],address[class|align|style],-h1[id|dir|class|align|style],-h2[id|dir|class|align|style],
-h3[id|dir|class|align|style],-h4[id|dir|class|align|style],-h5[id|dir|class|align|style],-h6[id|style|dir|class|align|style],hr[class|style],
-h3[id|dir|class|align|style],-h4[id|dir|class|align|style],-h5[id|dir|class|align|style],-h6[id|style|dir|class|align|style],hr[class|style],small[class|style],
dd[id|class|title|style|dir|lang],dl[id|class|title|style|dir|lang],dt[id|class|title|style|dir|lang],object[class|id|width|height|codebase|*],
param[name|value|_value|class],embed[type|width|height|src|class|*],map[name|class],area[shape|coords|href|alt|target|class],bdo[class],button[class],iframe[*]]]>
</validElements>
@@ -271,4 +271,4 @@ param[name|value|_value|class],embed[type|width|height|src|class|*],map[name|cla
}
</config>
</customConfig>
</tinymceConfig>
</tinymceConfig>
+2 -2
View File
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="AutoMapper" version="3.3.1" targetFramework="net45" />
<package id="ClientDependency" version="1.9.4" targetFramework="net45" />
<package id="ClientDependency" version="1.9.6" targetFramework="net45" />
<package id="ClientDependency-Mvc5" version="1.8.0.0" targetFramework="net45" />
<package id="dotless" version="1.5.2" targetFramework="net45" />
<package id="Examine" version="0.1.89" targetFramework="net45" />
@@ -37,5 +37,5 @@
<package id="SqlServerCE" version="4.0.0.1" targetFramework="net45" />
<package id="System.Collections.Immutable" version="1.1.36" targetFramework="net45" />
<package id="System.Reflection.Metadata" version="1.0.21" targetFramework="net45" />
<package id="Umbraco.ModelsBuilder" version="3.0.8" targetFramework="net45" />
<package id="Umbraco.ModelsBuilder" version="3.0.10" targetFramework="net45" />
</packages>
@@ -43,6 +43,7 @@
<meta name="apple-mobile-web-app-capable" content="yes">
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="robots" content="noindex, nofollow">
<meta name="pinterest" content="nopin" />
<title ng-bind="$root.locationTitle">Umbraco</title>
@@ -250,7 +250,7 @@
<key alias="documentTypeWithoutTemplate">Dokumenttype uden skabelon</key>
<key alias="newFolder">Ny mappe</key>
<key alias="newDataType">Ny datatype</key>
<key alias="newJavascriptFile">Ny javascript fil</key>
<key alias="newJavascriptFile">Ny JavaScript-fil</key>
<key alias="newEmptyPartialView">Ny tom partial view</key>
<key alias="newFolder">Ny mappe</key>
<key alias="newPartialViewMacro">Ny partial view makro</key>
@@ -1215,6 +1215,12 @@ Mange hilsner fra Umbraco robotten
</area>
<area alias="grid">
<key alias="rte">Rich Text Editor</key>
<key alias="media">Image</key>
<key alias="macro">Macro</key>
<key alias="embed">Embed</key>
<key alias="headline">Headline</key>
<key alias="quote">Quote</key>
<key alias="insertControl">Vælg indholdstype</key>
<key alias="chooseLayout">Vælg layout</key>
<key alias="addRows">Tilføj række</key>
@@ -850,6 +850,12 @@ Wenn Sie sich für Runway entscheiden, können Sie optional Blöcke nutzen, die
<key alias="template">Vorlage</key>
</area>
<area alias="grid">
<key alias="rte">Rich Text Editor</key>
<key alias="media">Image</key>
<key alias="macro">Macro</key>
<key alias="embed">Embed</key>
<key alias="headline">Headline</key>
<key alias="quote">Quote</key>
<key alias="insertControl">Element hinzufügen</key>
<key alias="addRows">Zeilenlayout auswählen</key>
<key alias="addElement">Element mit &lt;i class="icon icon-add blue"&gt;&lt;/i&gt; hinzufügen</key>
@@ -604,6 +604,7 @@
<key alias="rights">Permissions</key>
<key alias="search">Search</key>
<key alias="searchNoResult">Sorry, we can not find what you are looking for</key>
<key alias="clearSearch">Clear search</key>
<key alias="noItemsInList">No items have been added</key>
<key alias="server">Server</key>
<key alias="show">Show</key>
@@ -1505,6 +1506,12 @@ To manage your website, simply open the Umbraco back office and start adding con
</area>
<area alias="grid">
<key alias="rte">Rich Text Editor</key>
<key alias="media">Image</key>
<key alias="macro">Macro</key>
<key alias="embed">Embed</key>
<key alias="headline">Headline</key>
<key alias="quote">Quote</key>
<key alias="insertControl">Choose type of content</key>
<key alias="chooseLayout">Choose a layout</key>
<key alias="addRows">Add a row</key>
@@ -1953,7 +1960,7 @@ To manage your website, simply open the Umbraco back office and start adding con
</body>
</html>]]>
</key>
<key alias="invite">Invite</key>
</area>
<area alias="validation">
@@ -604,6 +604,7 @@
<key alias="rights">Permissions</key>
<key alias="search">Search</key>
<key alias="searchNoResult">Sorry, we can not find what you are looking for</key>
<key alias="clearSearch">Clear search</key>
<key alias="noItemsInList">No items have been added</key>
<key alias="server">Server</key>
<key alias="show">Show</key>
@@ -1500,6 +1501,12 @@ To manage your website, simply open the Umbraco back office and start adding con
<key alias="template">Template</key>
</area>
<area alias="grid">
<key alias="rte">Rich Text Editor</key>
<key alias="media">Image</key>
<key alias="macro">Macro</key>
<key alias="embed">Embed</key>
<key alias="headline">Headline</key>
<key alias="quote">Quote</key>
<key alias="insertControl">Choose type of content</key>
<key alias="chooseLayout">Choose a layout</key>
<key alias="addRows">Add a row</key>
@@ -1946,6 +1953,7 @@ To manage your website, simply open the Umbraco back office and start adding con
</body>
</html>]]>
</key>
<key alias="invite">Invite</key>
</area>
<area alias="validation">
<key alias="validation">Validation</key>
@@ -754,6 +754,12 @@
<key alias="template">Plantilla</key>
</area>
<area alias="grid">
<key alias="rte">Rich Text Editor</key>
<key alias="media">Image</key>
<key alias="macro">Macro</key>
<key alias="embed">Embed</key>
<key alias="headline">Headline</key>
<key alias="quote">Quote</key>
<key alias="insertControl">Insertar control</key>
<key alias="chooseLayout">Choose layout</key>
<key alias="addRows">Añade más filas</key>
@@ -1201,6 +1201,12 @@ Pour gérer votre site, ouvrez simplement le backoffice Umbraco et commencez à
</area>
<area alias="grid">
<key alias="rte">Rich Text Editor</key>
<key alias="media">Image</key>
<key alias="macro">Macro</key>
<key alias="embed">Embed</key>
<key alias="headline">Headline</key>
<key alias="quote">Quote</key>
<key alias="insertControl">Choisissez le type de contenu</key>
<key alias="chooseLayout">Choisissez une mise en page</key>
<key alias="addRows">Ajouter une ligne</key>
@@ -745,6 +745,12 @@ To manage your website, simply open the Umbraco back office and start adding con
<key alias="template">תבנית</key>
</area>
<area alias="grid">
<key alias="rte">Rich Text Editor</key>
<key alias="media">Image</key>
<key alias="macro">Macro</key>
<key alias="embed">Embed</key>
<key alias="headline">Headline</key>
<key alias="quote">Quote</key>
<key alias="insertControl">Choose type of content</key>
<key alias="chooseLayout">Choose a layout</key>
<key alias="addRows">Add a row</key>
@@ -732,6 +732,12 @@ Per gestire il tuo sito web, è sufficiente aprire il back office di Umbraco e i
<key alias="template">Template</key>
</area>
<area alias="grid">
<key alias="rte">Rich Text Editor</key>
<key alias="media">Image</key>
<key alias="macro">Macro</key>
<key alias="embed">Embed</key>
<key alias="headline">Headline</key>
<key alias="quote">Quote</key>
<key alias="insertControl">Choose type of content</key>
<key alias="chooseLayout">Choose a layout</key>
<key alias="addRows">Add a row</key>
@@ -976,6 +976,12 @@ Runwayをインストールして作られた新しいウェブサイトがど
</area>
<area alias="grid">
<key alias="rte">Rich Text Editor</key>
<key alias="media">Image</key>
<key alias="macro">Macro</key>
<key alias="embed">Embed</key>
<key alias="headline">Headline</key>
<key alias="quote">Quote</key>
<key alias="insertControl">挿入するアイテムを選択する</key>
<key alias="addLayout">レイアウトを選択</key>
<key alias="addRows">行の追加</key>
@@ -727,6 +727,12 @@
<key alias="template">템플릿</key>
</area>
<area alias="grid">
<key alias="rte">Rich Text Editor</key>
<key alias="media">Image</key>
<key alias="macro">Macro</key>
<key alias="embed">Embed</key>
<key alias="headline">Headline</key>
<key alias="quote">Quote</key>
<key alias="insertControl">Choose type of content</key>
<key alias="chooseLayout">Choose a layout</key>
<key alias="addRows">Add a row</key>
@@ -1039,6 +1039,12 @@ Echter, Runway biedt een gemakkelijke basis om je snel op weg te helpen. Als je
<key alias="template">Sjabloon</key>
</area>
<area alias="grid">
<key alias="rte">Rich Text Editor</key>
<key alias="media">Image</key>
<key alias="macro">Macro</key>
<key alias="embed">Embed</key>
<key alias="headline">Headline</key>
<key alias="quote">Quote</key>
<key alias="insertControl">Item toevoegen</key>
<key alias="chooseLayout">Kies de indeling</key>
<key alias="addRows">Kies een indeling voor deze pagina om content toe te kunnen voegen</key>
@@ -1274,6 +1274,12 @@ Naciśnij przycisk <strong>instaluj</strong>, aby zainstalować bazę danych Umb
</area>
<area alias="grid">
<key alias="rte">Rich Text Editor</key>
<key alias="media">Image</key>
<key alias="macro">Macro</key>
<key alias="embed">Embed</key>
<key alias="headline">Headline</key>
<key alias="quote">Quote</key>
<key alias="insertControl">Wybierz typ treści</key>
<key alias="chooseLayout">Wybierz układ</key>
<key alias="addRows">Dodaj wiersz</key>
@@ -715,6 +715,12 @@ Você pode publicar esta página e todas suas sub-páginas ao selecionar <em>pub
<key alias="template">Modelo</key>
</area>
<area alias="grid">
<key alias="rte">Rich Text Editor</key>
<key alias="media">Image</key>
<key alias="macro">Macro</key>
<key alias="embed">Embed</key>
<key alias="headline">Headline</key>
<key alias="quote">Quote</key>
<key alias="insertControl">Choose type of content</key>
<key alias="chooseLayout">Choose a layout</key>
<key alias="addRows">Add a row</key>
@@ -667,6 +667,12 @@
<key alias="text">Текст</key>
</area>
<area alias="grid">
<key alias="rte">Rich Text Editor</key>
<key alias="media">Image</key>
<key alias="macro">Macro</key>
<key alias="embed">Embed</key>
<key alias="headline">Headline</key>
<key alias="quote">Quote</key>
<key alias="addElement">Добавить содержимое</key>
<key alias="dropElement">Сбросить содержимое</key>
<key alias="addGridLayout">Добавить шаблон сетки</key>
@@ -780,6 +780,12 @@
<key alias="template">Sidmall</key>
</area>
<area alias="grid">
<key alias="rte">Rich Text Editor</key>
<key alias="media">Image</key>
<key alias="macro">Macro</key>
<key alias="embed">Embed</key>
<key alias="headline">Headline</key>
<key alias="quote">Quote</key>
<key alias="insertControl">Lägg till</key>
<key alias="chooseLayout">Choose layout</key>
<key alias="addRows">Lägg till rad</key>
@@ -930,6 +930,12 @@ To manage your website, simply open the Umbraco back office and start adding con
<key alias="template">Template</key>
</area>
<area alias="grid">
<key alias="rte">Rich Text Editor</key>
<key alias="media">Image</key>
<key alias="macro">Macro</key>
<key alias="embed">Embed</key>
<key alias="headline">Headline</key>
<key alias="quote">Quote</key>
<key alias="insertControl">Insert control</key>
<key alias="addRows">Choose a layout for the page</key>
<key alias="addElement"><![CDATA[To start, click the <i class="icon icon-add blue"></i> below and add your first element]]></key>
@@ -1230,6 +1230,12 @@
</area>
<area alias="grid">
<key alias="rte">Rich Text Editor</key>
<key alias="media">Image</key>
<key alias="macro">Macro</key>
<key alias="embed">Embed</key>
<key alias="headline">Headline</key>
<key alias="quote">Quote</key>
<key alias="insertControl">选择内容类别</key>
<key alias="chooseLayout">选择一项布局</key>
<key alias="addRows">添加一行</key>
@@ -117,6 +117,7 @@ namespace Umbraco.Web.Cache
LegacyMediaPickerPropertyConverter.ClearCaches();
SliderValueConverter.ClearCaches();
MediaPickerPropertyConverter.ClearCaches();
MultiNodeTreePickerPropertyConverter.ClearCaches();
base.Refresh(jsonPayload);
@@ -1,6 +1,6 @@
using System;
using System.Linq;
using System.Web.Script.Serialization;
using System.Web;
using Newtonsoft.Json;
using Umbraco.Core;
using Umbraco.Core.Cache;
@@ -83,36 +83,28 @@ namespace Umbraco.Web.Cache
public override void Refresh(string jsonPayload)
{
ClearCache(DeserializeFromJsonPayload(jsonPayload));
ClearCache();
base.Refresh(jsonPayload);
}
public override void Refresh(int id)
{
ClearCache(FromMemberGroup(ApplicationContext.Current.Services.MemberGroupService.GetById(id)));
ClearCache();
base.Refresh(id);
}
public override void Remove(int id)
{
ClearCache(FromMemberGroup(ApplicationContext.Current.Services.MemberGroupService.GetById(id)));
ClearCache();
base.Remove(id);
}
private void ClearCache(params JsonPayload[] payloads)
private void ClearCache()
{
if (payloads == null) return;
var memberGroupCache = ApplicationContext.Current.ApplicationCache.IsolatedRuntimeCache.GetCache<IMemberGroup>();
payloads.ForEach(payload =>
{
if (payload != null && memberGroupCache)
{
memberGroupCache.Result.ClearCacheByKeySearch(string.Format("{0}.{1}", typeof(IMemberGroup).FullName, payload.Name));
memberGroupCache.Result.ClearCacheItem(RepositoryBase.GetCacheIdKey<IMemberGroup>(payload.Id));
}
});
// Since we cache by group name, it could be problematic when renaming to
// previously existing names - see http://issues.umbraco.org/issue/U4-10846.
// To work around this, just clear all the cache items
ApplicationContext.Current.ApplicationCache.IsolatedRuntimeCache.ClearCache<IMemberGroup>();
}
}
}
}
@@ -1,11 +1,7 @@
using System;
using System.Linq;
using System.Web.Mvc;
using System.Web.Security;
using umbraco.BusinessLogic;
using umbraco.cms.businesslogic.member;
using Umbraco.Core;
using Umbraco.Core.Security;
using Umbraco.Web.Models;
using Umbraco.Web.Mvc;
@@ -21,6 +17,13 @@ namespace Umbraco.Web.Controllers
return CurrentUmbracoPage();
}
// U4-10762 Server error with "Register Member" snippet (Cannot save member with empty name)
// If name field is empty, add the email address instead
if (string.IsNullOrEmpty(model.Name) && string.IsNullOrEmpty(model.Email) == false)
{
model.Name = model.Email;
}
MembershipCreateStatus status;
var member = Members.RegisterMember(model, out status, model.LoginOnSuccess);
@@ -36,7 +39,6 @@ namespace Umbraco.Web.Controllers
return Redirect(model.RedirectUrl);
}
//redirect to current page by default
return RedirectToCurrentUmbracoPage();
case MembershipCreateStatus.InvalidUserName:
ModelState.AddModelError((model.UsernameIsEmail || model.Username == null)
@@ -45,8 +45,9 @@ namespace Umbraco.Web.Install.Controllers
if (ApplicationContext.Current.IsUpgrading)
{
// Update ClientDependency version
var clientDependencyConfig = new ClientDependencyConfiguration(ApplicationContext.Current.ProfilingLogger.Logger);
var clientDependencyUpdated = clientDependencyConfig.IncreaseVersionNumber();
var clientDependencyConfig = new ClientDependencyConfiguration(_umbracoContext.Application.ProfilingLogger.Logger);
var clientDependencyUpdated = clientDependencyConfig.UpdateVersionNumber(
UmbracoVersion.GetSemanticVersion(), DateTime.UtcNow, "yyyyMMdd");
// Delete ClientDependency temp directories to make sure we get fresh caches
var clientDependencyTempFilesDeleted = clientDependencyConfig.ClearTempFiles(HttpContext);
@@ -65,6 +65,8 @@ namespace Umbraco.Web.Models.Mapping
if (source.DefaultTemplate != null)
dest.SetDefaultTemplate(applicationContext.Services.FileService.GetTemplate(source.DefaultTemplate));
else
dest.SetDefaultTemplate(null);
ContentTypeModelMapperExtensions.AfterMapContentTypeSaveToEntity(source, dest, applicationContext);
});
@@ -201,10 +201,24 @@ namespace Umbraco.Web.Models.Mapping
var allContentPermissions = applicationContext.Services.UserService.GetPermissions(@group, true)
.ToDictionary(x => x.EntityId, x => x);
var contentEntities = allContentPermissions.Keys.Count == 0
? new IUmbracoEntity[0]
: applicationContext.Services.EntityService.GetAll(UmbracoObjectTypes.Document, allContentPermissions.Keys.ToArray());
IEnumerable<IUmbracoEntity> contentEntities;
if (allContentPermissions.Keys.Count == 0)
{
contentEntities = new IUmbracoEntity[0];
}
else
{
// a group can end up with way more than 2000 assigned permissions,
// so we need to break them into groups in order to avoid breaking
// the entity service due to too many Sql parameters.
var list = new List<IUmbracoEntity>();
contentEntities = list;
var entityService = applicationContext.Services.EntityService;
foreach (var idGroup in allContentPermissions.Keys.InGroupsOf(2000))
list.AddRange(entityService.GetAll(UmbracoObjectTypes.Document, idGroup.ToArray()));
}
var allAssignedPermissions = new List<AssignedContentPermissions>();
foreach (var entity in contentEntities)
@@ -229,7 +243,7 @@ namespace Umbraco.Web.Models.Mapping
});
//Important! Currently we are never mapping to multiple UserDisplay objects but if we start doing that
// this will cause an N+1 and we'll need to change how this works.
// this will cause an N+1 and we'll need to change how this works.
config.CreateMap<IUser, UserDisplay>()
.ForMember(detail => detail.Avatars, opt => opt.MapFrom(user => user.GetCurrentUserAvatarUrls(applicationContext.Services.UserService, applicationContext.ApplicationCache.RuntimeCache)))
.ForMember(detail => detail.Username, opt => opt.MapFrom(user => user.Username))
@@ -253,7 +267,7 @@ namespace Umbraco.Web.Models.Mapping
"media/mediaRoot")))
.ForMember(
detail => detail.StartContentIds,
opt => opt.MapFrom(user => GetStartNodeValues(
opt => opt.MapFrom(user => GetStartNodeValues(
user.StartContentIds.ToArray(),
applicationContext.Services.TextService,
applicationContext.Services.EntityService,
@@ -261,7 +275,7 @@ namespace Umbraco.Web.Models.Mapping
"content/contentRoot")))
.ForMember(
detail => detail.StartMediaIds,
opt => opt.MapFrom(user => GetStartNodeValues(
opt => opt.MapFrom(user => GetStartNodeValues(
user.StartMediaIds.ToArray(),
applicationContext.Services.TextService,
applicationContext.Services.EntityService,
@@ -328,7 +342,7 @@ namespace Umbraco.Web.Models.Mapping
//the best we can do here is to return the user's first user group as a IUserType object
//but we should attempt to return any group that is the built in ones first
var groups = user.Groups.ToArray();
detail.UserGroups = user.Groups.Select(x => x.Alias).ToArray();
detail.UserGroups = user.Groups.Select(x => x.Alias).ToArray();
if (groups.Length == 0)
{
@@ -369,8 +383,8 @@ namespace Umbraco.Web.Models.Mapping
}
private IEnumerable<EntityBasic> GetStartNodeValues(int[] startNodeIds,
ILocalizedTextService textService, IEntityService entityService, UmbracoObjectTypes objectType,
private IEnumerable<EntityBasic> GetStartNodeValues(int[] startNodeIds,
ILocalizedTextService textService, IEntityService entityService, UmbracoObjectTypes objectType,
string localizedKey)
{
if (startNodeIds.Length > 0)
@@ -385,7 +399,7 @@ namespace Umbraco.Web.Models.Mapping
return startNodes;
}
return Enumerable.Empty<EntityBasic>();
}
}
private void MapUserGroupBasic(ServiceContext services, dynamic group, UserGroupBasic display)
{
+39 -22
View File
@@ -1,6 +1,5 @@
using System;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Web;
using System.Web.Mvc;
@@ -13,8 +12,10 @@ namespace Umbraco.Web.Mvc
/// <summary>
/// Allows for Model Binding any IPublishedContent or IRenderModel
/// </summary>
public class RenderModelBinder : DefaultModelBinder, IModelBinder, IModelBinderProvider
public class RenderModelBinder : DefaultModelBinder, IModelBinderProvider
{
public static RenderModelBinder Instance = new RenderModelBinder();
/// <summary>
/// Binds the model to a value by using the specified controller context and binding context.
/// </summary>
@@ -132,10 +133,30 @@ namespace Umbraco.Web.Mvc
return null;
}
public class ModelBindingArgs : EventArgs
{
public ModelBindingArgs(Type sourceType, Type modelType, StringBuilder message)
{
SourceType = sourceType;
ModelType = modelType;
Message = message;
}
public bool SourceIsContent;
public bool ViewModelIsContent;
public Type SourceType { get; set; }
public Type ModelType { get; set; }
public StringBuilder Message { get; private set; }
public bool Restart { get; set; }
}
public static event EventHandler<ModelBindingArgs> ModelBindingException;
private static void ThrowModelBindingException(bool sourceContent, bool modelContent, Type sourceType, Type modelType)
{
var msg = new StringBuilder();
// prepare message
msg.Append("Cannot bind source");
if (sourceContent) msg.Append(" content");
msg.Append(" type ");
@@ -146,28 +167,24 @@ namespace Umbraco.Web.Mvc
msg.Append(modelType.FullName);
msg.Append(".");
// compare FullName for the time being because when upgrading ModelsBuilder,
// Umbraco does not know about the new attribute type - later on, can compare
// on type directly (ie after v7.4.2).
var sourceAttr = sourceType.Assembly.CustomAttributes.FirstOrDefault(x =>
x.AttributeType.FullName == "Umbraco.ModelsBuilder.PureLiveAssemblyAttribute");
var modelAttr = modelType.Assembly.CustomAttributes.FirstOrDefault(x =>
x.AttributeType.FullName == "Umbraco.ModelsBuilder.PureLiveAssemblyAttribute");
// raise event, to give model factories a chance at reporting
// the error with more details, and optionally request that
// the application restarts.
// bah.. names are App_Web_all.generated.cs.8f9494c4.jjuvxz55 so they ARE different, fuck!
// we cannot compare purely on type.FullName 'cos we might be trying to map Sub to Main = fails!
if (sourceAttr != null && modelAttr != null
&& sourceType.Assembly.GetName().Version.Revision != modelType.Assembly.GetName().Version.Revision)
var args = new ModelBindingArgs(sourceType, modelType, msg);
if (ModelBindingException != null)
ModelBindingException(Instance, args);
if (args.Restart)
{
msg.Append(" Types come from two PureLive assemblies with different versions,");
msg.Append(" this usually indicates that the application is in an unstable state.");
msg.Append(" The application is restarting now, reload the page and it should work.");
var context = HttpContext.Current;
if (context == null)
AppDomain.Unload(AppDomain.CurrentDomain);
else
ApplicationContext.Current.RestartApplicationPool(new HttpContextWrapper(context));
}
msg.Append(" The application is restarting now.");
var context = HttpContext.Current;
if (context == null)
AppDomain.Unload(AppDomain.CurrentDomain);
else
ApplicationContext.Current.RestartApplicationPool(new HttpContextWrapper(context));
}
throw new ModelBindingException(msg.ToString());
}
@@ -85,6 +85,9 @@ namespace Umbraco.Web.PropertyEditors.ValueConverters
/// </returns>
public override object ConvertDataToSource(PublishedPropertyType propertyType, object source, bool preview)
{
if (source == null)
return null;
if (IsMultipleDataType(propertyType.DataTypeId, propertyType.PropertyEditorAlias))
{
var nodeIds =
@@ -8,16 +8,18 @@
// --------------------------------------------------------------------------------------------------------------------
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using Newtonsoft.Json;
using Umbraco.Core;
using Umbraco.Core.Configuration;
using Umbraco.Core.Models;
using Umbraco.Core.Models.PublishedContent;
using Umbraco.Core.PropertyEditors;
using Umbraco.Core.PropertyEditors.ValueConverters;
using Umbraco.Web.Extensions;
using Umbraco.Core.Services;
namespace Umbraco.Web.PropertyEditors.ValueConverters
{
@@ -32,6 +34,20 @@ namespace Umbraco.Web.PropertyEditors.ValueConverters
[PropertyValueCache(PropertyCacheValue.XPath, PropertyCacheLevel.Content)]
public class MultiNodeTreePickerPropertyConverter : PropertyValueConverterBase
{
private readonly IDataTypeService _dataTypeService;
//TODO: Remove this ctor in v8 since the other one will use IoC
public MultiNodeTreePickerPropertyConverter()
: this(ApplicationContext.Current.Services.DataTypeService)
{ }
public MultiNodeTreePickerPropertyConverter(IDataTypeService dataTypeService)
: base()
{
if (dataTypeService == null) throw new ArgumentNullException("dataTypeService");
_dataTypeService = dataTypeService;
}
/// <summary>
/// The properties to exclude.
/// </summary>
@@ -125,6 +141,24 @@ namespace Umbraco.Web.PropertyEditors.ValueConverters
var umbHelper = new UmbracoHelper(UmbracoContext.Current);
Func<object, IPublishedContent> contentFetcher;
switch (GetPublishedContentType(propertyType.DataTypeId))
{
case PublishedItemType.Media:
contentFetcher = umbHelper.TypedMedia;
break;
case PublishedItemType.Member:
contentFetcher = umbHelper.TypedMember;
break;
case PublishedItemType.Content:
default:
contentFetcher = umbHelper.TypedContent;
break;
}
if (propertyType.PropertyEditorAlias.Equals(Constants.PropertyEditors.MultiNodeTreePickerAlias))
{
var nodeIds = (int[])source;
@@ -133,14 +167,9 @@ namespace Umbraco.Web.PropertyEditors.ValueConverters
{
var multiNodeTreePicker = new List<IPublishedContent>();
var objectType = UmbracoObjectTypes.Unknown;
foreach (var nodeId in nodeIds)
{
var multiNodeTreePickerItem =
GetPublishedContent(nodeId, ref objectType, UmbracoObjectTypes.Document, umbHelper.TypedContent)
?? GetPublishedContent(nodeId, ref objectType, UmbracoObjectTypes.Media, umbHelper.TypedMedia)
?? GetPublishedContent(nodeId, ref objectType, UmbracoObjectTypes.Member, umbHelper.TypedMember);
var multiNodeTreePickerItem = contentFetcher(nodeId);
if (multiNodeTreePickerItem != null)
{
@@ -163,14 +192,9 @@ namespace Umbraco.Web.PropertyEditors.ValueConverters
{
var multiNodeTreePicker = new List<IPublishedContent>();
var objectType = UmbracoObjectTypes.Unknown;
foreach (var udi in udis)
{
var multiNodeTreePickerItem =
GetPublishedContent(udi, ref objectType, UmbracoObjectTypes.Document, umbHelper.TypedContent)
?? GetPublishedContent(udi, ref objectType, UmbracoObjectTypes.Media, umbHelper.TypedMedia)
?? GetPublishedContent(udi, ref objectType, UmbracoObjectTypes.Member, umbHelper.TypedMember);
var multiNodeTreePickerItem = contentFetcher(udi);
if (multiNodeTreePickerItem != null)
{
multiNodeTreePicker.Add(multiNodeTreePickerItem);
@@ -186,31 +210,50 @@ namespace Umbraco.Web.PropertyEditors.ValueConverters
return source;
}
/// <summary>
/// Attempt to get an IPublishedContent instance based on ID and content type
/// </summary>
/// <param name="nodeId">The content node ID</param>
/// <param name="actualType">The type of content being requested</param>
/// <param name="expectedType">The type of content expected/supported by <paramref name="contentFetcher"/></param>
/// <param name="contentFetcher">A function to fetch content of type <paramref name="expectedType"/></param>
/// <returns>The requested content, or null if either it does not exist or <paramref name="actualType"/> does not match <paramref name="expectedType"/></returns>
private IPublishedContent GetPublishedContent<T>(T nodeId, ref UmbracoObjectTypes actualType, UmbracoObjectTypes expectedType, Func<T, IPublishedContent> contentFetcher)
private PublishedItemType GetPublishedContentType(int dataTypeId)
{
// is the actual type supported by the content fetcher?
if (actualType != UmbracoObjectTypes.Unknown && actualType != expectedType)
{
// no, return null
return null;
}
// GetPreValuesCollectionByDataTypeId is cached at repository level;
// still, the collection is deep-cloned so this is kinda expensive,
// better to cache here + trigger refresh in DataTypeCacheRefresher
// e.g. https://github.com/umbraco/Umbraco-CMS/blob/dev-v7/src/Umbraco.Web/Cache/DataTypeCacheRefresher.cs#L116-L119
// attempt to get the content
var content = contentFetcher(nodeId);
if (content != null)
return Storages.GetOrAdd(dataTypeId, id =>
{
// if we found the content, assign the expected type to the actual type so we don't have to keep looking for other types of content
actualType = expectedType;
}
return content;
var preValue = _dataTypeService
.GetPreValuesCollectionByDataTypeId(id)
.PreValuesAsDictionary
.FirstOrDefault(x => string.Equals(x.Key, "startNode", StringComparison.InvariantCultureIgnoreCase))
.Value;
if (preValue != null && string.IsNullOrWhiteSpace(preValue.Value) == false)
{
var data = JsonConvert.DeserializeAnonymousType(preValue.Value, new { type = string.Empty });
if (data != null)
{
switch (data.type.ToUpperInvariant())
{
case "MEDIA":
return PublishedItemType.Media;
case "MEMBER":
return PublishedItemType.Member;
case "CONTENT":
default:
return PublishedItemType.Content;
}
}
}
return PublishedItemType.Content;
});
}
private static readonly ConcurrentDictionary<int, PublishedItemType> Storages = new ConcurrentDictionary<int, PublishedItemType>();
internal static void ClearCaches()
{
Storages.Clear();
}
}
}
+48 -7
View File
@@ -1,4 +1,5 @@
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Xml.XPath;
@@ -224,14 +225,54 @@ namespace Umbraco.Web
{
var doc = cache.GetById(id);
return doc;
}
}
private static readonly ConcurrentDictionary<Guid, int> _guidToIntLoopkup = new ConcurrentDictionary<Guid, int>();
private IPublishedContent TypedDocumentById(Guid id, ContextualPublishedCache cache)
{
// todo: in v8, implement in a more efficient way
var legacyXml = UmbracoConfig.For.UmbracoSettings().Content.UseLegacyXmlSchema;
var xpath = legacyXml ? "//node [@key=$guid]" : "//* [@key=$guid]";
var doc = cache.GetSingleByXPath(xpath, new XPathVariable("guid", id.ToString()));
{
// Check if the loopkup is empty, if so populate it [LK]
if (_guidToIntLoopkup.Count == 0)
{
// TODO: Remove the debug profile logger
using (ApplicationContext.Current.ProfilingLogger.DebugDuration<PublishedContentQuery>("Populate GUID/INT lookup"))
{
// NOTE, using the `@nodeTypeAlias` attribute in the XPath as this was support in both legacy & new schemas
var tmpNodes = cache.GetXPathNavigator().Select("//*[@nodeTypeAlias]");
foreach (XPathNavigator tmpNode in tmpNodes)
{
int tmpNodeId;
Guid tmpNodeKey;
if (int.TryParse(tmpNode.GetAttribute("id", string.Empty), out tmpNodeId)
&& Guid.TryParse(tmpNode.GetAttribute("key", string.Empty), out tmpNodeKey))
{
_guidToIntLoopkup[tmpNodeKey] = tmpNodeId;
}
}
}
}
IPublishedContent doc;
// Check if the lookup contains the GUID/INT value
int nodeId;
if (_guidToIntLoopkup.TryGetValue(id, out nodeId) == false)
{
// If not, then we perform an inefficient XPath for the GUID
// todo: in v8, implement in a more efficient way
doc = cache.GetSingleByXPath("//*[@key=$guid]", new XPathVariable("guid", id.ToString()));
// When we have the node, we add the GUID/INT value to the lookup
if (doc != null)
_guidToIntLoopkup[id] = doc.Id;
}
else
{
// Otherwise we have the node id (INT) and can perform an efficient retrieval
doc = cache.GetById(nodeId);
}
return doc;
}
@@ -422,4 +463,4 @@ namespace Umbraco.Web
#endregion
}
}
}
+186 -43
View File
@@ -11,6 +11,7 @@ using Umbraco.Core;
using Umbraco.Core.Cache;
using Umbraco.Core.Logging;
using Umbraco.Core.Models;
using Umbraco.Core.Scoping;
using Umbraco.Core.Sync;
using Umbraco.Web.Cache;
using UmbracoExamine;
@@ -24,7 +25,12 @@ namespace Umbraco.Web.Search
/// </summary>
public sealed class ExamineEvents : ApplicationEventHandler
{
/// <summary>
// the default enlist priority is 100
// enlist with a lower priority to ensure that anything "default" runs after us
// but greater that SafeXmlReaderWriter priority which is 60
private const int EnlistPriority = 80;
/// <summary>
/// Once the application has started we should bind to all events and initialize the providers.
/// </summary>
/// <param name="httpApplication"></param>
@@ -447,11 +453,11 @@ namespace Umbraco.Web.Search
private static void ReIndexForMember(IMember member)
{
ExamineManager.Instance.ReIndexNode(
member.ToXml(), IndexTypes.Member,
ExamineManager.Instance.IndexProviderCollection.OfType<BaseUmbracoIndexer>()
//ensure that only the providers are flagged to listen execute
.Where(x => x.EnableDefaultEventHandler));
var actions = DeferedActions.Get(ApplicationContext.Current.ScopeProvider);
if (actions != null)
actions.Add(new DeferedReIndexForMember(member));
else
DeferedReIndexForMember.Execute(member);
}
/// <summary>
@@ -479,19 +485,11 @@ namespace Umbraco.Web.Search
private static void ReIndexForMedia(IMedia sender, bool isMediaPublished)
{
var xml = sender.ToXml();
//add an icon attribute to get indexed
xml.Add(new XAttribute("icon", sender.ContentType.Icon));
ExamineManager.Instance.ReIndexNode(
xml, IndexTypes.Media,
ExamineManager.Instance.IndexProviderCollection.OfType<BaseUmbracoIndexer>()
//Index this item for all indexers if the media is not trashed, otherwise if the item is trashed
// then only index this for indexers supporting unpublished media
.Where(x => isMediaPublished || (x.SupportUnpublishedContent))
.Where(x => x.EnableDefaultEventHandler));
var actions = DeferedActions.Get(ApplicationContext.Current.ScopeProvider);
if (actions != null)
actions.Add(new DeferedReIndexForMedia(sender, isMediaPublished));
else
DeferedReIndexForMedia.Execute(sender, isMediaPublished);
}
/// <summary>
@@ -504,15 +502,11 @@ namespace Umbraco.Web.Search
/// </param>
private static void DeleteIndexForEntity(int entityId, bool keepIfUnpublished)
{
ExamineManager.Instance.DeleteFromIndex(
entityId.ToString(CultureInfo.InvariantCulture),
ExamineManager.Instance.IndexProviderCollection.OfType<BaseUmbracoIndexer>()
//if keepIfUnpublished == true then only delete this item from indexes not supporting unpublished content,
// otherwise if keepIfUnpublished == false then remove from all indexes
.Where(x => keepIfUnpublished == false || x.SupportUnpublishedContent == false)
.Where(x => x.EnableDefaultEventHandler));
var actions = DeferedActions.Get(ApplicationContext.Current.ScopeProvider);
if (actions != null)
actions.Add(new DeferedDeleteIndex(entityId, keepIfUnpublished));
else
DeferedDeleteIndex.Execute(entityId, keepIfUnpublished);
}
/// <summary>
@@ -524,22 +518,171 @@ namespace Umbraco.Web.Search
/// </param>
private static void ReIndexForContent(IContent sender, bool isContentPublished)
{
var xml = sender.ToXml();
//add an icon attribute to get indexed
xml.Add(new XAttribute("icon", sender.ContentType.Icon));
ExamineManager.Instance.ReIndexNode(
xml, IndexTypes.Content,
ExamineManager.Instance.IndexProviderCollection.OfType<BaseUmbracoIndexer>()
//Index this item for all indexers if the content is published, otherwise if the item is not published
// then only index this for indexers supporting unpublished content
.Where(x => isContentPublished || (x.SupportUnpublishedContent))
.Where(x => x.EnableDefaultEventHandler));
var actions = DeferedActions.Get(ApplicationContext.Current.ScopeProvider);
if (actions != null)
actions.Add(new DeferedReIndexForContent(sender, isContentPublished));
else
DeferedReIndexForContent.Execute(sender, isContentPublished);
}
/// <summary>
private class DeferedActions
{
private readonly List<DeferedAction> _actions = new List<DeferedAction>();
public static DeferedActions Get(IScopeProvider scopeProvider)
{
var scopeContext = scopeProvider.Context;
if (scopeContext == null) return null;
return scopeContext.Enlist("examineEvents",
() => new DeferedActions(), // creator
(completed, actions) => // action
{
if (completed) actions.Execute();
}, EnlistPriority);
}
public void Add(DeferedAction action)
{
_actions.Add(action);
}
private void Execute()
{
foreach (var action in _actions)
action.Execute();
}
}
private abstract class DeferedAction
{
public virtual void Execute()
{ }
}
private class DeferedReIndexForContent : DeferedAction
{
private readonly IContent _content;
private readonly bool _isPublished;
public DeferedReIndexForContent(IContent content, bool isPublished)
{
_content = content;
_isPublished = isPublished;
}
public override void Execute()
{
Execute(_content, _isPublished);
}
public static void Execute(IContent content, bool isPublished)
{
var xml = content.ToXml();
//add an icon attribute to get indexed
xml.Add(new XAttribute("icon", content.ContentType.Icon));
ExamineManager.Instance.ReIndexNode(
xml, IndexTypes.Content,
ExamineManager.Instance.IndexProviderCollection.OfType<BaseUmbracoIndexer>()
//Index this item for all indexers if the content is published, otherwise if the item is not published
// then only index this for indexers supporting unpublished content
.Where(x => isPublished || (x.SupportUnpublishedContent))
.Where(x => x.EnableDefaultEventHandler));
}
}
private class DeferedReIndexForMedia : DeferedAction
{
private readonly IMedia _media;
private readonly bool _isPublished;
public DeferedReIndexForMedia(IMedia media, bool isPublished)
{
_media = media;
_isPublished = isPublished;
}
public override void Execute()
{
Execute(_media, _isPublished);
}
public static void Execute(IMedia media, bool isPublished)
{
var xml = media.ToXml();
//add an icon attribute to get indexed
xml.Add(new XAttribute("icon", media.ContentType.Icon));
ExamineManager.Instance.ReIndexNode(
xml, IndexTypes.Media,
ExamineManager.Instance.IndexProviderCollection.OfType<BaseUmbracoIndexer>()
//Index this item for all indexers if the media is not trashed, otherwise if the item is trashed
// then only index this for indexers supporting unpublished media
.Where(x => isPublished || (x.SupportUnpublishedContent))
.Where(x => x.EnableDefaultEventHandler));
}
}
private class DeferedReIndexForMember : DeferedAction
{
private readonly IMember _member;
public DeferedReIndexForMember(IMember member)
{
_member = member;
}
public override void Execute()
{
Execute(_member);
}
public static void Execute(IMember member)
{
ExamineManager.Instance.ReIndexNode(
member.ToXml(), IndexTypes.Member,
ExamineManager.Instance.IndexProviderCollection.OfType<BaseUmbracoIndexer>()
//ensure that only the providers are flagged to listen execute
.Where(x => x.EnableDefaultEventHandler));
}
}
private class DeferedDeleteIndex : DeferedAction
{
private readonly int _id;
private readonly bool _keepIfUnpublished;
public DeferedDeleteIndex(int id, bool keepIfUnpublished)
{
_id = id;
_keepIfUnpublished = keepIfUnpublished;
}
public override void Execute()
{
Execute(_id, _keepIfUnpublished);
}
public static void Execute(int id, bool keepIfUnpublished)
{
ExamineManager.Instance.DeleteFromIndex(
id.ToString(CultureInfo.InvariantCulture),
ExamineManager.Instance.IndexProviderCollection.OfType<BaseUmbracoIndexer>()
//if keepIfUnpublished == true then only delete this item from indexes not supporting unpublished content,
// otherwise if keepIfUnpublished == false then remove from all indexes
.Where(x => keepIfUnpublished == false || x.SupportUnpublishedContent == false)
.Where(x => x.EnableDefaultEventHandler));
}
}
/// <summary>
/// Converts a content node to XDocument
/// </summary>
/// <param name="node"></param>
@@ -583,4 +726,4 @@ namespace Umbraco.Web.Search
return new XDocument(ExamineXmlExtensions.ToXElement(xNode));
}
}
}
}
@@ -54,7 +54,7 @@ namespace Umbraco.Web.Trees
}
#endregion
/// <summary>
/// Ensure the noAccess metadata is applied for the root node if in dialog mode and the user doesn't have path access to it
/// </summary>
@@ -70,12 +70,12 @@ namespace Umbraco.Web.Trees
}
return node;
}
}
protected abstract TreeNode GetSingleTreeNode(IUmbracoEntity e, string parentId, FormDataCollection queryStrings);
/// <summary>
/// Returns a <see cref="TreeNode"/> for the <see cref="IUmbracoEntity"/> and
/// Returns a <see cref="TreeNode"/> for the <see cref="IUmbracoEntity"/> and
/// attaches some meta data to the node if the user doesn't have start node access to it when in dialog mode
/// </summary>
/// <param name="e"></param>
@@ -83,13 +83,13 @@ namespace Umbraco.Web.Trees
/// <param name="queryStrings"></param>
/// <returns></returns>
internal TreeNode GetSingleTreeNodeWithAccessCheck(IUmbracoEntity e, string parentId, FormDataCollection queryStrings)
{
bool hasPathAccess;
var entityIsAncestorOfStartNodes = Security.CurrentUser.IsInBranchOfStartNode(e, Services.EntityService, RecycleBinId, out hasPathAccess);
if (entityIsAncestorOfStartNodes == false)
return null;
{
bool hasPathAccess;
var entityIsAncestorOfStartNodes = Security.CurrentUser.IsInBranchOfStartNode(e, Services.EntityService, RecycleBinId, out hasPathAccess);
if (entityIsAncestorOfStartNodes == false)
return null;
var treeNode = GetSingleTreeNode(e, parentId, queryStrings);
var treeNode = GetSingleTreeNode(e, parentId, queryStrings);
if (hasPathAccess == false)
{
treeNode.AdditionalData["noAccess"] = true;
@@ -98,7 +98,7 @@ namespace Umbraco.Web.Trees
}
/// <summary>
/// Returns the
/// Returns the
/// </summary>
protected abstract int RecycleBinId { get; }
@@ -111,79 +111,69 @@ namespace Umbraco.Web.Trees
/// Returns the user's start node for this tree
/// </summary>
protected abstract int[] UserStartNodes { get; }
protected virtual TreeNodeCollection PerformGetTreeNodes(string id, FormDataCollection queryStrings)
{
var nodes = new TreeNodeCollection();
var altStartId = string.Empty;
if (queryStrings.HasKey(TreeQueryStringParameters.StartNodeId))
altStartId = queryStrings.GetValue<string>(TreeQueryStringParameters.StartNodeId);
var rootIdString = Constants.System.Root.ToString(CultureInfo.InvariantCulture);
var rootIdString = Constants.System.Root.ToString(CultureInfo.InvariantCulture);
var hasAccessToRoot = UserStartNodes.Contains(Constants.System.Root);
//check if a request has been made to render from a specific start node
if (string.IsNullOrEmpty(altStartId) == false && altStartId != "undefined" && altStartId != rootIdString)
var startNodeId = queryStrings.HasKey(TreeQueryStringParameters.StartNodeId)
? queryStrings.GetValue<string>(TreeQueryStringParameters.StartNodeId)
: string.Empty;
if (string.IsNullOrEmpty(startNodeId) == false && startNodeId != "undefined" && startNodeId != rootIdString)
{
id = altStartId;
// request has been made to render from a specific, non-root, start node
id = startNodeId;
//we need to verify that the user has access to view this node, otherwise we'll render an empty tree collection
// TODO: in the future we could return a validation statement so we can have some UI to notify the user they don't have access
// ensure that the user has access to that node, otherwise return the empty tree nodes collection
// TODO: in the future we could return a validation statement so we can have some UI to notify the user they don't have access
if (HasPathAccess(id, queryStrings) == false)
{
LogHelper.Warn<ContentTreeControllerBase>("The user " + Security.CurrentUser.Username + " does not have access to the tree node " + id);
return new TreeNodeCollection();
LogHelper.Warn<ContentTreeControllerBase>("User " + Security.CurrentUser.Username + " does not have access to node with id " + id);
return nodes;
}
// So there's an alt id specified, it's not the root node and the user has access to it, great! But there's one thing we
// need to consider:
// If the tree is being rendered in a dialog view we want to render only the children of the specified id, but
// when the tree is being rendered normally in a section and the current user's start node is not -1, then
// we want to include their start node in the tree as well.
// Therefore, in the latter case, we want to change the id to -1 since we want to render the current user's root node
// and the GetChildEntities method will take care of rendering the correct root node.
// If it is in dialog mode, then we don't need to change anything and the children will just render as per normal.
if (IsDialog(queryStrings) == false && UserStartNodes.Contains(Constants.System.Root) == false)
// if the tree is rendered...
// - in a dialog: render only the children of the specific start node, nothing to do
// - in a section: if the current user's start nodes do not contain the root node, we need
// to include these start nodes in the tree too, to provide some context - i.e. change
// start node back to root node, and then GetChildEntities method will take care of the rest.
if (IsDialog(queryStrings) == false && hasAccessToRoot == false)
id = rootIdString;
}
// get child entities - if id is root, but user's start nodes do not contain the
// root node, this returns the start nodes instead of root's children
var entities = GetChildEntities(id).ToList();
nodes.AddRange(entities.Select(x => GetSingleTreeNodeWithAccessCheck(x, id, queryStrings)).Where(x => x != null));
// if the user does not have access to the root node, what we have is the start nodes,
// but to provide some context we also need to add their topmost nodes when they are not
// topmost nodes themselves (level > 1).
if (id == rootIdString && hasAccessToRoot == false)
{
var topNodeIds = entities.Where(x => x.Level > 1).Select(GetTopNodeId).Where(x => x != 0).Distinct().ToArray();
if (topNodeIds.Length > 0)
{
id = Constants.System.Root.ToString(CultureInfo.InvariantCulture);
var topNodes = Services.EntityService.GetAll(UmbracoObjectType, topNodeIds.ToArray());
nodes.AddRange(topNodes.Select(x => GetSingleTreeNodeWithAccessCheck(x, id, queryStrings)).Where(x => x != null));
}
}
var entities = GetChildEntities(id).ToList();
//If we are looking up the root and there is more than one node ...
//then we want to lookup those nodes' 'site' nodes and render those so that the
//user has some context of where they are in the tree, this is generally for pickers in a dialog.
//for any node they don't have access too, we need to add some metadata
if (id == rootIdString && entities.Count > 1)
{
var siteNodeIds = new List<int>();
//put into array since we might modify the list
foreach (var e in entities.ToArray())
{
var pathParts = e.Path.Split(new[] {','}, StringSplitOptions.RemoveEmptyEntries);
if (pathParts.Length < 2)
continue; // this should never happen but better to check
int siteNodeId;
if (int.TryParse(pathParts[1], out siteNodeId) == false)
continue;
//we'll look up this
siteNodeIds.Add(siteNodeId);
}
var siteNodes = Services.EntityService.GetAll(UmbracoObjectType, siteNodeIds.ToArray())
.DistinctBy(e => e.Id)
.ToArray();
//add site nodes
nodes.AddRange(siteNodes.Select(e => GetSingleTreeNodeWithAccessCheck(e, id, queryStrings)).Where(node => node != null));
return nodes;
}
nodes.AddRange(entities.Select(e => GetSingleTreeNodeWithAccessCheck(e, id, queryStrings)).Where(node => node != null));
return nodes;
}
}
private static readonly char[] Comma = { ',' };
private int GetTopNodeId(IUmbracoEntity entity)
{
int id;
var parts = entity.Path.Split(Comma, StringSplitOptions.RemoveEmptyEntries);
return parts.Length >= 2 && int.TryParse(parts[1], out id) ? id : 0;
}
protected abstract MenuItemCollection PerformGetMenuForNode(string id, FormDataCollection queryStrings);
@@ -191,30 +181,27 @@ namespace Umbraco.Web.Trees
protected IEnumerable<IUmbracoEntity> GetChildEntities(string id)
{
// use helper method to ensure we support both integer and guid lookups
int iid;
// look up from GUID if it's not an integer
if (int.TryParse(id, out iid) == false)
// try to parse id as an integer else use GetEntityFromId
// which will grok Guids, Udis, etc and let use obtain the id
int entityId;
if (int.TryParse(id, out entityId) == false)
{
var idEntity = GetEntityFromId(id);
if (idEntity == null)
{
var entity = GetEntityFromId(id);
if (entity == null)
throw new HttpResponseException(HttpStatusCode.NotFound);
}
iid = idEntity.Id;
entityId = entity.Id;
}
// if a request is made for the root node but user has no access to
// root node, return start nodes instead
if (iid == Constants.System.Root && UserStartNodes.Contains(Constants.System.Root) == false)
if (entityId == Constants.System.Root && UserStartNodes.Contains(Constants.System.Root) == false)
{
return UserStartNodes.Length > 0
? Services.EntityService.GetAll(UmbracoObjectType, UserStartNodes)
: Enumerable.Empty<IUmbracoEntity>();
}
return Services.EntityService.GetChildren(iid, UmbracoObjectType).ToArray();
return Services.EntityService.GetChildren(entityId, UmbracoObjectType).ToArray();
}
/// <summary>
@@ -236,7 +223,7 @@ namespace Umbraco.Web.Trees
{
if (entity == null) return false;
return Security.CurrentUser.HasPathAccess(entity, Services.EntityService, RecycleBinId);
}
}
/// <summary>
/// Ensures the recycle bin is appended when required (i.e. user has access to the root and it's not in dialog mode)
@@ -257,7 +244,7 @@ namespace Umbraco.Web.Trees
if (queryStrings.HasKey(TreeQueryStringParameters.StartNodeId))
altStartId = queryStrings.GetValue<string>(TreeQueryStringParameters.StartNodeId);
//check if a request has been made to render from a specific start node
//check if a request has been made to render from a specific start node
if (string.IsNullOrEmpty(altStartId) == false && altStartId != "undefined" && altStartId != Constants.System.Root.ToString(CultureInfo.InvariantCulture))
{
id = altStartId;
@@ -324,7 +311,7 @@ namespace Umbraco.Web.Trees
menu.Items.Add<ActionEmptyTranscan>(ui.Text("actions", "emptyTrashcan"));
menu.Items.Add<ActionRefresh>(ui.Text("actions", ActionRefresh.Instance.Alias), true);
return menu;
}
}
return PerformGetMenuForNode(id, queryStrings);
}
@@ -355,8 +342,8 @@ namespace Umbraco.Web.Trees
internal IEnumerable<MenuItem> GetAllowedUserMenuItemsForNode(IUmbracoEntity dd)
{
var actions = ActionsResolver.Current.FromActionSymbols(Security.CurrentUser.GetPermissions(dd.Path, Services.UserService))
.ToList();
.ToList();
// A user is allowed to delete their own stuff
if (dd.CreatorId == Security.GetUserId() && actions.Contains(ActionDelete.Instance) == false)
actions.Add(ActionDelete.Instance);
@@ -370,12 +357,12 @@ namespace Umbraco.Web.Trees
/// <param name="doc">The Document to check permissions against</param>
/// <param name="allowedUserOptions">A list of MenuItems that the user has permissions to execute on the current document</param>
/// <remarks>By default the user must have Browse permissions to see the node in the Content tree</remarks>
/// <returns></returns>
/// <returns></returns>
internal bool CanUserAccessNode(IUmbracoEntity doc, IEnumerable<MenuItem> allowedUserOptions)
{
return allowedUserOptions.Select(x => x.Action).OfType<ActionBrowse>().Any();
}
/// <summary>
/// this will parse the string into either a GUID or INT
/// </summary>
@@ -399,11 +386,11 @@ namespace Umbraco.Web.Trees
{
var guidUdi = idUdi as GuidUdi;
if (guidUdi != null)
return new Tuple<Guid?, int?>(guidUdi.Guid, null);
}
return new Tuple<Guid?, int?>(guidUdi.Guid, null);
}
return null;
}
}
/// <summary>
/// Get an entity via an id that can be either an integer, Guid or UDI
@@ -442,11 +429,11 @@ namespace Umbraco.Web.Trees
}
return entity;
});
});
}
}
private readonly ConcurrentDictionary<string, IUmbracoEntity> _entityCache = new ConcurrentDictionary<string, IUmbracoEntity>();
}
}
@@ -1,5 +1,8 @@
using System.Net.Http.Formatting;
using umbraco;
using umbraco.BusinessLogic.Actions;
using Umbraco.Core;
using Umbraco.Core.Services;
using Umbraco.Web.Models.Trees;
using Umbraco.Web.Mvc;
using Umbraco.Web.WebApi.Filters;
@@ -53,6 +56,31 @@ namespace Umbraco.Web.Trees
protected override MenuItemCollection GetMenuForNode(string id, FormDataCollection queryStrings)
{
var menu = new MenuItemCollection();
if (id == Constants.System.Root.ToInvariantString())
{
//Create User
var createMenuItem = menu.Items.CreateMenuItem<ActionNew>(Services.TextService.Localize("actions/create"));
createMenuItem.Icon = "add";
createMenuItem.NavigateToRoute("users/users/overview?subview=users&create=true");
menu.Items.Add(createMenuItem);
//This is the same setting used in the global JS for 'showUserInvite'
if (EmailSender.CanSendRequiredEmail)
{
//Invite User (Action import closest type of action to an invite user)
var inviteMenuItem = menu.Items.CreateMenuItem<ActionImport>(Services.TextService.Localize("user/invite"));
inviteMenuItem.Icon = "message-unopened";
inviteMenuItem.NavigateToRoute("users/users/overview?subview=users&invite=true");
menu.Items.Add(inviteMenuItem);
}
return menu;
}
//There is no context menu options for editing a specific user
//Also we no longer list each user in the tree & in theory never hit this
return menu;
}
}
+2 -2
View File
@@ -105,8 +105,8 @@
<HintPath>..\packages\AutoMapper.3.3.1\lib\net40\AutoMapper.Net4.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="ClientDependency.Core, Version=1.9.4.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\ClientDependency.1.9.4\lib\net45\ClientDependency.Core.dll</HintPath>
<Reference Include="ClientDependency.Core, Version=1.9.6.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\ClientDependency.1.9.6\lib\net45\ClientDependency.Core.dll</HintPath>
</Reference>
<Reference Include="dotless.Core, Version=1.5.2.0, Culture=neutral, PublicKeyToken=96b446c9e63eae34, processorArchitecture=MSIL">
<HintPath>..\packages\dotless.1.5.2\lib\dotless.Core.dll</HintPath>
+1 -1
View File
@@ -118,7 +118,7 @@ namespace Umbraco.Web
ViewEngines.Engines.Add(new PluginViewEngine());
//set model binder
ModelBinderProviders.BinderProviders.Add(new RenderModelBinder()); // is a provider
ModelBinderProviders.BinderProviders.Add(RenderModelBinder.Instance); // is a provider
////add the profiling action filter
//GlobalFilters.Filters.Add(new ProfilingActionFilter());

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