Compare commits

...

251 Commits

Author SHA1 Message Date
Sebastiaan Jansssen b6b7b9f433 Bump version to 7.7.7 2017-12-11 13:57:31 +01:00
Mikkel Holck Madsen fb99b101d8 Merge pull request #2340 from umbraco/temp-U4-10610
U4-10610 Cannot restore content templates
2017-12-05 13:47:11 +01:00
Claus 0ce7efc978 U4-10610 Cannot restore content templates 2017-12-05 10:19:12 +01:00
Mikkel Holck Madsen 11bdfbba19 Merge pull request #2338 from umbraco/temp-u4-10715
U4-10715 - scheduled publishing and LB issue
2017-11-30 10:57:12 +01:00
Stephan 9694831638 U4-10715 - scheduled publishing and LB issue 2017-11-30 08:54:16 +01:00
bjarnef 8d14a3ef2c added number validation in embed overlay 2017-11-20 12:36:12 +01:00
bjarnef 2f3d9c9509 localize texts 2017-11-20 12:32:09 +01:00
Robert 6e8f3b6e13 Merge pull request #2324 from umbraco/temp-UAASSSCRUM-1254
Added custom RollingFileAppender and changed rollingStyle to "size"
2017-11-17 13:03:48 +01:00
mikkelhm b9cbdbd9a7 Add rename of Appender to csproj 2017-11-17 12:01:32 +01:00
mikkelhm ebf35356a8 Updates the CustomRollingFileAppender to read config settings to control it 2017-11-17 12:00:42 +01:00
Sebastiaan Janssen 7eca99e249 Bump version to 7.7.6 2017-11-15 15:21:25 +01:00
Sebastiaan Janssen 837bb83d48 Merge remote-tracking branch 'origin/dev-v7.6' into dev-v7 2017-11-15 14:40:19 +01:00
Sebastiaan Janssen 054ac78970 Revert "Position changed from "target" to "center""
This reverts commit c1769aa299.
2017-11-15 14:39:09 +01:00
Robert 5982a868ea Added custom RollingFileAppender and changed rollingStyle to "size"
OpenFile method has been overiden, this means that everytime a log will be opened, it will check the last access time of all existing logs, and delete the ones that haven't been accessed in more than 1 month.

Changing the rollingStyle to "size" will make sure that logs will roll once the maximumFileSize reaches its set limit.
2017-11-14 12:01:11 +01:00
Sebastiaan Janssen 69a42e26a9 Merge remote-tracking branch 'origin/dev-v7.6' into dev-v7 2017-11-14 11:42:00 +01:00
Sebastiaan Janssen d9ed420ed4 U4-10492 Users failing to list with MySQL 2017-11-14 11:38:45 +01:00
Sebastiaan Janssen 2b3397120f Disambiguate events by explicitly naming them 2017-11-14 11:23:48 +01:00
Sebastiaan Janssen 1f41aa7d81 Merge branch 'dev-v7.6' into dev-v7
# Conflicts:
#	src/SolutionInfo.cs
#	src/Umbraco.Core/Configuration/UmbracoVersion.cs
#	src/Umbraco.Web.UI/Umbraco.Web.UI.csproj
#	src/Umbraco.Web.UI/packages.config
2017-11-14 07:19:08 +01:00
Sebastiaan Janssen dad77fc506 Bump version to 7.7.5 2017-11-14 07:17:19 +01:00
Sebastiaan Janssen 350f5c88c7 Bump version to 7.6.12 2017-11-14 07:16:14 +01:00
Stephan 928c0dc535 Merge pull request #2314 from umbraco/temp-U4-10646
U4-10646 Sorting nodes in edge cases can lead to blanking out of property data
2017-11-13 17:33:27 +01:00
Sebastiaan Janssen cc7a28db65 Update to latest ImageProcessor 2017-11-13 15:39:29 +01:00
Sebastiaan Janssen 065e764957 Update to latest Examine 2017-11-13 15:39:28 +01:00
Sebastiaan Janssen 000ba73887 Merge branch 'dev-v7.6' into dev-v7
# Conflicts:
#	build/NuSpecs/UmbracoCms.Core.nuspec
#	src/Umbraco.Tests/Umbraco.Tests.csproj
#	src/Umbraco.Tests/packages.config
#	src/Umbraco.Web.UI/Umbraco.Web.UI.csproj
#	src/Umbraco.Web.UI/packages.config
#	src/Umbraco.Web/Umbraco.Web.csproj
#	src/Umbraco.Web/packages.config
#	src/UmbracoExamine/UmbracoExamine.csproj
#	src/UmbracoExamine/packages.config
#	src/umbraco.MacroEngines/packages.config
#	src/umbraco.MacroEngines/umbraco.MacroEngines.csproj
2017-11-13 15:38:59 +01:00
Sebastiaan Janssen 08b81d991b Update to latest ImageProcessor 2017-11-13 15:33:54 +01:00
Sebastiaan Janssen 4937f87c0d Update to latest Examine 2017-11-13 15:27:15 +01:00
Claus dc67d82671 adding trim. 2017-11-08 12:08:30 +01:00
Claus c7d9683fc4 Merge pull request #2277 from umbraco/temp-U4-10589
U4-10589 Login should be sanitized and/or cause validation errors if trying to save with
2017-11-08 12:07:34 +01:00
Mads Rasmussen ed7675bdcd Merge pull request #1584 from readingdancer/U4-9144
Style changes to the developer dashboard area.
2017-11-08 11:49:48 +01:00
Mads Rasmussen 3c7c6b4ad7 Update thumbnails.less
Use new color variables
2017-11-08 11:38:32 +01:00
Mads Rasmussen 838d7975c9 Update healthcheck.less
prevent UI from "jumping" on hover
2017-11-08 11:36:23 +01:00
Mads Rasmussen 5af9712d51 Merge branch 'dev-v7' into U4-9144 2017-11-08 10:43:58 +01:00
Shannon e2c2b8534f Merge branch 'dev-v7' of https://github.com/umbraco/Umbraco-CMS into dev-v7 2017-11-08 19:48:02 +11:00
Shannon cfd3cc5187 OK... maybe that is now required 2017-11-08 19:47:47 +11:00
Sebastiaan Janssen 1f29418ea5 Revert "Adds overloads so you can do paging with the TypedSearch methods."
This reverts commit 089f488c15.
2017-11-08 09:23:58 +01:00
Shannon 977b30c51a Revert "more test hacks" which in theory shouldn't be required for 7.7+ 2017-11-08 19:23:34 +11:00
Shannon 66a849dd12 Merge branch 'dev-v7.6' into dev-v7 2017-11-08 19:20:28 +11:00
Shannon 637abc384b more test hacks 2017-11-08 18:46:08 +11:00
Shannon 8959b81f6a another test fix attempt (this is only for 7.6, this is already fixed in 7.7) 2017-11-08 18:16:17 +11:00
Shannon 32bb8ac5a4 Merge branch 'dev-v7.6' of https://github.com/umbraco/Umbraco-CMS into dev-v7.6 2017-11-08 17:47:32 +11:00
Shannon 016caba35f attempt to fix tests 2017-11-08 17:47:18 +11:00
Shannon 9290f61f94 Merge branch 'dev-v7.6' into dev-v7
# Conflicts:
#	src/Umbraco.Core/Security/MembershipProviderExtensions.cs
#	src/Umbraco.Web.UI/umbraco/config/lang/en.xml
#	src/Umbraco.Web.UI/umbraco/config/lang/en_us.xml
2017-11-08 17:36:27 +11:00
Shannon Deminick d522dd7a31 Merge pull request #2313 from umbraco/temp-U4-10620
U4-10620 Umbraco 2FA implementation issues
2017-11-08 17:18:31 +11:00
Shannon 95f632e1ea Adds notes and overrides SendTwoFactorCodeAsync and checks for -1 instead of null 2017-11-08 17:16:11 +11:00
Shannon Deminick e72ec171f7 Merge pull request #2312 from umbraco/temp-U4-9857
Temp u4 9857
2017-11-08 16:06:53 +11:00
Shannon 2538e2e9c9 additional null check 2017-11-08 16:06:23 +11:00
Daniël Knippers b1ceeb23b3 Only show characters left is a number of characters is configured on the datatype, hide otherwise 2017-11-07 23:13:59 +01:00
Sebastiaan Janssen 46d0807fa4 Merge pull request #2287 from PerplexDaniel/U4-6985
Switching between sections - select last node
2017-11-07 20:26:25 +01:00
Sebastiaan Janssen 579c572dd8 Oops, missed that I was passing a string array into the int array param 2017-11-07 18:36:37 +01:00
Sebastiaan Janssen bbf4c18825 U4-10646 Sorting nodes in edge cases can lead to blanking out of property data 2017-11-07 17:12:04 +01:00
Sebastiaan Janssen 9a94ac5317 Implement TwoFactorSignInAsync from Identity repo to make sure our custom GetVerifiedUserIdAsync fires
U4-10620 Umbraco 2FA implementation issues
2017-11-07 16:51:40 +01:00
Sebastiaan Janssen 0b904e82b5 Get user by id instead of loginname
U4-9857 Umbraco 7.6 - Exception after changing user login name
2017-11-07 16:36:15 +01:00
Claus c816558936 cleanup. 2017-11-07 15:14:45 +01:00
Sebastiaan Janssen 51fec0c7d3 Remove misleading text, nothing bad will happen when you close the sort panel, sorting is a background task. 2017-11-07 14:03:17 +01:00
Sebastiaan Janssen 87ace12a4f Prevent double clicks of the Save button
U4-10646 Sorting nodes in edge cases can lead to blanking out of property data
2017-11-07 13:49:02 +01:00
Sebastiaan Janssen 632f84904f Merge branch 'dev-v7.6' into dev-v7 2017-11-07 10:32:12 +01:00
Daniël Knippers a1fd73cdb0 Feature Request: Double Click Content Node to Expand
Doube-clicking a tree item now expands or collapses a node. It basically does the exact same as clicking the triangle left of the node.

(cherry picked from commit bd2a794b59)
2017-11-07 10:30:08 +01:00
Sebastiaan Janssen a53866953e Merge pull request #2296 from PerplexDaniel/U4-6259
Feature Request: Double Click Content Node to Expand
2017-11-07 10:29:10 +01:00
Sebastiaan Janssen ff996b05f0 Merge branch 'dev-v7.6' into dev-v7 2017-11-06 17:30:00 +01:00
Sebastiaan Janssen 403502ef1b Merge pull request #2294 from ja0b/U4-854
U4-854 Add MaxLength to Textstring fields --> Fixed

(cherry picked from commit ee4ad36e70)
2017-11-06 17:11:12 +01:00
Sebastiaan Janssen ee4ad36e70 Merge pull request #2294 from ja0b/U4-854
U4-854 Add MaxLength to Textstring fields --> Fixed
2017-11-06 17:08:46 +01:00
Sebastiaan Janssen 4f2650277a Don't need showcharacterslefttext if we're always showing number of chars left 2017-11-06 17:07:14 +01:00
Sebastiaan Janssen 0231a6037e Always show number of characters left
Makes it less magical as to why you can't type any more characters.
2017-11-06 17:03:23 +01:00
Sebastiaan Janssen db51a5bb44 Update TextboxPropertyEditor.cs 2017-11-06 17:02:34 +01:00
Sebastiaan Janssen d1b7063e44 Rename textstringnumber.html to textstringlimited.html 2017-11-06 17:02:08 +01:00
Sebastiaan Janssen 364d4b11e8 Merge branch 'dev-v7.6' into dev-v7 2017-11-06 15:00:05 +01:00
Craig c1769aa299 Position changed from "target" to "center"
Prevents modal jumping position on HIDPI screens

(cherry picked from commit 422be31c4e)
2017-11-06 14:58:31 +01:00
Sebastiaan Janssen a571eee945 Merge pull request #2292 from craigs100/U4-10628
U4-10628
2017-11-06 14:57:46 +01:00
prjseal 143d127fb9 Format date in backoffice based on Users language
We have formatted the Created Date and Updated Date using the Current
Culture of the application.

(cherry picked from commit 10ca1239b6)
2017-11-06 14:03:54 +01:00
Lewis Smith 01cf2e240a U4-10627 - Updated stats / facts when installing.
U4-10627 Update some of the Umbraco Installer facts. Updated the facts you get when installing umbraco. All facts that were changed were taken from the Umbraco page.

https://umbraco.com/blog/codegarden-2017-the-aftermath/
https://umbraco.com/blog/codegarden-2017/
(cherry picked from commit 69258fee7b)
2017-11-06 13:51:43 +01:00
Tim 49689d5057 Fixes missing content type check.
(cherry picked from commit 80d605beac)
2017-11-06 13:48:09 +01:00
Andy Felton f722d7731d Fixed URL Tracker button colour
(cherry picked from commit bb9a0258df)
2017-11-06 13:47:05 +01:00
Sebastiaan Janssen 74ba3261ff Merge branch 'dev-v7.6' into dev-v7 2017-11-06 12:33:48 +01:00
Sebastiaan Janssen ac42f335c2 Fix U4-4889 checkbox in template 2017-11-06 12:33:12 +01:00
Sebastiaan Janssen f0eefbd5af U4-10636 Removed '#' from 'value' when generating alias 2017-11-06 12:31:06 +01:00
Sebastiaan Janssen ed48f29e3a Merge pull request #2300 from dernafees/dev-v7
Fix U4-4889 checkbox in template.
2017-11-06 12:28:32 +01:00
Sebastiaan Janssen 03c5d5197b Updates a few more fields to make sure clicking on labels focuses the field 2017-11-06 12:28:14 +01:00
Sebastiaan Janssen 7f0921bd96 Delete web.config.temp-build.0 2017-11-06 12:09:15 +01:00
Sebastiaan Janssen c38b49b1cf Delete vwd.webinfo 2017-11-06 12:08:45 +01:00
Sebastiaan Janssen c4dfbd4a1c Merge pull request #2304 from pbres/dev-v7
U4-10636 Unable to generate alias for localized name
2017-11-06 12:04:16 +01:00
Sebastiaan Janssen 9b1e5d7649 Update entity.resource.js 2017-11-06 12:03:53 +01:00
Pawel Bres c07b96ade7 Merge pull request #1 from pbres/pbres-patch-1
Removed '#' from 'value' when generating alias
2017-11-04 15:09:00 +01:00
Pawel Bres 576a790e2f Removed '#' from 'value' when generating alias
When '#' is presented in the 'value' everything in the GET URL after '#' gets removed because it's being treated as "hash" part of the URL and it's not being sent to the server at all.
2017-11-04 15:07:47 +01:00
Alejandro Ocampo 29f93160b7 removing unnecessary if statement 2017-11-03 11:51:39 +01:00
Warren Buckley 827e79c705 Merge pull request #2280 from umbraco/temp-U4-10625
U4-10625 HealthCheckController non-empty constructor fails to initial…
2017-11-03 09:29:14 +00:00
Stephan f6ea317dd1 Merge pull request #2299 from PerplexDaniel/U4-10582
Make a shiny template for the emails that are sent from Umbraco
2017-11-02 18:19:32 +01:00
Stephan 68e8ca8d8e Merge pull request #2289 from LewisS303/U4-10627
U4-10627 - Updated stats / facts when installing.
2017-11-02 18:03:25 +01:00
Stephan bcae131545 Merge pull request #2067 from Xiaohao112/patch-1
Created a link to composition doctype
2017-11-02 17:55:30 +01:00
Haider Naji c6d686eabd Fix U4-4889 checkbox in template. 2017-11-02 16:50:19 +00:00
Sebastiaan Janssen a8b660bfbf Check for itemMinHeight on scope before trying to set it 2017-11-02 17:46:01 +01:00
Sebastiaan Janssen 1f60486df8 Merge pull request #2232 from marcemarc/temp-U4-10510
Check for itemMinHeight on scope before trying to set it
2017-11-02 16:45:23 +00:00
Daniël Knippers c066280990 Make a shiny template for the emails that are sent from Umbraco
Make a shiny template for the emails that are sent from Umbraco (only for EN and EN-US).
2017-11-02 16:44:08 +00:00
Sebastiaan Janssen ba747ea579 Merge pull request #2293 from LottePitcher/ReadmeUpdate
Update README.md with correct location of build.bat
2017-11-02 16:42:43 +00:00
Stephan 6f857b16ee Merge pull request #2286 from Attackmonkey/U4-9291
Adds overloads so you can do paging with the TypedSearch methods.
2017-11-02 17:25:26 +01:00
Alejandro Ocampo 27115e5794 U4-854 Add MaxLength to Textstring fields --> Fixed 2017-11-02 17:14:13 +01:00
Stephan 13e6a81bbe Merge pull request #2291 from Attackmonkey/U4-9613
Fixes missing content type check.
2017-11-02 17:03:58 +01:00
Daniël Knippers bd2a794b59 Feature Request: Double Click Content Node to Expand
Doube-clicking a tree item now expands or collapses a node. It basically does the exact same as clicking the triangle left of the node.
2017-11-02 16:01:24 +00:00
Stephan 576ffce9aa Merge pull request #2290 from AndyFelton/U4-9932
Fixed URL Tracker button colour
2017-11-02 16:56:57 +01:00
Lotte Pitcher 3bfdaa7e10 Update README.md with correct location of build.bat
With a link to the build markdown page
2017-11-02 15:39:57 +00:00
Sebastiaan Janssen dc7b5bae9b Fix U4-10618 - AbstractConfigCheck SuccessMessages are missing CurrentValue 2017-11-02 16:28:58 +01:00
Craig 422be31c4e Position changed from "target" to "center"
Prevents modal jumping position on HIDPI screens
2017-11-02 15:26:20 +00:00
Sebastiaan Janssen 8d8fb76694 Merge pull request #2279 from Jeavon/temp-U4-10618
Fix U4-10618 - AbstractConfigCheck
2017-11-02 15:25:24 +00:00
Tim 80d605beac Fixes missing content type check. 2017-11-02 15:17:35 +00:00
Andy Felton bb9a0258df Fixed URL Tracker button colour 2017-11-02 15:06:13 +00:00
Lewis Smith 69258fee7b U4-10627 - Updated stats / facts when installing.
U4-10627 Update some of the Umbraco Installer facts. Updated the facts you get when installing umbraco. All facts that were changed were taken from the Umbraco page.

https://umbraco.com/blog/codegarden-2017-the-aftermath/ 
https://umbraco.com/blog/codegarden-2017/
2017-11-02 14:31:19 +00:00
Stephan 1fd7569c6e Merge pull request #2285 from prjseal/U4-6152
Format date in backoffice based on Users language
2017-11-02 15:20:40 +01:00
Robert 3a1f19ee0a Merge pull request #2283 from jchurchley/U4-9142
U4-9142 - Multiple Related Links pickers on same Document Type not working
2017-11-02 15:09:50 +01:00
Daniël Knippers 90bc7f5829 Switching between sections - select last node
When returning to a previously visited section, will open the last selected node within that section immediately again, if any.
2017-11-02 15:06:35 +01:00
Claus 30b391f3fb Merge pull request #2281 from umbraco/temp-U4-10622
U4-10622 Corrupted id/key map
2017-11-02 14:56:35 +01:00
Tim 089f488c15 Adds overloads so you can do paging with the TypedSearch methods. 2017-11-02 13:55:19 +00:00
Stephan 99b99ce3cd Merge branch 'tompipe-U4-8982-AddIsPublishedtoExamine' into dev-v7 2017-11-02 14:44:39 +01:00
prjseal 10ca1239b6 Format date in backoffice based on Users language
We have formatted the Created Date and Updated Date using the Current
Culture of the application.
2017-11-02 13:44:05 +00:00
Stephan f4fc3c4db4 Merge branch 'U4-8982-AddIsPublishedtoExamine' of https://github.com/tompipe/Umbraco-CMS into tompipe-U4-8982-AddIsPublishedtoExamine 2017-11-02 14:44:03 +01:00
DESKTOP-6DNOQH9\John 234c0680d8 Checking if $scope.model.value is an array on the add method. 2017-11-02 12:15:04 +00:00
Stephan ea8c6af028 Document common PowerShell issues when building 2017-11-02 13:07:45 +01:00
Shannon Deminick 5f31c70cbe stats 2017-11-02 18:39:47 +11:00
Shannon Deminick 579a04d179 updates stats 2017-11-02 18:37:56 +11:00
Shannon ff3b7963b1 U4-10622 Corrupted id/key map 2017-11-02 15:35:47 +11:00
Shannon e85d212891 U4-10625 HealthCheckController non-empty constructor fails to initialize the correct variables 2017-11-02 15:18:58 +11:00
Jeavon ef40ecfefd Fix U4-10618 - AbstractConfigCheck SuccessMessages are missing CurrentValue 2017-11-01 12:34:24 +00:00
Robert 73b2d31298 Moved username trimming to service level, also added email trimming 2017-11-01 13:08:17 +01:00
Robert 8676a99b3a Trimming login input on the server-side as well 2017-11-01 09:00:05 +01:00
Sebastiaan Janssen 84b380028c Fixes U4-9401 Double slashes in some Umbraco generated urls causes broken links 2017-10-31 23:21:41 +01:00
Robert 0b2cfe956d Triming login field to avoid validation errors 2017-10-31 15:19:06 +01:00
Shannon Deminick 006deb22db Merge pull request #2271 from richarth/patch-1
Updated grammar
2017-10-31 11:22:52 +11:00
Shannon Deminick 40624255ca Merge pull request #2272 from bjarnef/dev-v7-U4-10609
U4-10609 - Fix missing end closing <div> in login screen
2017-10-31 11:22:04 +11:00
Bjarne Fyrstenborg 24900fb9f8 Fix missing end closing <div> 2017-10-30 18:39:21 +01:00
Richard Thompson 594c473134 Updated grammar
Updated the grammar of the email validation messages
2017-10-30 15:00:08 +00:00
Shannon Deminick 49d54f8ca5 Merge pull request #2266 from ProNotion/issues/U4-9401
Fixes  U4-9401 Double slashes in some Umbraco generated urls causes broken links
2017-10-27 14:32:04 +11:00
Simon Dingley 731e380445 Fixes U4-9401 Double slashes in some Umbraco generated urls causes broken links 2017-10-26 14:27:23 +01:00
Shannon Deminick bd0edb322d Merge pull request #2262 from umbraco/temp-U4-10564
U4-10564 - Update ImageProcessor dependencies
2017-10-26 15:06:36 +11:00
Sebastiaan Janssen f766057e50 Merge branch 'dev-v7.6' into dev-v7
# Conflicts:
#	src/Umbraco.Core/PluginManager.cs
#	src/Umbraco.Tests/TestHelpers/BaseUmbracoApplicationTest.cs
2017-10-25 14:13:38 +02:00
Sebastiaan Janssen f0b5c831f1 Manually applied all changes for U4-10503 Umbraco plugins cache files should be stored in the same local temp location as the umbraco xml cache file 2017-10-25 14:05:56 +02:00
Shannon d3232a09fb U4-10503 Umbraco plugins cache files should be stored in the same local temp location as the umbraco xml cache file
(cherry picked from commit 7b3f7f4ad4)
2017-10-25 13:42:10 +02:00
Sebastiaan Janssen 586c59949a Merge branch 'dev-v7.6' into dev-v7
# Conflicts:
#	src/SolutionInfo.cs
#	src/Umbraco.Core/Configuration/UmbracoVersion.cs
#	src/Umbraco.Web.UI/Umbraco.Web.UI.csproj
2017-10-25 13:05:11 +02:00
Shannon 7cbaecc53a U4-10538 Disable Ping on front-end nodes when load balancing
(cherry picked from commit fd8daa398f)
2017-10-25 13:03:31 +02:00
Stephan e84a963d66 U4-10121 - Scheduled Publishing as background task
(cherry picked from commit 79df75c415)
2017-10-25 11:51:42 +02:00
Sebastiaan Janssen 58c180d6cc Merge pull request #2242 from umbraco/temp-U4-10538
U4-10538 Disable Ping on front-end nodes when load balancing
2017-10-24 17:21:13 +02:00
Sebastiaan Janssen 18e377f159 U4-10564 - Update ImageProcessor dependencies 2017-10-24 13:20:33 +02:00
Sebastiaan Janssen 7e7f9902f6 Bumps version to 7.7.4 2017-10-23 14:18:00 +02:00
Sebastiaan Janssen a36184a261 Bump version to 7.6.11 2017-10-23 14:14:59 +02:00
Sebastiaan Janssen dcd2630d6b Merge branch 'dev-v7.6' into dev-v7 2017-10-23 14:10:04 +02:00
Sebastiaan Janssen b70f543790 Reverts wrongly committed files 2017-10-23 14:02:00 +02:00
Sebastiaan Janssen 24c1c15b66 Merge branch 'dev-v7' of https://github.com/umbraco/Umbraco-CMS into dev-v7 2017-10-23 13:59:30 +02:00
Sebastiaan Janssen 4a0cd7228b Revert "U4-10554 - warn if closing page with changes"
This reverts commit 24b147e2a6.
2017-10-23 13:59:06 +02:00
Stephan edfe212227 Fix login issue 2017-10-20 15:35:30 +02:00
Sebastiaan Janssen e3bc98a155 Merge pull request #2257 from umbraco/temp-U4-10566
U4-10566 The legacy API Member.PopulateGroups throws an exception
2017-10-19 06:59:18 -07:00
Shannon f85532f15e U4-10566 The legacy API Member.PopulateGroups throws an exception 2017-10-20 00:56:34 +11:00
Sebastiaan Janssen b04d71ca5f Merge pull request #2256 from richarth/patch-1
Removed duplicate translations
2017-10-19 00:41:33 -07:00
Sebastiaan Janssen ab4de382f3 Merge pull request #2252 from umbraco/temp-u4-7317
U4-7317 - select default template
2017-10-18 12:38:53 -07:00
Sebastiaan Janssen a293c633fc Merge pull request #2249 from umbraco/temp-u4-8652
U4-8652 - accept exceptions when loading some assemblies
2017-10-18 11:00:45 -07:00
Richard Thompson 507e3ece98 Removed duplicate translations
Removed duplicate definition of English translations
2017-10-18 15:36:17 +01:00
Stephan b77826fd3d Merge branch 'dev-v7' of https://github.com/umbraco/Umbraco-CMS into dev-v7 2017-10-18 12:18:59 +02:00
Stephan 4c7358d63b U4-8960 - minor fixes 2017-10-18 12:17:58 +02:00
Stephan 4814612102 Merge branch 'U4-8960' of https://github.com/lars-erik/Umbraco-CMS into temp-u4-8960 2017-10-18 11:56:00 +02:00
Robert 6dae4396bb Merge pull request #2250 from umbraco/temp-u4-10554
U4-10554 - warn if closing page with changes
2017-10-18 11:53:54 +02:00
Stephan dd5560f00b U4-8616 - minor cleanup 2017-10-18 10:11:23 +02:00
Stephan b56575fc50 Merge branch 'dev-v7' of https://github.com/jhauge/Umbraco-CMS into temp-u4-8616 2017-10-18 09:49:05 +02:00
Stephan b06d30c0f9 U4-10554 - cross-browser 2017-10-18 09:29:50 +02:00
Claus 9c50e1c48d fixing bug in U4-10524 Show warning in UI for the media/content picker that is referencing a trashed or deleted item 2017-10-17 23:52:34 +02:00
Claus 0688835ac0 fixing bug in U4-10524 Show warning in UI for the media/content picker that is referencing a trashed or deleted item 2017-10-17 23:44:03 +02:00
Stephan 353b8f21cd U4-7317 - select default template 2017-10-17 16:04:31 +02:00
Stephan 30a0d553d5 Merge pull request #1230 from bjarnef/dev-v7-U4-8319
U4-8319 - Sort data types array by name A-Z
2017-10-17 15:06:54 +02:00
Stephan d0fbc362b2 Merge branch 'dev-v7' of https://github.com/umbraco/Umbraco-CMS into dev-v7 2017-10-17 15:00:13 +02:00
Stephan 39c534ef54 Merge branch 'temp-u4-7115' into dev-v7 2017-10-17 14:59:56 +02:00
Stephan 7f86166abf Merge branch 'dev-v7' of https://github.com/hfloyd/Umbraco-CMS into temp-u4-7115 2017-10-17 14:59:07 +02:00
Robert 838e86469a Merge pull request #2245 from umbraco/temp-u4-5322
U4-5322 - add labels to color picker
2017-10-17 14:47:36 +02:00
Stephan 24b147e2a6 U4-10554 - warn if closing page with changes 2017-10-17 14:39:47 +02:00
Stephan 11342ff1df U4-8652 - accept exceptions when loading some assemblies 2017-10-17 14:04:24 +02:00
Robert bf20af9345 Merge pull request #2247 from umbraco/temp-u4-5722b
Temp u4 5722b
2017-10-17 13:19:34 +02:00
Robert c69774e3f2 Merge pull request #2246 from umbraco/temp-u4-7360
U4-7360 - toggle password visibility
2017-10-17 12:30:37 +02:00
Robert 7de8f5a59a Added missing width and height to the "show password" icon
Not having the height and width on the icon, caused IE 11 to shrink the icon which looked a bit off.
2017-10-17 12:09:55 +02:00
Sebastiaan Janssen 6795afd5c2 Merge branch 'dev-v7.6' into dev-v7
# Conflicts:
#	src/SolutionInfo.cs
#	src/Umbraco.Core/Configuration/UmbracoVersion.cs
#	src/Umbraco.Web.UI/Umbraco.Web.UI.csproj
#	src/Umbraco.Web/UmbracoDefaultOwinStartup.cs
2017-10-17 11:06:52 +02:00
Sebastiaan Janssen 9411a22a0d Don't forget to call the ConfigureUmbracoAuthentication method 2017-10-17 11:04:01 +02:00
Sebastiaan Janssen 461ce64feb Bump version to 7.6.10 2017-10-17 10:57:18 +02:00
Robert 53c251feb5 Merge pull request #2237 from umbraco/temp-U4-10504
U4-10504 Previewing content results in the same PrepareDocument (expe…
2017-10-17 10:20:21 +02:00
Sebastiaan Janssen c5a55b17e6 Manually applying U4-10369: Split out ConfigureUmbracoAuthentication method 2017-10-17 10:08:37 +02:00
Sebastiaan Janssen fd577afe2c Html encode nodenames to prevent XSS attacks. Fixes U4-10497 XSS Vulnerability in page name.
(cherry picked from commit fe2b86b681)
2017-10-16 20:32:56 +02:00
Sebastiaan Janssen f46ef0b006 U4-10506 Importing a specially crafted document type file can cause XXE attack
(cherry picked from commit 5dde2efe0d)
2017-10-16 20:32:04 +02:00
Stephan 909e3788ea Merge branch 'U4-5722' of https://github.com/NikRimington/Umbraco-CMS into temp-u4-5722b 2017-10-16 17:20:19 +02:00
Stephan 09a92ef6ce U4-7360 - toggle password visibility 2017-10-16 16:58:15 +02:00
Stephan 7d9c2bcce9 Merge branch 'dev-v7' into temp-u4-5322 2017-10-16 16:32:43 +02:00
Stephan 529ae961ff U4-5322 - add labels to color picker 2017-10-16 16:16:43 +02:00
Sebastiaan Janssen 04f64cd804 Merge branch 'dev-v7.6' into dev-v7
# Conflicts:
#	src/Umbraco.Web/Editors/MediaController.cs
2017-10-16 16:14:54 +02:00
Sebastiaan Janssen dc937ec942 Fix the "Add media" box no longer being square 2017-10-16 16:13:47 +02:00
Shannon cefd9e7323 Fixes PostAddFolder
(cherry picked from commit c5d874464a)

# Conflicts:
#	src/Umbraco.Web/Editors/MediaController.cs
2017-10-16 15:53:54 +02:00
Mads Rasmussen 315690e758 fixes breadcrumbs and search when start node is set
(cherry picked from commit 1ec07aa205)
2017-10-16 15:14:24 +02:00
Mads Rasmussen fb8c519f71 fixes: U4-10521 Creating new folders from the media picker no longer works
(cherry picked from commit 1cc3b39601)

# Conflicts:
#	src/Umbraco.Web.UI.Client/src/views/common/overlays/mediaPicker/mediapicker.html
2017-10-16 15:13:56 +02:00
Sebastiaan Janssen 80f172e3fb Bump version to 7.7.3 2017-10-16 14:56:43 +02:00
Sebastiaan Janssen 5eced19816 Merge branch 'dev-v7.6' into dev-v7
# Conflicts:
#	src/Umbraco.Web.UI.Client/src/less/property-editors.less
#	src/Umbraco.Web.UI.Client/src/views/propertyeditors/mediapicker/mediapicker.controller.js
2017-10-16 14:24:18 +02:00
Warren Buckley 5df4d3509d Fix in PowerShell build - The 7Zip tool download was giving two paths & thus break the build script
(cherry picked from commit a2e6da2491)
2017-10-16 14:22:09 +02:00
Claus 4bd263e7bc U4-10524 Show warning in UI for the media/content picker that is referencing a trashed or deleted item
U4-10533 Show warning in UI for the link picker that is referencing a trashed or deleted item
cherrypicked from dev-v7.
2017-10-16 13:52:17 +02:00
Claus b094bfad29 U4-10533 Show warning in UI for the link picker that is referencing a trashed or deleted item 2017-10-16 13:05:20 +02:00
Sebastiaan Janssen e333f6c628 Merge pull request #2236 from umbraco/temp-U4-10521
fixes: U4-10521 Creating new folders from the media picker no longer …
2017-10-16 12:44:32 +02:00
Shannon 916bc6badb U4-10539 - reverts merge issue that reverted the fix for U4-9262
(cherry picked from commit 2a0cc71d06)
2017-10-16 08:38:17 +02:00
Sebastiaan Janssen 76ee23b933 Merge pull request #2243 from umbraco/temp-U4-10539
U4-10539 - reverts merge issue that reverted the fix for U4-9262
2017-10-16 08:36:56 +02:00
Shannon 2a0cc71d06 U4-10539 - reverts merge issue that reverted the fix for U4-9262 2017-10-16 17:05:33 +11:00
Shannon fd8daa398f U4-10538 Disable Ping on front-end nodes when load balancing 2017-10-16 16:22:10 +11:00
Warren Buckley a2e6da2491 Fix in PowerShell build - The 7Zip tool download was giving two paths & thus break the build script 2017-10-13 11:19:39 +01:00
Mads Rasmussen ba7d8b0955 Merge pull request #2240 from bjarnef/dev-v7-U4-10528
U4-10528 - Add better function to get initials from name
2017-10-13 10:13:00 +02:00
Shannon Deminick 7288bcf679 Merge pull request #2239 from umbraco/temp-U4-10524
U4-10524 Show warning in UI for any picker that is referencing a tras…
2017-10-13 17:08:16 +11:00
Shannon ca57b9c5e6 fixes issue with js exceptions 2017-10-13 16:50:39 +11:00
Shannon 62ce7f6132 U4-10519 Legacy create is broken 2017-10-13 16:33:49 +11:00
Bjarne Fyrstenborg b1f2c5d93a Add better function to get initials from name 2017-10-12 23:46:02 +02:00
Mads Rasmussen 1ec07aa205 fixes breadcrumbs and search when start node is set 2017-10-12 16:13:14 +02:00
Claus 13055ad1f2 U4-10524 Show warning in UI for any picker that is referencing a trashed or deleted item
fixing the trash flag not getting mapped via automapper.
fixing up the ui for mediapicker.
fixing a small ui issue with the contentpicker and trashed content.
2017-10-12 11:35:08 +02:00
Shannon d5447106a6 U4-10504 Previewing content results in the same PrepareDocument (expensive) procedure to be executed 3 times 2017-10-12 18:23:19 +11:00
Shannon c5d874464a Fixes PostAddFolder 2017-10-12 17:11:45 +11:00
Mads Rasmussen 1cc3b39601 fixes: U4-10521 Creating new folders from the media picker no longer works 2017-10-11 10:18:40 +02:00
Warren Buckley c5f4793d11 Merge pull request #2233 from umbraco/temp-U4-10503-2
U4-10503 Umbraco plugins cache files should be stored in the same local temp location as the umbraco xml cache file
2017-10-09 14:04:16 +01:00
Shannon 4175c0530f Merge branch 'dev-v7' into temp-U4-10503-2 2017-10-09 23:05:17 +11:00
Shannon cf97926f26 trying another test fix 2017-10-09 19:00:00 +11:00
Shannon 4b08c3a5c3 Reset PluginManager on each tests, no reason not to, this should resolve the issue 2017-10-09 18:20:07 +11:00
Shannon fbda4fc8d1 Fixes part of the failing tests 2017-10-09 17:49:01 +11:00
Shannon 312b994537 Merge branch 'dev-v7' into temp-U4-10503-2 2017-10-09 16:42:21 +11:00
Shannon dd1bfe9cbf Merge branch 'dev-v7' of https://github.com/umbraco/Umbraco-CMS into dev-v7 2017-10-09 16:08:14 +11:00
Shannon de17b69564 U4-10452 Unable to create new User Groups programmatically - publicizes UserGroup 2017-10-09 16:07:55 +11:00
Shannon 7f44f4a030 readonly field 2017-10-09 16:01:49 +11:00
Shannon 422219ab21 Updates the cache file paths to be resolved behind a lazy so that there's proper locking in place for accessing the value, this also makes the code a little nicer. 2017-10-09 16:01:22 +11:00
Shannon Deminick 9986a3c2c2 Merge pull request #2162 from Bitmapped/U4-9081-external
U4-10369: Split out ConfigureUmbracoAuthentication method
2017-10-09 15:50:45 +11:00
Shannon ce81416368 Ensures the DistCache file is stored in the same configured temp location as the plugin cache files 2017-10-09 14:50:34 +11:00
Shannon 04e04ae47a Ensures that the local folder does not also get created when using the env temp storage location, this is also a tiny bit better for perfs 2017-10-09 14:40:23 +11:00
Marc Goodson 4e6d60b755 Check for itemMinHeight on scope before trying to set it - Issue U4-10510 2017-10-07 15:07:28 +01:00
Warren Buckley 0f6e7d26c9 Merge pull request #1596 from StefanoChiodino/U4-7721
U4-7721 install button miss aligned
2017-10-06 15:00:09 +01:00
Warren Buckley 51ceba6fea Merge pull request #1780 from bjarnef/dev-v7-U4-9599
U4-9599 - Fix caret in font size select
2017-10-06 14:25:55 +01:00
Sebastiaan Janssen 5dde2efe0d U4-10506 Importing a specially crafted document type file can cause XXE attack 2017-10-06 15:14:41 +02:00
Sebastiaan Janssen fe2b86b681 Html encode nodenames to prevent XSS attacks. Fixes U4-10497 XSS Vulnerability in page name. 2017-10-06 14:38:21 +02:00
Warren Buckley 368fec4ac1 Merge pull request #2231 from umbraco/temp-U4-10503
U4-10503 Umbraco plugins cache files should be stored in the same local temp location as the umbraco xml cache file
2017-10-06 13:27:22 +01:00
Shannon 9016147118 Streamlines temp folder name so it's consistent, ensure the folder exists before writing to it 2017-10-06 12:11:20 +11:00
Shannon bee75803f7 Adds file exist checks 2017-10-06 11:51:27 +11:00
Shannon 7b3f7f4ad4 U4-10503 Umbraco plugins cache files should be stored in the same local temp location as the umbraco xml cache file 2017-10-06 11:47:25 +11:00
Shannon Deminick f6c25f29c0 Merge pull request #2229 from keroberts/dev-v7-U4-10496
Fix Typo in Email Property Editor
2017-10-06 01:01:48 +11:00
keroberts 6de3b920eb Fix Typo in Email Property Editor 2017-10-05 14:04:02 +01:00
Bitmapped 606abd8ac7 Restructure per discussion in U4-10369 2017-09-06 00:43:27 -04:00
Bitmapped 65db5396cf Spelling fix 2017-08-30 20:06:20 -04:00
Bitmapped 32d5a0a57c Add method for configuring external logins so things can be granularly overriden. 2017-08-30 20:04:30 -04:00
Nik 7367c8ef67 Re-do min max number of items in the grid after rebasing 2017-07-30 02:09:38 +01:00
Xiaohao112 ed480e1e6e Created a link to composition doctype
Related to this issue; http://issues.umbraco.org/issue/U4-10192. Made a link to a composition from the current doctype.
2017-07-24 14:12:59 +02:00
Bjarne Fyrstenborg be1172d604 Add icon for font select 2017-03-04 18:20:03 +01:00
Bjarne Fyrstenborg 7cf8cd3518 Fix font size caret 2017-03-04 18:19:44 +01:00
Stefano Chiodino 4cab1c89b4 U4-7721 Specify margin 0 for buttons
On Safari input elemnts have 1px margin which use to make customise and
install buttons not aligned
2016-11-03 16:05:38 +00:00
Chris Houston a4f83e0125 Style changes to the developer dashboard area. 2016-11-03 14:41:41 +00:00
Tom Pipe 7b08c0dde6 Adding isPublished value to the index 2016-11-03 11:48:49 +00:00
Stefano Chiodino 88fd5a9623 Remove background-color on preview that was interfering with the website
style
2016-11-03 11:40:20 +00:00
Lars-Erik Aabech 361ef2a475 Opening up GetHttpContextFactory for extending (actually in prev commit, but messed up) 2016-09-13 23:57:31 +02:00
Lars-Erik Aabech d382fcc919 Issue with isHosted in TypeFinder when unit testing. 2016-09-13 23:56:15 +02:00
Lars-Erik Aabech aac8451627 Removing HttpContext dependency from GridValueConverter. Adding configuration for IOHelper when testing to remove usage of HttpContext. 2016-09-11 21:36:10 +02:00
Jesper Hauge c96c09f42f Merge branch 'dev-v7' of https://github.com/umbraco/Umbraco-CMS into dev-v7 2016-06-20 21:55:25 +02:00
Jesper Hauge 50f8f18503 Fixes U4-8616 2016-06-20 21:53:40 +02:00
bjarnef 9001cd8a6f Sort data types array by name A-Z 2016-04-14 23:50:43 +02:00
Heather Floyd 1279fd234f Checking for possible Null Ref Exception in Textstring.cshtml grid renderer 2015-09-11 19:43:41 -04:00
144 changed files with 5704 additions and 4130 deletions
+37
View File
@@ -14,6 +14,43 @@ By default, this builds the current version. It is possible to specify a differe
Valid version strings are defined in the `Set-UmbracoVersion` documentation below.
## PowerShell Quirks
There is a good chance that running `build.ps1` ends up in error, with messages such as
>The file ...\build\build.ps1 is not digitally signed. You cannot run this script on the current system. For more information about running scripts and setting execution policy, see about_Execution_Policies.
PowerShell has *Execution Policies* that may prevent the script from running. You can check the current policies with:
PS> Get-ExecutionPolicy -List
Scope ExecutionPolicy
----- ---------------
MachinePolicy Undefined
UserPolicy Undefined
Process Undefined
CurrentUser Undefined
LocalMachine RemoteSigned
Policies can be `Restricted`, `AllSigned`, `RemoteSigned`, `Unrestricted` and `Bypass`. Scopes can be `MachinePolicy`, `UserPolicy`, `Process`, `CurrentUser`, `LocalMachine`. You need the current policy to be `RemoteSigned`&mdash;as long as it is `Undefined`, the script cannot run. You can change the current user policy with:
PS> Set-ExecutionPolicy -Scope CurrentUser -ExecutionPolicy RemoteSigned
Alternatively, you can do it at machine level, from within an elevated PowerShell session:
PS> Set-ExecutionPolicy -Scope LocalMachine -ExecutionPolicy RemoteSigned
And *then* the script should run. It *might* however still complain about executing scripts, with messages such as:
>Security warning - Run only scripts that you trust. While scripts from the internet can be useful, this script can potentially harm your computer. If you trust this script, use the Unblock-File cmdlet to allow the script to run without this warning message. Do you want to run ...\build\build.ps1?
[D] Do not run [R] Run once [S] Suspend [?] Help (default is "D"):
This is usually caused by the scripts being *blocked*. And that usually happens when the source code has been downloaded as a Zip file. When Windows downloads Zip files, they are marked as *blocked* (technically, they have a Zone.Identifier alternate data stream, with a value of "3" to indicate that they were downloaded from the Internet). And when such a Zip file is un-zipped, each and every single file is also marked as blocked.
The best solution is to unblock the Zip file before un-zipping: right-click the files, open *Properties*, and there should be a *Unblock* checkbox at the bottom of the dialog. If, however, the Zip file has already been un-zipped, it is possible to recursively unblock all files from PowerShell with:
PS> Get-ChildItem -Recurse *.* | Unblock-File
## Notes
Git might have issues dealing with long file paths during build. You may want/need to enable `core.longpaths` support (see [this page](https://github.com/msysgit/msysgit/wiki/Git-cannot-create-a-file-or-directory-with-a-long-path) for details).
+3 -3
View File
@@ -2,7 +2,7 @@
Umbraco CMS
===========
The friendliest, most flexible and fastest growing ASP.NET CMS used by more than 390,000 websites worldwide: [https://umbraco.com](https://umbraco.com)
The friendliest, most flexible and fastest growing ASP.NET CMS used by more than 443,000 websites worldwide: [https://umbraco.com](https://umbraco.com)
[![ScreenShot](vimeo.png)](https://vimeo.com/172382998/)
@@ -12,7 +12,7 @@ Umbraco is a free open source Content Management System built on the ASP.NET pla
## Building Umbraco from source ##
The easiest way to get started is to run `build/build.bat` which will build both the backoffice (also known as "Belle") and the Umbraco core. You can then easily start debugging from Visual Studio, or if you need to debug Belle you can run `gulp dev` in `src\Umbraco.Web.UI.Client`.
The easiest way to get started is to run `build.bat` which will build both the backoffice (also known as "Belle") and the Umbraco core. You can then easily start debugging from Visual Studio, or if you need to debug Belle you can run `gulp dev` in `src\Umbraco.Web.UI.Client`. See [this page](BUILD.md) for more details.
Note that you can always [download a nightly build](http://nightly.umbraco.org/?container=umbraco-750) so you don't have to build the code yourself.
@@ -26,7 +26,7 @@ For the first time on the Microsoft platform, there is a free user and developer
Umbraco is not only loved by developers, but is a content editors dream. Enjoy intuitive editing tools, media management, responsive views and approval workflows to send your content live.
Used by more than 350,000 active websites including Carlsberg, Segway, Amazon and Heinz and **The Official ASP.NET and IIS.NET website from Microsoft** ([https://asp.net](https://asp.net) / [https://iis.net](https://iis.net)), you can be sure that the technology is proven, stable and scales. Backed by the team at Umbraco HQ, and supported by a dedicated community of over 200,000 craftspeople globally, you can trust that Umbraco is a safe choice and is here to stay.
Used by more than 443,000 active websites including Carlsberg, Segway, Amazon and Heinz and **The Official ASP.NET and IIS.NET website from Microsoft** ([https://asp.net](https://asp.net) / [https://iis.net](https://iis.net)), you can be sure that the technology is proven, stable and scales. Backed by the team at Umbraco HQ, and supported by a dedicated community of over 220,000 craftspeople globally, you can trust that Umbraco is a safe choice and is here to stay.
To view more examples, please visit [https://umbraco.com/why-umbraco/#caseStudies](https://umbraco.com/why-umbraco/#caseStudies)
+1 -2
View File
@@ -10,6 +10,5 @@ IF ERRORLEVEL 1 (
:error
ECHO.
ECHO Can not run build\build.ps1.
ECHO If this is due to a SecurityError then make sure to run the following command from an administrator command prompt:
ECHO If this is due to a SecurityError then please refer to BUILD.md for help!
ECHO.
ECHO powershell Set-ExecutionPolicy -ExecutionPolicy RemoteSigned
@@ -40,6 +40,7 @@ function Get-UmbracoBuildEnv
&$nuget install 7-Zip.CommandLine -OutputDirectory $path -Verbosity quiet
$dir = ls "$path\7-Zip.CommandLine.*" | sort -property Name -descending | select -first 1
$file = ls -path "$dir" -name 7za.exe -recurse
$file = ls -path "$dir" -name 7za.exe -recurse | select -first 1 #A select is because there is tools\7za.exe & tools\x64\7za.exe
mv "$dir\$file" $sevenZip
Remove-Directory $dir
}
+4 -4
View File
@@ -33,13 +33,13 @@
<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)" />
<dependency id="Examine" version="[0.1.85, 1.0.0)" />
<dependency id="ImageProcessor" version="[2.5.3, 3.0.0)" />
<dependency id="ImageProcessor.Web" version="[4.8.3, 5.0.0)" />
<dependency id="Examine" version="[0.1.88, 1.0.0)" />
<dependency id="ImageProcessor" version="[2.5.6, 3.0.0)" />
<dependency id="ImageProcessor.Web" version="[4.8.7, 5.0.0)" />
<dependency id="semver" version="[1.1.2, 3.0.0)" />
<!-- Markdown can not be updated due to: https://github.com/hey-red/markdownsharp/issues/71#issuecomment-233585487 -->
<dependency id="Markdown" version="[1.14.7, 2.0.0)" />
<dependency id="System.Threading.Tasks.Dataflow" version="[4.7.0, 5.0.0)" />
<dependency id="System.Threading.Tasks.Dataflow" version="[4.7.0, 5.0.0)" />
</dependencies>
</metadata>
<files>
+1 -1
View File
@@ -19,7 +19,7 @@
<dependency id="Newtonsoft.Json" version="[10.0.2, 11.0.0)" />
<dependency id="Umbraco.ModelsBuilder" version="[3.0.7, 4.0.0)" />
<dependency id="Microsoft.AspNet.SignalR.Core" version="[2.2.1, 3.0.0)" />
<dependency id="ImageProcessor.Web.Config" version="[2.3.0, 3.0.0)" />
<dependency id="ImageProcessor.Web.Config" version="[2.3.1, 3.0.0)" />
</dependencies>
</metadata>
<files>
+2 -2
View File
@@ -11,5 +11,5 @@ using System.Resources;
[assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyFileVersion("7.7.2")]
[assembly: AssemblyInformationalVersion("7.7.2")]
[assembly: AssemblyFileVersion("7.7.7")]
[assembly: AssemblyInformationalVersion("7.7.7")]
@@ -538,24 +538,41 @@ namespace Umbraco.Core.Configuration
internal static bool ContentCacheXmlStoredInCodeGen
{
get { return ContentCacheXmlStorageLocation == ContentXmlStorage.AspNetTemp; }
get { return LocalTempStorageLocation == LocalTempStorage.AspNetTemp; }
}
internal static ContentXmlStorage ContentCacheXmlStorageLocation
/// <summary>
/// This is the location type to store temporary files such as cache files or other localized files for a given machine
/// </summary>
/// <remarks>
/// Currently used for the xml cache file and the plugin cache files
/// </remarks>
internal static LocalTempStorage LocalTempStorageLocation
{
get
{
{
//there's a bunch of backwards compat config checks here....
//This is the current one
if (ConfigurationManager.AppSettings.ContainsKey("umbracoLocalTempStorage"))
{
return Enum<LocalTempStorage>.Parse(ConfigurationManager.AppSettings["umbracoLocalTempStorage"]);
}
//This one is old
if (ConfigurationManager.AppSettings.ContainsKey("umbracoContentXMLStorage"))
{
return Enum<ContentXmlStorage>.Parse(ConfigurationManager.AppSettings["umbracoContentXMLStorage"]);
}
return Enum<LocalTempStorage>.Parse(ConfigurationManager.AppSettings["umbracoContentXMLStorage"]);
}
//This one is older
if (ConfigurationManager.AppSettings.ContainsKey("umbracoContentXMLUseLocalTemp"))
{
return bool.Parse(ConfigurationManager.AppSettings["umbracoContentXMLUseLocalTemp"])
? ContentXmlStorage.AspNetTemp
: ContentXmlStorage.Default;
? LocalTempStorage.AspNetTemp
: LocalTempStorage.Default;
}
return ContentXmlStorage.Default;
return LocalTempStorage.Default;
}
}
@@ -1,6 +1,6 @@
namespace Umbraco.Core.Configuration
{
internal enum ContentXmlStorage
internal enum LocalTempStorage
{
Default,
AspNetTemp,
@@ -6,7 +6,7 @@ namespace Umbraco.Core.Configuration
{
public class UmbracoVersion
{
private static readonly Version Version = new Version("7.7.2");
private static readonly Version Version = new Version("7.7.7");
/// <summary>
/// Gets the current version of Umbraco.
+24 -6
View File
@@ -13,11 +13,28 @@ using Umbraco.Core.Configuration;
namespace Umbraco.Core.IO
{
public static class IOHelper
{
{
/// <summary>
/// Gets or sets a value forcing Umbraco to consider it is non-hosted.
/// </summary>
/// <remarks>This should always be false, unless unit testing.</remarks>
public static bool ForceNotHosted { get; set; }
private static string _rootDir = "";
// static compiled regex for faster performance
private readonly static Regex ResolveUrlPattern = new Regex("(=[\"\']?)(\\W?\\~(?:.(?![\"\']?\\s+(?:\\S+)=|[>\"\']))+.)[\"\']?", RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace);
/// <summary>
/// Gets a value indicating whether Umbraco is hosted.
/// </summary>
public static bool IsHosted
{
get
{
return ForceNotHosted == false && (HttpContext.Current != null || HostingEnvironment.IsHosted);
}
}
public static char DirSepChar
{
@@ -72,14 +89,14 @@ namespace Umbraco.Core.IO
internal static string ResolveUrlsFromTextString(string text)
{
if (UmbracoConfig.For.UmbracoSettings().Content.ResolveUrlsFromTextString)
{
{
using (DisposableTimer.DebugDuration(typeof(IOHelper), "ResolveUrlsFromTextString starting", "ResolveUrlsFromTextString complete"))
{
// find all relative urls (ie. urls that contain ~)
var tags = ResolveUrlPattern.Matches(text);
foreach (Match tag in tags)
{
{
string url = "";
if (tag.Groups[1].Success)
url = tag.Groups[1].Value;
@@ -97,7 +114,8 @@ namespace Umbraco.Core.IO
public static string MapPath(string path, bool useHttpContext)
{
if (path == null) throw new ArgumentNullException("path");
if (path == null) throw new ArgumentNullException("path");
useHttpContext = useHttpContext && IsHosted;
// Check if the path is already mapped
if ((path.Length >= 2 && path[1] == Path.VolumeSeparatorChar)
@@ -303,7 +321,7 @@ namespace Umbraco.Core.IO
var debugFolder = Path.Combine(binFolder, "debug");
if (Directory.Exists(debugFolder))
return debugFolder;
#endif
#endif
var releaseFolder = Path.Combine(binFolder, "release");
if (Directory.Exists(releaseFolder))
return releaseFolder;
+8 -8
View File
@@ -73,19 +73,19 @@ namespace Umbraco.Core.IO
{
get
{
switch (GlobalSettings.ContentCacheXmlStorageLocation)
switch (GlobalSettings.LocalTempStorageLocation)
{
case ContentXmlStorage.AspNetTemp:
case LocalTempStorage.AspNetTemp:
return Path.Combine(HttpRuntime.CodegenDir, @"UmbracoData\umbraco.config");
case ContentXmlStorage.EnvironmentTemp:
case LocalTempStorage.EnvironmentTemp:
var appDomainHash = HttpRuntime.AppDomainAppId.ToSHA1();
var cachePath = Path.Combine(Environment.ExpandEnvironmentVariables("%temp%"), "UmbracoXml",
//include the appdomain hash is just a safety check, for example if a website is moved from worker A to worker B and then back
// to worker A again, in theory the %temp% folder should already be empty but we really want to make sure that its not
// utilizing an old path
var cachePath = Path.Combine(Environment.ExpandEnvironmentVariables("%temp%"), "UmbracoData",
//include the appdomain hash is just a safety check, for example if a website is moved from worker A to worker B and then back
// to worker A again, in theory the %temp% folder should already be empty but we really want to make sure that its not
// utilizing an old path
appDomainHash);
return Path.Combine(cachePath, "umbraco.config");
case ContentXmlStorage.Default:
case LocalTempStorage.Default:
return IOHelper.ReturnPath("umbracoContentXML", "~/App_Data/umbraco.config");
default:
throw new ArgumentOutOfRangeException();
@@ -0,0 +1,95 @@
using System;
using System.IO;
using log4net.Appender;
using log4net.Util;
namespace Umbraco.Core.Logging
{
/// <summary>
/// This class will do the exact same thing as the RollingFileAppender that comes from log4net
/// With the extension, that it is able to do automatic cleanup of the logfiles in the directory where logging happens
///
/// By specifying the properties MaxLogFileDays and BaseFilePattern, the files will automaticly get deleted when
/// the logger is configured(typically when the app starts). To utilize this appender swap out the type of the rollingFile appender
/// that ships with Umbraco, to be Umbraco.Core.Logging.RollingFileCleanupAppender, and add the maxLogFileDays and baseFilePattern elements
/// to the configuration i.e.:
///
/// <example>
/// <appender name="rollingFile" type="Log4netAwesomeness.CustomRollingFileAppender, Log4netAwesomeness">
/// <file type="log4net.Util.PatternString" value="App_Data\Logs\UmbracoTraceLog.%property{log4net:HostName}.txt" />
/// <lockingModel type="log4net.Appender.FileAppender+MinimalLock" />
/// <appendToFile value="true" />
/// <rollingStyle value="Date" />
/// <maximumFileSize value="5MB" />
/// <maxLogFileDays value="5"/>
/// <basefilePattern value="UmbracoTraceLog.*.txt.*"/>
/// <layout type="log4net.Layout.PatternLayout">
/// <conversionPattern value=" %date [P%property{processId}/D%property{appDomainId}/T%thread] %-5level %logger - %message%newline" />
/// </layout>
/// <layout type="log4net.Layout.PatternLayout">
/// <conversionPattern value=" %date [P%property{processId}/D%property{appDomainId}/T%thread] %-5level %logger - %message%newline" />
/// </layout>
/// <encoding value="utf-8" />
/// </appender>
/// </example>
/// </summary>
public class RollingFileCleanupAppender : RollingFileAppender
{
public int MaxLogFileDays { get; set; }
public string BaseFilePattern { get; set; }
/// <summary>
/// This override will delete logs older than the specified amount of days
/// </summary>
/// <param name="fileName"></param>
/// <param name="append"></param>
protected override void OpenFile(string fileName, bool append)
{
bool cleanup = true;
// Validate settings and input
if (MaxLogFileDays <= 0)
{
LogLog.Warn(typeof(RollingFileCleanupAppender), "Parameter 'MaxLogFileDays' needs to be a positive integer, aborting cleanup");
cleanup = false;
}
if (string.IsNullOrWhiteSpace(BaseFilePattern))
{
LogLog.Warn(typeof(RollingFileCleanupAppender), "Parameter 'BaseFilePattern' is empty, aborting cleanup");
cleanup = false;
}
// grab the directory we are logging to, as this is were we will search for older logfiles
var logFolder = Path.GetDirectoryName(fileName);
if (Directory.Exists(logFolder) == false)
{
LogLog.Warn(typeof(RollingFileCleanupAppender), string.Format("Directory '{0}' for logfiles does not exist, aborting cleanup", logFolder));
cleanup = false;
}
// If everything is validated, we can do the actual cleanup
if (cleanup)
{
Cleanup(logFolder);
}
base.OpenFile(fileName, append);
}
private void Cleanup(string directoryPath)
{
// only take files that matches the pattern we are using i.e. UmbracoTraceLog.*.txt.*
string[] logFiles = Directory.GetFiles(directoryPath, BaseFilePattern);
LogLog.Debug(typeof(RollingFileCleanupAppender), string.Format("Found {0} files that matches the baseFilePattern: '{1}'", logFiles.Length, BaseFilePattern));
foreach (var logFile in logFiles)
{
DateTime lastAccessTime = System.IO.File.GetLastWriteTimeUtc(logFile);
// take the value from the config file
if (lastAccessTime < DateTime.Now.AddDays(-MaxLogFileDays))
{
LogLog.Debug(typeof(RollingFileCleanupAppender), string.Format("Deleting file {0} as its lastAccessTime is older than {1} days speficied by MaxLogFileDays", logFile, MaxLogFileDays));
base.DeleteFile(logFile);
}
}
}
}
}
@@ -12,7 +12,7 @@ namespace Umbraco.Core.Models.Membership
/// </summary>
[Serializable]
[DataContract(IsReference = true)]
internal class UserGroup : Entity, IUserGroup, IReadOnlyUserGroup
public class UserGroup : Entity, IUserGroup, IReadOnlyUserGroup
{
private int? _startContentId;
private int? _startMediaId;
@@ -188,7 +188,7 @@ namespace Umbraco.Core.Models
Language,
/// <summary>
/// Document
/// Document Blueprint
/// </summary>
[UmbracoObjectType(Constants.ObjectTypes.DocumentBlueprint, typeof(IContent))]
[FriendlyName("DocumentBlueprint")]
@@ -134,7 +134,9 @@ namespace Umbraco.Core.Persistence.Repositories
.InnerJoin<ContentDto>(SqlSyntax)
.On<ContentVersionDto, ContentDto>(SqlSyntax, left => left.NodeId, right => right.NodeId)
.InnerJoin<NodeDto>(SqlSyntax)
.On<ContentDto, NodeDto>(SqlSyntax, left => left.NodeId, right => right.NodeId);
.On<ContentDto, NodeDto>(SqlSyntax, left => left.NodeId, right => right.NodeId)
.InnerJoin<ContentTypeDto>()
.On<ContentTypeDto, ContentDto>(left => left.NodeId, right => right.ContentTypeId);
//TODO: IF we want to enable querying on content type information this will need to be joined
//.InnerJoin<ContentTypeDto>(SqlSyntax)
//.On<ContentDto, ContentTypeDto>(SqlSyntax, left => left.ContentTypeId, right => right.NodeId, SqlSyntax);
@@ -833,11 +835,21 @@ order by umbracoNode.{2}, umbracoNode.parentID, umbracoNode.sortOrder",
}
public int CountPublished()
{
var sql = GetBaseQuery(true).Where<NodeDto>(x => x.Trashed == false)
.Where<DocumentDto>(x => x.Published == true);
return Database.ExecuteScalar<int>(sql);
public int CountPublished(string contentTypeAlias = null)
{
if (contentTypeAlias.IsNullOrWhiteSpace())
{
var sql = GetBaseQuery(true).Where<NodeDto>(x => x.Trashed == false)
.Where<DocumentDto>(x => x.Published == true);
return Database.ExecuteScalar<int>(sql);
}
else
{
var sql = GetBaseQuery(true).Where<NodeDto>(x => x.Trashed == false)
.Where<DocumentDto>(x => x.Published == true)
.Where<ContentTypeDto>(x => x.Alias == contentTypeAlias);
return Database.ExecuteScalar<int>(sql);
}
}
public void ReplaceContentPermissions(EntityPermissionSet permissionSet)
@@ -26,7 +26,7 @@ namespace Umbraco.Core.Persistence.Repositories
/// <remarks>
/// We require this on the repo because the IQuery{IContent} cannot supply the 'newest' parameter
/// </remarks>
int CountPublished();
int CountPublished(string contentTypeAlias = null);
/// <summary>
/// Used to bulk update the permissions set for a content item. This will replace all permissions
@@ -191,11 +191,11 @@ ORDER BY colName";
return new Dictionary<UserState, int>
{
{UserState.All, result[0].num},
{UserState.Active, result[1].num},
{UserState.Disabled, result[2].num},
{UserState.LockedOut, result[3].num},
{UserState.Invited, result[4].num}
{UserState.All, (int)result[0].num},
{UserState.Active, (int)result[1].num},
{UserState.Disabled, (int)result[2].num},
{UserState.LockedOut, (int)result[3].num},
{UserState.Invited, (int)result[4].num}
};
}
+116 -75
View File
@@ -6,6 +6,7 @@ using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading;
using System.Web;
using System.Web.Compilation;
using Umbraco.Core.Cache;
using Umbraco.Core.IO;
@@ -15,6 +16,7 @@ using Umbraco.Core.Persistence.SqlSyntax;
using Umbraco.Core.Profiling;
using Umbraco.Core.PropertyEditors;
using umbraco.interfaces;
using Umbraco.Core.Configuration;
using File = System.IO.File;
namespace Umbraco.Core
@@ -39,7 +41,8 @@ namespace Umbraco.Core
private readonly IServiceProvider _serviceProvider;
private readonly IRuntimeCacheProvider _runtimeCache;
private readonly ProfilingLogger _logger;
private readonly string _tempFolder;
private readonly Lazy<string> _pluginListFilePath = new Lazy<string>(GetPluginListFilePath);
private readonly Lazy<string> _pluginHashFilePath = new Lazy<string>(GetPluginHashFilePath);
private readonly object _typesLock = new object();
private readonly Dictionary<TypeListKey, TypeList> _types = new Dictionary<TypeListKey, TypeList>();
@@ -65,14 +68,7 @@ namespace Umbraco.Core
_serviceProvider = serviceProvider;
_runtimeCache = runtimeCache;
_logger = logger;
// the temp folder where the cache file lives
_tempFolder = IOHelper.MapPath("~/App_Data/TEMP/PluginCache");
if (Directory.Exists(_tempFolder) == false)
Directory.CreateDirectory(_tempFolder);
var pluginListFile = GetPluginListFilePath();
if (detectChanges)
{
//first check if the cached hash is string.Empty, if it is then we need
@@ -84,7 +80,8 @@ namespace Umbraco.Core
// if the hash has changed, clear out the persisted list no matter what, this will force
// rescanning of all plugin types including lazy ones.
// http://issues.umbraco.org/issue/U4-4789
File.Delete(pluginListFile);
if(File.Exists(_pluginListFilePath.Value))
File.Delete(_pluginListFilePath.Value);
WriteCachePluginsHash();
}
@@ -94,7 +91,8 @@ namespace Umbraco.Core
// if the hash has changed, clear out the persisted list no matter what, this will force
// rescanning of all plugin types including lazy ones.
// http://issues.umbraco.org/issue/U4-4789
File.Delete(pluginListFile);
if (File.Exists(_pluginListFilePath.Value))
File.Delete(_pluginListFilePath.Value);
// always set to true if we're not detecting (generally only for testing)
RequiresRescanning = true;
@@ -187,11 +185,10 @@ namespace Umbraco.Core
{
if (_cachedAssembliesHash != null)
return _cachedAssembliesHash;
if (File.Exists(_pluginHashFilePath.Value) == false) return string.Empty;
var filePath = GetPluginHashFilePath();
if (File.Exists(filePath) == false) return string.Empty;
var hash = File.ReadAllText(filePath, Encoding.UTF8);
var hash = File.ReadAllText(_pluginHashFilePath.Value, Encoding.UTF8);
_cachedAssembliesHash = hash;
return _cachedAssembliesHash;
@@ -210,7 +207,7 @@ namespace Umbraco.Core
return _currentAssembliesHash;
_currentAssembliesHash = GetFileHash(new List<Tuple<FileSystemInfo, bool>>
{
{
// the bin folder and everything in it
new Tuple<FileSystemInfo, bool>(new DirectoryInfo(IOHelper.MapPath(SystemDirectories.Bin)), false),
// the app code folder and everything in it
@@ -219,7 +216,7 @@ namespace Umbraco.Core
new Tuple<FileSystemInfo, bool>(new FileInfo(IOHelper.MapPath("~/global.asax")), false),
// trees.config - use the contents to create the hash since this gets resaved on every app startup!
new Tuple<FileSystemInfo, bool>(new FileInfo(IOHelper.MapPath(SystemDirectories.Config + "/trees.config")), true)
}, _logger);
}, _logger);
return _currentAssembliesHash;
}
@@ -229,9 +226,8 @@ namespace Umbraco.Core
/// Writes the assembly hash file.
/// </summary>
private void WriteCachePluginsHash()
{
var filePath = GetPluginHashFilePath();
File.WriteAllText(filePath, CurrentAssembliesHash.ToString(), Encoding.UTF8);
{
File.WriteAllText(_pluginHashFilePath.Value, CurrentAssembliesHash, Encoding.UTF8);
}
/// <summary>
@@ -274,7 +270,7 @@ namespace Umbraco.Core
}
}
}
return generator.GenerateHash();
return generator.GenerateHash();
}
}
}
@@ -314,7 +310,7 @@ namespace Umbraco.Core
uniqInfos.Add(fileOrFolder.FullName);
generator.AddFileSystemItem(fileOrFolder);
}
return generator.GenerateHash();
return generator.GenerateHash();
}
}
}
@@ -347,12 +343,11 @@ namespace Umbraco.Core
{
return ReadCache();
}
catch
catch (Exception ex)
{
try
{
var filePath = GetPluginListFilePath();
File.Delete(filePath);
File.Delete(_pluginListFilePath.Value);
}
catch
{
@@ -366,12 +361,11 @@ namespace Umbraco.Core
internal Dictionary<Tuple<string, string>, IEnumerable<string>> ReadCache()
{
var cache = new Dictionary<Tuple<string, string>, IEnumerable<string>>();
var filePath = GetPluginListFilePath();
if (File.Exists(filePath) == false)
if (File.Exists(_pluginListFilePath.Value) == false)
return cache;
using (var stream = GetFileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read, ListFileOpenReadTimeout))
using (var stream = GetFileStream(_pluginListFilePath.Value, FileMode.Open, FileAccess.Read, FileShare.Read, ListFileOpenReadTimeout))
using (var reader = new StreamReader(stream))
{
while (true)
@@ -414,38 +408,86 @@ namespace Umbraco.Core
/// <remarks>Generally only used for resetting cache, for example during the install process.</remarks>
public void ClearPluginCache()
{
var path = GetPluginListFilePath();
if (File.Exists(path))
File.Delete(path);
path = GetPluginHashFilePath();
if (File.Exists(path))
File.Delete(path);
if (File.Exists(_pluginListFilePath.Value))
File.Delete(_pluginListFilePath.Value);
if (File.Exists(_pluginHashFilePath.Value))
File.Delete(_pluginHashFilePath.Value);
_runtimeCache.ClearCacheItem(CacheKey);
}
private string GetPluginListFilePath()
private static string GetPluginListFilePath()
{
var filename = "umbraco-plugins." + NetworkHelper.FileSafeMachineName + ".list";
return Path.Combine(_tempFolder, filename);
string pluginListFilePath;
switch (GlobalSettings.LocalTempStorageLocation)
{
case LocalTempStorage.AspNetTemp:
pluginListFilePath = Path.Combine(HttpRuntime.CodegenDir, @"UmbracoData\umbraco-plugins.list");
break;
case LocalTempStorage.EnvironmentTemp:
var appDomainHash = HttpRuntime.AppDomainAppId.ToSHA1();
var cachePath = Path.Combine(Environment.ExpandEnvironmentVariables("%temp%"), "UmbracoData",
//include the appdomain hash is just a safety check, for example if a website is moved from worker A to worker B and then back
// to worker A again, in theory the %temp% folder should already be empty but we really want to make sure that its not
// utilizing an old path
appDomainHash);
pluginListFilePath = Path.Combine(cachePath, "umbraco-plugins.list");
break;
case LocalTempStorage.Default:
default:
var tempFolder = IOHelper.MapPath("~/App_Data/TEMP/PluginCache");
pluginListFilePath = Path.Combine(tempFolder, "umbraco-plugins." + NetworkHelper.FileSafeMachineName + ".list");
break;
}
//ensure the folder exists
var folder = Path.GetDirectoryName(pluginListFilePath);
if (folder == null)
throw new InvalidOperationException("The folder could not be determined for the file " + pluginListFilePath);
if (Directory.Exists(folder) == false)
Directory.CreateDirectory(folder);
return pluginListFilePath;
}
private string GetPluginHashFilePath()
private static string GetPluginHashFilePath()
{
var filename = "umbraco-plugins." + NetworkHelper.FileSafeMachineName + ".hash";
return Path.Combine(_tempFolder, filename);
string pluginHashFilePath;
switch (GlobalSettings.LocalTempStorageLocation)
{
case LocalTempStorage.AspNetTemp:
pluginHashFilePath = Path.Combine(HttpRuntime.CodegenDir, @"UmbracoData\umbraco-plugins.hash");
break;
case LocalTempStorage.EnvironmentTemp:
var appDomainHash = HttpRuntime.AppDomainAppId.ToSHA1();
var cachePath = Path.Combine(Environment.ExpandEnvironmentVariables("%temp%"), "UmbracoData",
//include the appdomain hash is just a safety check, for example if a website is moved from worker A to worker B and then back
// to worker A again, in theory the %temp% folder should already be empty but we really want to make sure that its not
// utilizing an old path
appDomainHash);
pluginHashFilePath = Path.Combine(cachePath, "umbraco-plugins.hash");
break;
case LocalTempStorage.Default:
default:
var tempFolder = IOHelper.MapPath("~/App_Data/TEMP/PluginCache");
pluginHashFilePath = Path.Combine(tempFolder, "umbraco-plugins." + NetworkHelper.FileSafeMachineName + ".hash");
break;
}
//ensure the folder exists
var folder = Path.GetDirectoryName(pluginHashFilePath);
if (folder == null)
throw new InvalidOperationException("The folder could not be determined for the file " + pluginHashFilePath);
if (Directory.Exists(folder) == false)
Directory.CreateDirectory(folder);
return pluginHashFilePath;
}
internal void WriteCache()
{
// be absolutely sure
if (Directory.Exists(_tempFolder) == false)
Directory.CreateDirectory(_tempFolder);
var filePath = GetPluginListFilePath();
using (var stream = GetFileStream(filePath, FileMode.Create, FileAccess.Write, FileShare.None, ListFileOpenWriteTimeout))
using (var stream = GetFileStream(_pluginListFilePath.Value, FileMode.Create, FileAccess.Write, FileShare.None, ListFileOpenWriteTimeout))
using (var writer = new StreamWriter(stream))
{
foreach (var typeList in _types.Values)
@@ -461,8 +503,7 @@ namespace Umbraco.Core
internal void UpdateCache()
{
// note
// at the moment we write the cache to disk every time we update it. ideally we defer the writing
// TODO: at the moment we write the cache to disk every time we update it. ideally we defer the writing
// since all the updates are going to happen in a row when Umbraco starts. that being said, the
// file is small enough, so it is not a priority.
WriteCache();
@@ -475,13 +516,13 @@ namespace Umbraco.Core
while (true)
{
try
{
{
return new FileStream(path, fileMode, fileAccess, fileShare);
}
catch
catch (Exception ex)
{
if (--attempts == 0)
throw;
throw;
LogHelper.Debug<PluginManager>(string.Format("Attempted to get filestream for file {0} failed, {1} attempts left, pausing for {2} milliseconds", path, attempts, pauseMilliseconds));
Thread.Sleep(pauseMilliseconds);
@@ -560,7 +601,7 @@ namespace Umbraco.Core
if (cache == false || typeof(IDiscoverable).IsAssignableFrom(typeof(T)) == false)
{
return ResolveTypesInternal(
typeof (T), null,
typeof(T), null,
() => TypeFinder.FindClassesOfType<T>(specificAssemblies ?? AssembliesToScan),
cache);
}
@@ -569,14 +610,14 @@ namespace Umbraco.Core
// filter the cached discovered types (and cache the result)
var discovered = ResolveTypesInternal(
typeof (IDiscoverable), null,
typeof(IDiscoverable), null,
() => TypeFinder.FindClassesOfType<IDiscoverable>(AssembliesToScan),
true);
return ResolveTypesInternal(
typeof (T), null,
typeof(T), null,
() => discovered
.Where(x => typeof (T).IsAssignableFrom(x)),
.Where(x => typeof(T).IsAssignableFrom(x)),
true);
}
@@ -599,7 +640,7 @@ namespace Umbraco.Core
if (cache == false || typeof(IDiscoverable).IsAssignableFrom(typeof(T)) == false)
{
return ResolveTypesInternal(
typeof (T), typeof (TAttribute),
typeof(T), typeof(TAttribute),
() => TypeFinder.FindClassesOfTypeWithAttribute<T, TAttribute>(specificAssemblies ?? AssembliesToScan),
cache);
}
@@ -608,12 +649,12 @@ namespace Umbraco.Core
// filter the cached discovered types (and cache the result)
var discovered = ResolveTypesInternal(
typeof (IDiscoverable), null,
typeof(IDiscoverable), null,
() => TypeFinder.FindClassesOfType<IDiscoverable>(AssembliesToScan),
true);
return ResolveTypesInternal(
typeof (T), typeof (TAttribute),
typeof(T), typeof(TAttribute),
() => discovered
.Where(x => typeof(T).IsAssignableFrom(x))
.Where(x => x.GetCustomAttributes<TAttribute>(false).Any()),
@@ -635,7 +676,7 @@ namespace Umbraco.Core
cache &= specificAssemblies == null;
return ResolveTypesInternal(
typeof (object), typeof (TAttribute),
typeof(object), typeof(TAttribute),
() => TypeFinder.FindClassesWithAttribute<TAttribute>(specificAssemblies ?? AssembliesToScan),
cache);
}
@@ -653,13 +694,13 @@ namespace Umbraco.Core
var name = ResolvedName(baseType, attributeType);
lock (_typesLock)
using (_logger.TraceDuration<PluginManager>(
"Resolving " + name,
"Resolved " + name)) // cannot contain typesFound.Count as it's evaluated before the find
{
// resolve within a lock & timer
return ResolveTypesInternalLocked(baseType, attributeType, finder, cache);
}
using (_logger.TraceDuration<PluginManager>(
"Resolving " + name,
"Resolved " + name)) // cannot contain typesFound.Count as it's evaluated before the find
{
// resolve within a lock & timer
return ResolveTypesInternalLocked(baseType, attributeType, finder, cache);
}
}
private static string ResolvedName(Type baseType, Type attributeType)
@@ -691,7 +732,7 @@ namespace Umbraco.Core
// else proceed,
typeList = new TypeList(baseType, attributeType);
var scan = RequiresRescanning || File.Exists(GetPluginListFilePath()) == false;
var scan = RequiresRescanning || File.Exists(_pluginListFilePath.Value) == false;
if (scan)
{
@@ -795,7 +836,7 @@ namespace Umbraco.Core
public TypeListKey(Type baseType, Type attributeType)
{
BaseType = baseType ?? typeof (object);
BaseType = baseType ?? typeof(object);
AttributeType = attributeType;
}
@@ -813,7 +854,7 @@ namespace Umbraco.Core
var hash = 5381;
hash = ((hash << 5) + hash) ^ BaseType.GetHashCode();
hash = ((hash << 5) + hash) ^ (AttributeType ?? typeof (TypeListKey)).GetHashCode();
hash = ((hash << 5) + hash) ^ (AttributeType ?? typeof(TypeListKey)).GetHashCode();
return hash;
}
}
@@ -876,7 +917,7 @@ namespace Umbraco.Core
{
// look for IParameterEditor (fast, IDiscoverable) then filter
var propertyEditor = typeof (PropertyEditor);
var propertyEditor = typeof(PropertyEditor);
return mgr.ResolveTypes<IParameterEditor>()
.Where(x => propertyEditor.IsAssignableFrom(x) && x != propertyEditor);
@@ -891,8 +932,8 @@ namespace Umbraco.Core
/// </remarks>
public static IEnumerable<Type> ResolveParameterEditors(this PluginManager mgr)
{
var propertyEditor = typeof (PropertyEditor);
var parameterEditor = typeof (ParameterEditor);
var propertyEditor = typeof(PropertyEditor);
var parameterEditor = typeof(ParameterEditor);
return mgr.ResolveTypes<IParameterEditor>()
.Where(x => x != propertyEditor && x != parameterEditor);
@@ -178,29 +178,25 @@ namespace Umbraco.Core.PropertyEditors
return result;
}
private void ConvertItemsToJsonIfDetected(IDictionary<string, object> result)
protected void ConvertItemsToJsonIfDetected(IDictionary<string, object> result)
{
//now we're going to try to see if any of the values are JSON, if they are we'll convert them to real JSON objects
// so they can be consumed as real json in angular!
// convert values that are Json to true Json objects that can be consumed by Angular
var keys = result.Keys.ToArray();
for (var i = 0; i < keys.Length; i++)
{
if (result[keys[i]] is string)
if ((result[keys[i]] is string) == false) continue;
var asString = result[keys[i]].ToString();
if (asString.DetectIsJson() == false) continue;
try
{
var asString = result[keys[i]].ToString();
if (asString.DetectIsJson())
{
try
{
var json = JsonConvert.DeserializeObject(asString);
result[keys[i]] = json;
}
catch
{
//swallow this exception, we thought it was json but it really isn't so continue returning a string
}
}
result[keys[i]] = JsonConvert.DeserializeObject(asString);
}
catch
{
// swallow this exception, we thought it was Json but it really isn't so continue returning a string
}
}
}
@@ -1,13 +1,14 @@
using System;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Umbraco.Core.Configuration;
using Umbraco.Core.Models;
using Umbraco.Core.Models.PublishedContent;
namespace Umbraco.Core.PropertyEditors.ValueConverters
{
[DefaultPropertyValueConverter]
[PropertyValueType(typeof(string))]
[PropertyValueCache(PropertyCacheValue.All, PropertyCacheLevel.Content)]
public class ColorPickerValueConverter : PropertyValueConverterBase
public class ColorPickerValueConverter : PropertyValueConverterBase, IPropertyValueConverterMeta
{
public override bool IsConverter(PublishedPropertyType propertyType)
{
@@ -18,11 +19,60 @@ namespace Umbraco.Core.PropertyEditors.ValueConverters
return false;
}
public Type GetPropertyValueType(PublishedPropertyType propertyType)
{
return UseLabel(propertyType) ? typeof(PickedColor) : typeof(string);
}
public PropertyCacheLevel GetPropertyCacheLevel(PublishedPropertyType propertyType, PropertyCacheValue cacheValue)
{
return PropertyCacheLevel.Content;
}
private bool UseLabel(PublishedPropertyType propertyType)
{
var preValues = ApplicationContext.Current.Services.DataTypeService.GetPreValuesCollectionByDataTypeId(propertyType.DataTypeId);
PreValue preValue;
return preValues.PreValuesAsDictionary.TryGetValue("useLabel", out preValue) && preValue.Value == "1";
}
public override object ConvertDataToSource(PublishedPropertyType propertyType, object source, bool preview)
{
// make sure it's a string
return source == null ? string.Empty : source.ToString();
var useLabel = UseLabel(propertyType);
if (source == null) return useLabel ? null : string.Empty;
var ssource = source.ToString();
if (ssource.DetectIsJson())
{
try
{
var jo = JsonConvert.DeserializeObject<JObject>(ssource);
if (useLabel) return new PickedColor(jo["value"].ToString(), jo["label"].ToString());
return jo["value"].ToString();
}
catch { /* not json finally */ }
}
if (useLabel) return new PickedColor(ssource, ssource);
return ssource;
}
public class PickedColor
{
public PickedColor(string color, string label)
{
Color = color;
Label = label;
}
public string Color { get; private set; }
public string Label { get; private set; }
public override string ToString()
{
return Color;
}
}
}
}
@@ -43,8 +43,8 @@ namespace Umbraco.Core.PropertyEditors.ValueConverters
var gridConfig = UmbracoConfig.For.GridConfig(
ApplicationContext.Current.ProfilingLogger.Logger,
ApplicationContext.Current.ApplicationCache.RuntimeCache,
new DirectoryInfo(HttpContext.Current.Server.MapPath(SystemDirectories.AppPlugins)),
new DirectoryInfo(HttpContext.Current.Server.MapPath(SystemDirectories.Config)),
new DirectoryInfo(IOHelper.MapPath(SystemDirectories.AppPlugins)),
new DirectoryInfo(IOHelper.MapPath(SystemDirectories.Config)),
HttpContext.Current.IsDebuggingEnabled);
var sections = GetArray(obj, "sections");
@@ -12,6 +12,7 @@ using Umbraco.Core.Models.Identity;
namespace Umbraco.Core.Security
{
//TODO: In v8 we need to change this to use an int? nullable TKey instead, see notes against overridden TwoFactorSignInAsync
public class BackOfficeSignInManager : SignInManager<BackOfficeIdentityUser, int>
{
private readonly ILogger _logger;
@@ -259,5 +260,67 @@ namespace Umbraco.Core.Security
}
return null;
}
/// <summary>
/// Two factor verification step
/// </summary>
/// <param name="provider"></param>
/// <param name="code"></param>
/// <param name="isPersistent"></param>
/// <param name="rememberBrowser"></param>
/// <returns></returns>
/// <remarks>
/// This is implemented because we cannot override GetVerifiedUserIdAsync and instead we have to shadow it
/// so due to this and because we are using an INT as the TKey and not an object, it can never be null. Adding to that
/// the default(int) value returned by the base class is always a valid user (i.e. the admin) so we just have to duplicate
/// all of this code to check for -1 instead.
/// </remarks>
public override async Task<SignInStatus> TwoFactorSignInAsync(string provider, string code, bool isPersistent, bool rememberBrowser)
{
var userId = await GetVerifiedUserIdAsync();
if (userId == -1)
{
return SignInStatus.Failure;
}
var user = await UserManager.FindByIdAsync(userId);
if (user == null)
{
return SignInStatus.Failure;
}
if (await UserManager.IsLockedOutAsync(user.Id))
{
return SignInStatus.LockedOut;
}
if (await UserManager.VerifyTwoFactorTokenAsync(user.Id, provider, code))
{
// When token is verified correctly, clear the access failed count used for lockout
await UserManager.ResetAccessFailedCountAsync(user.Id);
await SignInAsync(user, isPersistent, rememberBrowser);
return SignInStatus.Success;
}
// If the token is incorrect, record the failure which also may cause the user to be locked out
await UserManager.AccessFailedAsync(user.Id);
return SignInStatus.Failure;
}
/// <summary>Send a two factor code to a user</summary>
/// <param name="provider"></param>
/// <returns></returns>
/// <remarks>
/// This is implemented because we cannot override GetVerifiedUserIdAsync and instead we have to shadow it
/// so due to this and because we are using an INT as the TKey and not an object, it can never be null. Adding to that
/// the default(int) value returned by the base class is always a valid user (i.e. the admin) so we just have to duplicate
/// all of this code to check for -1 instead.
/// </remarks>
public override async Task<bool> SendTwoFactorCodeAsync(string provider)
{
var userId = await GetVerifiedUserIdAsync();
if (userId == -1)
return false;
var token = await UserManager.GenerateTwoFactorTokenAsync(userId, provider);
var identityResult = await UserManager.NotifyTwoFactorTokenAsync(userId, provider, token);
return identityResult.Succeeded;
}
}
}
+91 -1
View File
@@ -62,7 +62,7 @@ namespace Umbraco.Core.Services
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repository = RepositoryFactory.CreateContentRepository(uow);
return repository.CountPublished();
return repository.CountPublished(contentTypeAlias);
}
}
@@ -2006,6 +2006,96 @@ namespace Umbraco.Core.Services
}
}
return true;
}
/// <summary>
/// Sorts a collection of <see cref="IContent"/> objects by updating the SortOrder according
/// to the ordering of node Ids passed in.
/// </summary>
/// <remarks>
/// Using this method will ensure that the Published-state is maintained upon sorting
/// so the cache is updated accordingly - as needed.
/// </remarks>
/// <param name="ids"></param>
/// <param name="userId"></param>
/// <param name="raiseEvents"></param>
/// <returns>True if sorting succeeded, otherwise False</returns>
public bool Sort(int[] ids, int userId = 0, bool raiseEvents = true)
{
var shouldBePublished = new List<IContent>();
var shouldBeSaved = new List<IContent>();
using (new WriteLock(Locker))
{
var allContent = GetByIds(ids).ToDictionary(x => x.Id, x => x);
var items = ids.Select(x => allContent[x]);
using (var uow = UowProvider.GetUnitOfWork())
{
var asArray = items.ToArray();
var saveEventArgs = new SaveEventArgs<IContent>(asArray);
if (raiseEvents && uow.Events.DispatchCancelable(Saving, this, saveEventArgs, "Saving"))
{
uow.Commit();
return false;
}
var repository = RepositoryFactory.CreateContentRepository(uow);
var i = 0;
foreach (var content in asArray)
{
//If the current sort order equals that of the content
//we don't need to update it, so just increment the sort order
//and continue.
if (content.SortOrder == i)
{
i++;
continue;
}
content.SortOrder = i;
content.WriterId = userId;
i++;
if (content.Published)
{
//TODO: This should not be an inner operation, but if we do this, it cannot raise events and cannot be cancellable!
var published = _publishingStrategy.Publish(uow, content, userId).Success;
shouldBePublished.Add(content);
}
else
shouldBeSaved.Add(content);
repository.AddOrUpdate(content);
//add or update a preview
repository.AddOrUpdatePreviewXml(content, c => _entitySerializer.Serialize(this, _dataTypeService, _userService, c));
}
foreach (var content in shouldBePublished)
{
//Create and Save ContentXml DTO
repository.AddOrUpdateContentXml(content, c => _entitySerializer.Serialize(this, _dataTypeService, _userService, c));
}
if (raiseEvents)
{
saveEventArgs.CanCancel = false;
uow.Events.Dispatch(Saved, this, saveEventArgs, "Saved");
}
if (shouldBePublished.Any())
{
//TODO: This should not be an inner operation, but if we do this, it cannot raise events and cannot be cancellable!
_publishingStrategy.PublishingFinalized(uow, shouldBePublished, false);
}
Audit(uow, AuditType.Sort, "Sorting content performed by user", userId, 0);
uow.Commit();
}
}
return true;
}
@@ -42,6 +42,7 @@ namespace Umbraco.Core.Services
xml.Add(new XAttribute("writerID", content.WriterId));
xml.Add(new XAttribute("template", content.Template == null ? "0" : content.Template.Id.ToString(CultureInfo.InvariantCulture)));
xml.Add(new XAttribute("nodeTypeAlias", content.ContentType.Alias));
xml.Add(new XAttribute("isPublished", content.Published));
if (deep)
{
+15 -1
View File
@@ -642,7 +642,21 @@ namespace Umbraco.Core.Services
/// <param name="userId"></param>
/// <param name="raiseEvents"></param>
/// <returns>True if sorting succeeded, otherwise False</returns>
bool Sort(IEnumerable<IContent> items, int userId = 0, bool raiseEvents = true);
bool Sort(IEnumerable<IContent> items, int userId = 0, bool raiseEvents = true);
/// <summary>
/// Sorts a collection of <see cref="IContent"/> objects by updating the SortOrder according
/// to the ordering of node Ids passed in.
/// </summary>
/// <remarks>
/// Using this method will ensure that the Published-state is maintained upon sorting
/// so the cache is updated accordingly - as needed.
/// </remarks>
/// <param name="ids"></param>
/// <param name="userId"></param>
/// <param name="raiseEvents"></param>
/// <returns>True if sorting succeeded, otherwise False</returns>
bool Sort(int[] ids, int userId = 0, bool raiseEvents = true);
/// <summary>
/// Gets the parent of the current content as an <see cref="IContent"/> item.
+2 -2
View File
@@ -106,8 +106,8 @@ namespace Umbraco.Core.Services
try
{
_locker.EnterWriteLock();
_id2Key[id] = new TypedId<Guid>(val.Value, umbracoObjectType); ;
_key2Id[val.Value] = new TypedId<int>();
_id2Key[id] = new TypedId<Guid>(val.Value, umbracoObjectType);
_key2Id[val.Value] = new TypedId<int>(id, umbracoObjectType);
}
finally
{
+5 -1
View File
@@ -986,7 +986,11 @@ namespace Umbraco.Core.Services
/// <param name="raiseEvents">Optional parameter to raise events.
/// Default is <c>True</c> otherwise set to <c>False</c> to not raise events</param>
public void Save(IMember entity, bool raiseEvents = true)
{
{
//trimming username and email to make sure we have no trailing space
entity.Username = entity.Username.Trim();
entity.Email = entity.Email.Trim();
using (var uow = UowProvider.GetUnitOfWork())
{
var saveEventArgs = new SaveEventArgs<IMember>(entity);
@@ -14,6 +14,7 @@ using Umbraco.Core.Logging;
using Umbraco.Core.Models.Rdbms;
using Umbraco.Core.Persistence;
using umbraco.interfaces;
using Umbraco.Core.Configuration;
using Umbraco.Core.Persistence.SqlSyntax;
namespace Umbraco.Core.Sync
@@ -39,6 +40,7 @@ namespace Umbraco.Core.Sync
private bool _syncing;
private bool _released;
private readonly ProfilingLogger _profilingLogger;
private readonly Lazy<string> _distCacheFilePath = new Lazy<string>(GetDistCacheFilePath);
protected DatabaseServerMessengerOptions Options { get; private set; }
protected ApplicationContext ApplicationContext { get { return _appContext; } }
@@ -460,10 +462,9 @@ namespace Umbraco.Core.Sync
/// </remarks>
private void ReadLastSynced()
{
var path = SyncFilePath;
if (File.Exists(path) == false) return;
if (File.Exists(_distCacheFilePath.Value) == false) return;
var content = File.ReadAllText(path);
var content = File.ReadAllText(_distCacheFilePath.Value);
int last;
if (int.TryParse(content, out last))
_lastId = last;
@@ -478,7 +479,7 @@ namespace Umbraco.Core.Sync
/// </remarks>
private void SaveLastSynced(int id)
{
File.WriteAllText(SyncFilePath, id.ToString(CultureInfo.InvariantCulture));
File.WriteAllText(_distCacheFilePath.Value, id.ToString(CultureInfo.InvariantCulture));
_lastId = id;
}
@@ -498,20 +499,40 @@ namespace Umbraco.Core.Sync
+ "/D" + AppDomain.CurrentDomain.Id // eg 22
+ "] " + Guid.NewGuid().ToString("N").ToUpper(); // make it truly unique
/// <summary>
/// Gets the sync file path for the local server.
/// </summary>
/// <returns>The sync file path for the local server.</returns>
private static string SyncFilePath
private static string GetDistCacheFilePath()
{
get
{
var tempFolder = IOHelper.MapPath("~/App_Data/TEMP/DistCache/" + NetworkHelper.FileSafeMachineName);
if (Directory.Exists(tempFolder) == false)
Directory.CreateDirectory(tempFolder);
var fileName = HttpRuntime.AppDomainAppId.ReplaceNonAlphanumericChars(string.Empty) + "-lastsynced.txt";
return Path.Combine(tempFolder, HttpRuntime.AppDomainAppId.ReplaceNonAlphanumericChars(string.Empty) + "-lastsynced.txt");
string distCacheFilePath;
switch (GlobalSettings.LocalTempStorageLocation)
{
case LocalTempStorage.AspNetTemp:
distCacheFilePath = Path.Combine(HttpRuntime.CodegenDir, @"UmbracoData", fileName);
break;
case LocalTempStorage.EnvironmentTemp:
var appDomainHash = HttpRuntime.AppDomainAppId.ToSHA1();
var cachePath = Path.Combine(Environment.ExpandEnvironmentVariables("%temp%"), "UmbracoData",
//include the appdomain hash is just a safety check, for example if a website is moved from worker A to worker B and then back
// to worker A again, in theory the %temp% folder should already be empty but we really want to make sure that its not
// utilizing an old path
appDomainHash);
distCacheFilePath = Path.Combine(cachePath, fileName);
break;
case LocalTempStorage.Default:
default:
var tempFolder = IOHelper.MapPath("~/App_Data/TEMP/DistCache");
distCacheFilePath = Path.Combine(tempFolder, fileName);
break;
}
//ensure the folder exists
var folder = Path.GetDirectoryName(distCacheFilePath);
if (folder == null)
throw new InvalidOperationException("The folder could not be determined for the file " + distCacheFilePath);
if (Directory.Exists(folder) == false)
Directory.CreateDirectory(folder);
return distCacheFilePath;
}
#endregion
+49 -5
View File
@@ -1,13 +1,12 @@
using System;
using System.Collections.Generic;
using System.Configuration;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Security;
using System.Text;
using System.Web;
using System.Web.Compilation;
using System.Web.Hosting;
using Umbraco.Core.IO;
using Umbraco.Core.Logging;
@@ -21,6 +20,38 @@ namespace Umbraco.Core
{
private static volatile HashSet<Assembly> _localFilteredAssemblyCache;
private static readonly object LocalFilteredAssemblyCacheLocker = new object();
private static readonly List<string> NotifiedLoadExceptionAssemblies = new List<string>();
private static string[] _assembliesAcceptingLoadExceptions;
private static string[] AssembliesAcceptingLoadExceptions
{
get
{
if (_assembliesAcceptingLoadExceptions != null)
return _assembliesAcceptingLoadExceptions;
var s = ConfigurationManager.AppSettings["Umbraco.AssembliesAcceptingLoadExceptions"];
return _assembliesAcceptingLoadExceptions = string.IsNullOrWhiteSpace(s)
? new string[0]
: s.Split(',').Select(x => x.Trim()).ToArray();
}
}
private static bool AcceptsLoadExceptions(Assembly a)
{
if (AssembliesAcceptingLoadExceptions.Length == 0)
return false;
if (AssembliesAcceptingLoadExceptions.Length == 1 && AssembliesAcceptingLoadExceptions[0] == "*")
return true;
var name = a.GetName().Name; // simple name of the assembly
return AssembliesAcceptingLoadExceptions.Any(pattern =>
{
if (pattern.Length > name.Length) return false; // pattern longer than name
if (pattern.Length == name.Length) return pattern.InvariantEquals(name); // same length, must be identical
if (pattern[pattern.Length] != '.') return false; // pattern is shorter than name, must end with dot
return name.StartsWith(pattern); // and name must start with pattern
});
}
/// <summary>
/// lazily load a reference to all assemblies and only local assemblies.
@@ -45,7 +76,7 @@ namespace Umbraco.Core
HashSet<Assembly> assemblies = null;
try
{
var isHosted = HttpContext.Current != null || HostingEnvironment.IsHosted;
var isHosted = IOHelper.IsHosted;
try
{
@@ -528,9 +559,22 @@ namespace Umbraco.Core
AppendCouldNotLoad(sb, a, getAll);
foreach (var loaderException in rex.LoaderExceptions.WhereNotNull())
AppendLoaderException(sb, loaderException);
var ex = new ReflectionTypeLoadException(rex.Types, rex.LoaderExceptions, sb.ToString());
// rethrow with new message
throw new ReflectionTypeLoadException(rex.Types, rex.LoaderExceptions, sb.ToString());
// rethrow with new message, unless accepted
if (AcceptsLoadExceptions(a) == false) throw ex;
// log a warning, and return what we can
lock (NotifiedLoadExceptionAssemblies)
{
if (NotifiedLoadExceptionAssemblies.Contains(a.FullName) == false)
{
NotifiedLoadExceptionAssemblies.Add(a.FullName);
LogHelper.WarnWithException(typeof(TypeFinder), "Could not load all types from " + a.GetName().Name + ".", ex);
}
}
return rex.Types.WhereNotNull().ToArray();
}
}
+4
View File
@@ -117,6 +117,8 @@ namespace Umbraco.Core
{
case UmbracoObjectTypes.Document:
return Document;
case UmbracoObjectTypes.DocumentBlueprint:
return DocumentBluePrint;
case UmbracoObjectTypes.Media:
return Media;
case UmbracoObjectTypes.Member:
@@ -161,6 +163,8 @@ namespace Umbraco.Core
{
case Document:
return UmbracoObjectTypes.Document;
case DocumentBluePrint:
return UmbracoObjectTypes.DocumentBlueprint;
case Media:
return UmbracoObjectTypes.Media;
case Member:
+4 -3
View File
@@ -56,8 +56,8 @@
<HintPath>..\packages\SharpZipLib.0.86.0\lib\20\ICSharpCode.SharpZipLib.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="ImageProcessor, Version=2.5.3.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\ImageProcessor.2.5.3\lib\net45\ImageProcessor.dll</HintPath>
<Reference Include="ImageProcessor, Version=2.5.6.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\ImageProcessor.2.5.6\lib\net45\ImageProcessor.dll</HintPath>
</Reference>
<Reference Include="log4net, Version=2.0.8.0, Culture=neutral, PublicKeyToken=669e0ddf0bb1aa2a, processorArchitecture=MSIL">
<HintPath>..\packages\log4net.2.0.8\lib\net45-full\log4net.dll</HintPath>
@@ -198,7 +198,7 @@
<Compile Include="Configuration\BaseRest\ExtensionElement.cs" />
<Compile Include="Configuration\BaseRest\ExtensionElementCollection.cs" />
<Compile Include="Configuration\BaseRest\MethodElement.cs" />
<Compile Include="Configuration\ContentXmlStorage.cs" />
<Compile Include="Configuration\LocalTempStorage.cs" />
<Compile Include="Configuration\CoreDebug.cs" />
<Compile Include="Configuration\Dashboard\AccessElement.cs" />
<Compile Include="Configuration\Dashboard\AccessItem.cs" />
@@ -366,6 +366,7 @@
<Compile Include="HashGenerator.cs" />
<Compile Include="IEmailSender.cs" />
<Compile Include="IHttpContextAccessor.cs" />
<Compile Include="Logging\RollingFileCleanupAppender.cs" />
<Compile Include="Models\EntityBase\EntityPath.cs" />
<Compile Include="Models\EntityBase\IDeletableEntity.cs" />
<Compile Include="Models\IUserControl.cs" />
+1 -1
View File
@@ -3,7 +3,7 @@
<package id="AutoMapper" version="3.3.1" targetFramework="net45" />
<package id="ClientDependency" version="1.9.2" targetFramework="net45" />
<package id="HtmlAgilityPack" version="1.4.9.5" targetFramework="net45" />
<package id="ImageProcessor" version="2.5.3" targetFramework="net45" />
<package id="ImageProcessor" version="2.5.6" targetFramework="net45" />
<package id="log4net" version="2.0.8" targetFramework="net45" />
<package id="Log4Net.Async" version="2.0.4" targetFramework="net45" />
<package id="Microsoft.AspNet.Identity.Core" version="2.2.1" targetFramework="net45" />
+1 -1
View File
@@ -20,7 +20,7 @@ using Umbraco.Tests.TestHelpers.Entities;
namespace Umbraco.Tests.Models
{
[TestFixture]
public class ContentTests : BaseUmbracoConfigurationTest
public class ContentTests : BaseUmbracoApplicationTest
{
[SetUp]
public void Init()
@@ -388,13 +388,12 @@ namespace Umbraco.Tests.TestHelpers
return ctx;
}
protected FakeHttpContextFactory GetHttpContextFactory(string url, RouteData routeData = null)
protected virtual FakeHttpContextFactory GetHttpContextFactory(string url, RouteData routeData = null)
{
var factory = routeData != null
? new FakeHttpContextFactory(url, routeData)
: new FakeHttpContextFactory(url);
//set the state helper
StateHelper.HttpContext = factory.HttpContext;
@@ -118,26 +118,13 @@ namespace Umbraco.Tests.TestHelpers
});
}
/// <summary>
/// By default this returns false which means the plugin manager will not be reset so it doesn't need to re-scan
/// all of the assemblies. Inheritors can override this if plugin manager resetting is required, generally needs
/// to be set to true if the SetupPluginManager has been overridden.
/// </summary>
protected virtual bool PluginManagerResetRequired
{
get { return false; }
}
/// <summary>
/// Inheritors can resset the plugin manager if they choose to on teardown
/// </summary>
protected virtual void ResetPluginManager()
{
if (PluginManagerResetRequired)
{
PluginManager.Current = null;
}
}
PluginManager.Current = null;
}
protected virtual CacheHelper CreateCacheHelper()
{
@@ -185,26 +172,23 @@ namespace Umbraco.Tests.TestHelpers
/// </summary>
protected virtual void SetupPluginManager()
{
if (PluginManager.Current == null || PluginManagerResetRequired)
PluginManager.Current = new PluginManager(
new ActivatorServiceProvider(),
CacheHelper.RuntimeCache, ProfilingLogger, false)
{
PluginManager.Current = new PluginManager(
new ActivatorServiceProvider(),
CacheHelper.RuntimeCache, ProfilingLogger, false)
AssembliesToScan = new[]
{
AssembliesToScan = new[]
{
Assembly.Load("Umbraco.Core"),
Assembly.Load("umbraco"),
Assembly.Load("Umbraco.Tests"),
Assembly.Load("businesslogic"),
Assembly.Load("cms"),
Assembly.Load("controls"),
Assembly.Load("umbraco.editorControls"),
Assembly.Load("umbraco.MacroEngines"),
Assembly.Load("umbraco.providers"),
}
};
}
Assembly.Load("Umbraco.Core"),
Assembly.Load("umbraco"),
Assembly.Load("Umbraco.Tests"),
Assembly.Load("businesslogic"),
Assembly.Load("cms"),
Assembly.Load("controls"),
Assembly.Load("umbraco.editorControls"),
Assembly.Load("umbraco.MacroEngines"),
Assembly.Load("umbraco.providers"),
}
};
}
/// <summary>
+8 -1
View File
@@ -7,12 +7,19 @@ using NUnit.Framework;
using Umbraco.Core;
using Umbraco.Core.Deploy;
using Umbraco.Core.Serialization;
using Umbraco.Tests.TestHelpers;
namespace Umbraco.Tests
{
[TestFixture]
public class UdiTests
public class UdiTests : BaseUmbracoApplicationTest
{
[SetUp]
public void Setup()
{
Udi.ResetUdiTypes();
}
[Test]
public void StringUdiCtorTest()
{
+2 -2
View File
@@ -62,8 +62,8 @@
<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="Examine, Version=0.1.85.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\Examine.0.1.85\lib\net45\Examine.dll</HintPath>
<Reference Include="Examine, Version=0.1.88.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\Examine.0.1.88\lib\net45\Examine.dll</HintPath>
</Reference>
<Reference Include="ICSharpCode.SharpZipLib, Version=0.86.0.518, Culture=neutral, PublicKeyToken=1b03e6acf1164f73, processorArchitecture=MSIL">
<HintPath>..\packages\SharpZipLib.0.86.0\lib\20\ICSharpCode.SharpZipLib.dll</HintPath>
@@ -20,8 +20,14 @@ using Umbraco.Web.Templates;
namespace Umbraco.Tests.Web
{
[TestFixture]
public class TemplateUtilitiesTests
public class TemplateUtilitiesTests : BaseUmbracoApplicationTest
{
[SetUp]
public void Setup()
{
Udi.ResetUdiTypes();
}
[TestCase("", "")]
[TestCase("hello href=\"{localLink:1234}\" world ", "hello href=\"/my-test-url\" world ")]
[TestCase("hello href=\"{localLink:umb://document-type/9931BDE0-AAC3-4BAB-B838-909A7B47570E}\" world ", "hello href=\"/my-test-url\" world ")]
+1 -1
View File
@@ -2,7 +2,7 @@
<packages>
<package id="AutoMapper" version="3.3.1" targetFramework="net45" />
<package id="Castle.Core" version="4.0.0" targetFramework="net45" />
<package id="Examine" version="0.1.85" targetFramework="net45" />
<package id="Examine" version="0.1.88" targetFramework="net45" />
<package id="log4net" version="2.0.8" targetFramework="net45" />
<package id="Log4Net.Async" version="2.0.4" targetFramework="net45" />
<package id="Lucene.Net" version="2.9.4.1" targetFramework="net45" />
@@ -31,15 +31,17 @@
display: block;
padding: 4px;
line-height: @baseLineHeight;
border: 1px solid #ddd;
border: 1px solid @gray-8;
.border-radius(@baseBorderRadius);
.box-shadow(0 1px 3px rgba(0,0,0,.055));
.transition(all .2s ease-in-out);
}
// Add a hover/focus state for linked versions only
a.thumbnail:hover,
a.thumbnail:focus {
border-color: @linkColor;
// Add a hover/focus state for linked versions only.
a.thumbnail:hover,
a.thumbnail:focus,
a div.thumbnail:hover,
a div.thumbnail:focus {
border-color: @turquoise;
.box-shadow(0 1px 4px rgba(0,105,214,.25));
}
@@ -7,12 +7,22 @@ var app = angular.module("Umbraco.canvasdesigner", ['colorpicker', 'ui.slider',
.controller("Umbraco.canvasdesignerController", function ($scope, $http, $window, $timeout, $location, dialogService) {
var isInit = $location.search().init;
if (isInit === "true") {
//do not continue, this is the first load of this new window, if this is passed in it means it's been
//initialized by the content editor and then the content editor will actually re-load this window without
//this flag. This is a required trick to get around chrome popup mgr. We don't want to double load preview.aspx
//since that will double prepare the preview documents
return;
}
$scope.isOpen = false;
$scope.frameLoaded = false;
$scope.enableCanvasdesigner = 0;
$scope.googleFontFamilies = {};
$scope.pageId = $location.search().id;
$scope.pageUrl = "../dialogs/Preview.aspx?id=" + $location.search().id;
var pageId = $location.search().id;
$scope.pageId = pageId;
$scope.pageUrl = "../dialogs/Preview.aspx?id=" + pageId;
$scope.valueAreLoaded = false;
$scope.devices = [
{ name: "desktop", css: "desktop", icon: "icon-display", title: "Desktop" },
@@ -3,7 +3,7 @@
* @name umbraco.directives.directive:umbSections
* @restrict E
**/
function sectionsDirective($timeout, $window, navigationService, treeService, sectionService, appState, eventsService, $location) {
function sectionsDirective($timeout, $window, navigationService, treeService, sectionService, appState, eventsService, $location, historyService) {
return {
restrict: "E", // restrict to an element
replace: true, // replace the html element with the template
@@ -161,7 +161,9 @@ function sectionsDirective($timeout, $window, navigationService, treeService, se
$location.path(section.routePath);
}
else {
$location.path(section.alias).search('');
var lastAccessed = historyService.getLastAccessedItemForSection(section.alias);
var path = lastAccessed != null ? lastAccessed.link : section.alias;
$location.path(path).search('');
}
};
@@ -208,9 +208,9 @@
if (!$scope.busy) {
// Chromes popup blocker will kick in if a window is opened
// outwith the initial scoped request. This trick will fix that.
// without the initial scoped request. This trick will fix that.
//
var previewWindow = $window.open('preview/?id=' + content.id, 'umbpreview');
var previewWindow = $window.open('preview/?init=true&id=' + content.id, 'umbpreview');
// Build the correct path so both /#/ and #/ work.
var redirect = Umbraco.Sys.ServerVariables.umbracoSettings.umbracoPath + '/preview/?id=' + content.id;
@@ -36,7 +36,7 @@ angular.module("umbraco.directives")
// this will greatly improve performance since there's potentially a lot of nodes being rendered = a LOT of watches!
template: '<li ng-class="{\'current\': (node == currentNode), \'has-children\': node.hasChildren}" on-right-click="altSelect(node, $event)">' +
'<div ng-class="getNodeCssClass(node)" ng-swipe-right="options(node, $event)" >' +
'<div ng-class="getNodeCssClass(node)" ng-swipe-right="options(node, $event)" ng-dblclick="load(node)" >' +
//NOTE: This ins element is used to display the search icon if the node is a container/listview and the tree is currently in dialog
//'<ins ng-if="tree.enablelistviewsearch && node.metaData.isContainer" class="umb-tree-node-search icon-search" ng-click="searchNode(node, $event)" alt="searchAltText"></ins>' +
'<ins ng-class="{\'icon-navigation-right\': !node.expanded || node.metaData.isContainer, \'icon-navigation-down\': node.expanded && !node.metaData.isContainer}" ng-click="load(node)">&nbsp;</ins>' +
@@ -66,9 +66,13 @@ Use this directive to render an avatar.
function getNameInitials(name) {
if(name) {
var initials = name.match(/\b\w/g) || [];
initials = ((initials.shift() || '') + (initials.pop() || '')).toUpperCase();
return initials;
var names = name.split(' '),
initials = names[0].substring(0, 1);
if (names.length > 1) {
initials += names[names.length - 1].substring(0, 1);
}
return initials.toUpperCase();
}
return null;
}
@@ -110,7 +110,7 @@ Use this directive to generate a thumbnail grid of media items.
itemMinWidth = scope.itemMinWidth;
}
if (scope.itemMinWidth) {
if (scope.itemMinHeight) {
itemMinHeight = scope.itemMinHeight;
}
@@ -0,0 +1,26 @@
(function () {
'use strict';
// comes from https://codepen.io/jakob-e/pen/eNBQaP
// works fine with Angular 1.6.5 - alas not with 1.1.5 - binding issue
function PasswordToggleDirective($compile) {
var directive = {
restrict: 'A',
scope: {},
link: function(scope, elem, attrs) {
scope.tgl = function () { elem.attr("type", (elem.attr("type") === "text" ? "password" : "text")); }
var lnk = angular.element("<a data-ng-click=\"tgl()\">Toggle</a>");
$compile(lnk)(scope);
elem.wrap("<div class=\"password-toggle\"/>").after(lnk);
}
};
return directive;
}
angular.module('umbraco.directives').directive('umbPasswordToggle', PasswordToggleDirective);
})();
@@ -41,7 +41,7 @@ function entityResource($q, $http, umbRequestHelper) {
if (!value) {
return "";
}
value = value.replace("#", "");
return umbRequestHelper.resourcePromise(
$http.get(
umbRequestHelper.getApiUrl(
@@ -2,12 +2,12 @@
* @ngdoc service
* @name umbraco.services.assetsService
*
* @requires $q
* @requires $q
* @requires angularHelper
*
*
* @description
* Promise-based utillity service to lazy-load client-side dependencies inside angular controllers.
*
*
* ##usage
* To use, simply inject the assetsService into any controller that needs it, and make
* sure the umbraco.services module is accesible - which it should be by default.
@@ -18,7 +18,7 @@
* //this code executes when the dependencies are done loading
* });
* });
* </pre>
* </pre>
*
* You can also load individual files, which gives you greater control over what attibutes are passed to the file, as well as timeout
*
@@ -38,13 +38,14 @@
* //loadcss cannot determine when the css is done loading, so this will trigger instantly
* });
* });
* </pre>
* </pre>
*/
angular.module('umbraco.services')
.factory('assetsService', function ($q, $log, angularHelper, umbRequestHelper, $rootScope, $http) {
var initAssetsLoaded = false;
var appendRnd = function (url) {
function appendRnd (url) {
//if we don't have a global umbraco obj yet, the app is bootstrapping
if (!Umbraco.Sys.ServerVariables.application) {
return url;
@@ -77,7 +78,8 @@ angular.module('umbraco.services')
return this.loadedAssets[path];
}
},
/**
/**
Internal method. This is called when the application is loading and the user is already authenticated, or once the user is authenticated.
There's a few assets the need to be loaded for the application to function but these assets require authentication to load.
*/
@@ -108,10 +110,10 @@ angular.module('umbraco.services')
*
* @description
* Injects a file as a stylesheet into the document head
*
*
* @param {String} path path to the css file to load
* @param {Scope} scope optional scope to pass into the loader
* @param {Object} keyvalue collection of attributes to pass to the stylesheet element
* @param {Object} keyvalue collection of attributes to pass to the stylesheet element
* @param {Number} timeout in milliseconds
* @returns {Promise} Promise object which resolves when the file has loaded
*/
@@ -149,10 +151,10 @@ angular.module('umbraco.services')
*
* @description
* Injects a file as a javascript into the document
*
*
* @param {String} path path to the js file to load
* @param {Scope} scope optional scope to pass into the loader
* @param {Object} keyvalue collection of attributes to pass to the script element
* @param {Object} keyvalue collection of attributes to pass to the script element
* @param {Number} timeout in milliseconds
* @returns {Promise} Promise object which resolves when the file has loaded
*/
@@ -192,8 +194,8 @@ angular.module('umbraco.services')
* @methodOf umbraco.services.assetsService
*
* @description
* Injects a collection of files, this can be ONLY js files
*
* Injects a collection of css and js files
*
*
* @param {Array} pathArray string array of paths to the files to load
* @param {Scope} scope optional scope to pass into the loader
@@ -206,61 +208,72 @@ angular.module('umbraco.services')
throw "pathArray must be an array";
}
// Check to see if there's anything to load, resolve promise if not
var nonEmpty = _.reject(pathArray, function (item) {
return item === undefined || item === "";
});
});
//don't load anything if there's nothing to load
if (nonEmpty.length > 0) {
var promises = [];
var assets = [];
//compile a list of promises
//blocking
_.each(nonEmpty, function (path) {
path = convertVirtualPath(path);
var asset = service._getAssetPromise(path);
//if not previously loaded, add to list of promises
if (asset.state !== "loaded") {
if (asset.state === "new") {
asset.state = "loading";
assets.push(asset);
}
//we need to always push to the promises collection to monitor correct
//execution
promises.push(asset.deferred.promise);
}
});
//gives a central monitoring of all assets to load
promise = $q.all(promises);
_.each(assets, function (asset) {
LazyLoad.js(appendRnd(asset.path), function () {
asset.state = "loaded";
if (!scope) {
asset.deferred.resolve(true);
}
else {
angularHelper.safeApply(scope, function () {
asset.deferred.resolve(true);
});
}
});
});
}
else {
//return and resolve
if (nonEmpty.length === 0) {
var deferred = $q.defer();
promise = deferred.promise;
deferred.resolve(true);
return promise;
}
//compile a list of promises
//blocking
var promises = [];
var assets = [];
_.each(nonEmpty, function (path) {
path = convertVirtualPath(path);
var asset = service._getAssetPromise(path);
//if not previously loaded, add to list of promises
if (asset.state !== "loaded") {
if (asset.state === "new") {
asset.state = "loading";
assets.push(asset);
}
//we need to always push to the promises collection to monitor correct
//execution
promises.push(asset.deferred.promise);
}
});
//gives a central monitoring of all assets to load
promise = $q.all(promises);
// Split into css and js asset arrays, and use LazyLoad on each array
var cssAssets = _.filter(assets,
function (asset) {
return asset.path.match(/(\.css$|\.css\?)/ig);
});
var jsAssets = _.filter(assets,
function (asset) {
return asset.path.match(/(\.js$|\.js\?)/ig);
});
function assetLoaded(asset) {
asset.state = "loaded";
if (!scope) {
asset.deferred.resolve(true);
return;
}
angularHelper.safeApply(scope,
function () {
asset.deferred.resolve(true);
});
}
if (cssAssets.length > 0) {
var cssPaths = _.map(cssAssets, function (asset) { return appendRnd(asset.path) });
LazyLoad.css(cssPaths, function() { _.each(cssAssets, assetLoaded); });
}
if (jsAssets.length > 0) {
var jsPaths = _.map(jsAssets, function (asset) { return appendRnd(asset.path) });
LazyLoad.js(jsPaths, function () { _.each(jsAssets, assetLoaded); });
}
return promise;
}
@@ -115,6 +115,27 @@ angular.module('umbraco.services')
*/
getCurrent: function(){
return nArray;
}
},
/**
* @ngdoc method
* @name umbraco.services.historyService#getLastAccessedItemForSection
* @methodOf umbraco.services.historyService
*
* @description
* Method to return the item that was last accessed in the given section
*
* @param {string} sectionAlias Alias of the section to return the last accessed item for.
*/
getLastAccessedItemForSection: function (sectionAlias) {
for (var i = 0, len = nArray.length; i < len; i++) {
var item = nArray[i];
if (item.link.indexOf(sectionAlias + "/") === 0) {
return item;
}
}
return null;
}
};
});
@@ -242,8 +242,8 @@
var propGroups = _.find(genericTab.properties, function (item) {
return item.alias === "_umb_membergroup";
});
saveModel.email = propEmail.value;
saveModel.username = propLogin.value;
saveModel.email = propEmail.value.trim();
saveModel.username = propLogin.value.trim();
saveModel.password = this.formatChangePasswordModel(propPass.value);
@@ -17,7 +17,7 @@ angular.module("umbraco.install").factory('installerService', function($rootScop
//add to umbraco installer facts here
var facts = ['Umbraco helped millions of people watch a man jump from the edge of space',
'Over 420 000 websites are currently powered by Umbraco',
'Over 440 000 websites are currently powered by Umbraco',
"At least 2 people have named their cat 'Umbraco'",
'On an average day, more than 1000 people download Umbraco',
'<a target="_blank" href="https://umbraco.tv">umbraco.tv</a> is the premier source of Umbraco video tutorials to get you started',
@@ -31,10 +31,10 @@ angular.module("umbraco.install").factory('installerService', function($rootScop
"At least 4 people have the Umbraco logo tattooed on them",
"'Umbraco' is the danish name for an allen key",
"Umbraco has been around since 2005, that's a looong time in IT",
"More than 550 people from all over the world meet each year in Denmark in June for our annual conference <a target='_blank' href='https://umbra.co/codegarden'>CodeGarden</a>",
"More than 600 people from all over the world meet each year in Denmark in June for our annual conference <a target='_blank' href='https://umbra.co/codegarden'>CodeGarden</a>",
"While you are installing Umbraco someone else on the other side of the planet is probably doing it too",
"You can extend Umbraco without modifying the source code using either JavaScript or C#",
"Umbraco was installed in more than 165 countries in 2015"
"Umbraco has been installed in more than 198 countries"
];
/**
@@ -261,6 +261,9 @@ input[type="submit"].btn {
*padding-top: 1px;
*padding-bottom: 1px;
}
// Safari defaults to 1px for input. Ref U4-7721.
margin: 0px;
}
@@ -35,3 +35,10 @@
margin-right: 5px;
color: @gray-7;
}
input.umb-breadcrumbs__add-ancestor {
height: 25px;
margin-top: -2px;
margin-left: 3px;
width: 100px;
}
@@ -636,9 +636,19 @@
clear: both;
}
.umb-grid .mce-btn button {
padding: 8px 6px;
line-height: inherit;
.umb-grid .mce-btn {
button {
padding-top: 8px;
padding-bottom: 8px;
padding-left: 6px;
line-height: inherit;
}
&:not(.mce-menubtn) {
button {
padding-right: 6px;
}
}
}
.umb-grid .mce-toolbar {
@@ -29,12 +29,12 @@
padding: 15px 10px;
box-sizing: border-box;
text-align: center;
border: 2px solid transparent;
border: 1px solid @gray-8;
height: 100%;
}
.umb-healthcheck-group:hover {
border: 2px solid @turquoise;
border: 1px solid @turquoise;
cursor: pointer;
}
@@ -66,7 +66,7 @@
margin-bottom: auto;
}
.login-overlay .form input[type="text"],
.login-overlay .form input[type="text"],
.login-overlay .form input[type="password"],
.login-overlay .form input[type="email"] {
height: 36px;
@@ -114,8 +114,44 @@
line-height: 36px;
}
.login-overlay .text-error,
.login-overlay .text-info
.login-overlay .text-error,
.login-overlay .text-info
{
font-weight:bold;
}
}
.password-toggle {
position: relative;
display: block;
user-select: none;
input::-ms-clear, input::-ms-reveal {
display: none;
}
a {
opacity: .5;
cursor: pointer;
display: inline-block;
position: absolute;
height: 1px;
width: 45px;
height: 75%;
font-size: 0;
background-repeat: no-repeat;
background-size: 50%;
background-position: center;
top: 0;
margin-left: -45px;
z-index: 1;
-webkit-tap-highlight-color: transparent;
}
[type="text"] + a {
background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='32' height='32' viewBox='0 0 32 32'%3E%3Cpath fill='%23444' d='M29.6.4C29 0 28 0 27.4.4L21 6.8c-1.4-.5-3-.8-5-.8C9 6 3 10 0 16c1.3 2.6 3 4.8 5.4 6.5l-5 5c-.5.5-.5 1.5 0 2 .3.4.7.5 1 .5s1 0 1.2-.4l27-27C30 2 30 1 29.6.4zM13 10c1.3 0 2.4 1 2.8 2L12 15.8c-1-.4-2-1.5-2-2.8 0-1.7 1.3-3 3-3zm-9.6 6c1.2-2 2.8-3.5 4.7-4.7l.7-.2c-.4 1-.6 2-.6 3 0 1.8.6 3.4 1.6 4.7l-2 2c-1.6-1.2-3-2.7-4-4.4zM24 13.8c0-.8 0-1.7-.4-2.4l-10 10c.7.3 1.6.4 2.4.4 4.4 0 8-3.6 8-8z'/%3E%3Cpath fill='%23444' d='M26 9l-2.2 2.2c2 1.3 3.6 3 4.8 4.8-1.2 2-2.8 3.5-4.7 4.7-2.7 1.5-5.4 2.3-8 2.3-1.4 0-2.6 0-3.8-.4L10 25c2 .6 4 1 6 1 7 0 13-4 16-10-1.4-2.8-3.5-5.2-6-7z'/%3E%3C/svg%3E");
}
[type="password"] + a {
background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='32' height='32' viewBox='0 0 32 32'%3E%3Cpath fill='%23444' d='M16 6C9 6 3 10 0 16c3 6 9 10 16 10s13-4 16-10c-3-6-9-10-16-10zm8 5.3c1.8 1.2 3.4 2.8 4.6 4.7-1.2 2-2.8 3.5-4.7 4.7-3 1.5-6 2.3-8 2.3s-6-.8-8-2.3C6 19.5 4 18 3 16c1.5-2 3-3.5 5-4.7l.6-.2C8 12 8 13 8 14c0 4.5 3.5 8 8 8s8-3.5 8-8c0-1-.3-2-.6-2.6l.4.3zM16 13c0 1.7-1.3 3-3 3s-3-1.3-3-3 1.3-3 3-3 3 1.3 3 3z'/%3E%3C/svg%3E");
}
}
@@ -109,16 +109,48 @@ ul.color-picker li a {
}
/* pre-value editor */
/*.control-group.color-picker-preval:before {
content: "";
display: inline-block;
vertical-align: middle;
height: 100%;
}*/
/*.control-group.color-picker-preval div.thumbnail {
display: inline-block;
vertical-align: middle;
}*/
.control-group.color-picker-preval div.color-picker-prediv {
display: inline-block;
width: 60%;
}
.control-group.color-picker-preval pre {
display: inline;
margin-right: 20px;
margin-left: 10px;
width: 50%;
white-space: nowrap;
overflow: hidden;
margin-bottom: 0;
vertical-align: middle;
}
.control-group.color-picker-preval btn {
//vertical-align: middle;
}
.control-group.color-picker-preval input[type="text"] {
min-width: 40%;
width: 40%;
display: inline-block;
margin-right: 20px;
margin-top: 1px;
}
.control-group.color-picker-preval label {
border:solid @white 1px;
padding:6px;
border: solid @white 1px;
padding: 6px;
}
@@ -126,21 +158,21 @@ ul.color-picker li a {
// Media picker
// --------------------------------------------------
.umb-mediapicker .add-link {
display: inline-block;
height: 120px;
width: 120px;
text-align: center;
color: @gray-8;
border: 2px @gray-8 dashed;
line-height: 120px;
text-decoration: none;
display: flex;
justify-content:center;
align-items:center;
width: 120px;
text-align: center;
color: @gray-8;
border: 2px @gray-8 dashed;
text-decoration: none;
transition: all 150ms ease-in-out;
transition: all 150ms ease-in-out;
&:hover {
color: @turquoise-d1;
border-color: @turquoise;
}
&:hover {
color: @turquoise-d1;
border-color: @turquoise;
}
}
.umb-mediapicker .picked-image {
@@ -165,6 +197,10 @@ ul.color-picker li a {
text-decoration: none;
}
.umb-mediapicker .add-link-square {
height: 120px;
}
.umb-thumbnails{
@@ -207,11 +243,10 @@ ul.color-picker li a {
.umb-mediapicker .umb-sortable-thumbnails li {
flex-direction: column;
margin: 0;
margin: 0 5px 0 0;
padding: 5px;
}
.umb-sortable-thumbnails li:hover a {
display: flex;
justify-content: center;
@@ -219,16 +254,20 @@ ul.color-picker li a {
}
.umb-sortable-thumbnails li img {
max-width:100%;
max-height:100%;
margin:auto;
display:block;
background-image: url(../img/checkered-background.png);
max-width:100%;
max-height:100%;
margin:auto;
display:block;
background-image: url(../img/checkered-background.png);
}
.umb-sortable-thumbnails li img.noScale{
max-width: none !important;
max-height: none !important;
.umb-sortable-thumbnails li img.trashed {
opacity:0.3;
}
.umb-sortable-thumbnails li img.noScale {
max-width: none !important;
max-height: none !important;
}
.umb-sortable-thumbnails .umb-icon-holder {
@@ -254,8 +293,8 @@ ul.color-picker li a {
}
.umb-sortable-thumbnails li:hover .umb-sortable-thumbnails__actions {
opacity: 1;
visibility: visible;
opacity: 1;
visibility: visible;
}
.umb-sortable-thumbnails .umb-sortable-thumbnails__action {
@@ -285,27 +324,27 @@ ul.color-picker li a {
// -------------------------------------------------
.umb-cropper{
position: relative;
position: relative;
}
.umb-cropper img, .umb-cropper-gravity img{
position: relative;
max-width: 100%;
height: auto;
top: 0;
left: 0;
position: relative;
max-width: 100%;
height: auto;
top: 0;
left: 0;
}
.umb-cropper img {
max-width: none;
max-width: none;
}
.umb-cropper .overlay, .umb-cropper-gravity .overlay {
top: 0;
left: 0;
cursor: move;
z-index: @zindexCropperOverlay;
position: absolute;
top: 0;
left: 0;
cursor: move;
z-index: @zindexCropperOverlay;
position: absolute;
}
.umb-cropper .viewport{
@@ -317,43 +356,43 @@ ul.color-picker li a {
}
.umb-cropper-gravity .viewport{
overflow: hidden;
position: relative;
width: 100%;
height: 100%;
overflow: hidden;
position: relative;
width: 100%;
height: 100%;
}
.umb-cropper .viewport:after {
content: "";
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: @zindexCropperOverlay - 1;
-moz-opacity: .75;
opacity: .75;
filter: alpha(opacity=7);
-webkit-box-shadow: inset 0 0 0 20px white,inset 0 0 0 21px rgba(0,0,0,.1),inset 0 0 20px 21px rgba(0,0,0,.2);
-moz-box-shadow: inset 0 0 0 20px white,inset 0 0 0 21px rgba(0,0,0,.1),inset 0 0 20px 21px rgba(0,0,0,.2);
box-shadow: inset 0 0 0 20px white,inset 0 0 0 21px rgba(0,0,0,.1),inset 0 0 20px 21px rgba(0,0,0,.2);
content: "";
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: @zindexCropperOverlay - 1;
-moz-opacity: .75;
opacity: .75;
filter: alpha(opacity=7);
-webkit-box-shadow: inset 0 0 0 20px white,inset 0 0 0 21px rgba(0,0,0,.1),inset 0 0 20px 21px rgba(0,0,0,.2);
-moz-box-shadow: inset 0 0 0 20px white,inset 0 0 0 21px rgba(0,0,0,.1),inset 0 0 20px 21px rgba(0,0,0,.2);
box-shadow: inset 0 0 0 20px white,inset 0 0 0 21px rgba(0,0,0,.1),inset 0 0 20px 21px rgba(0,0,0,.2);
}
.umb-cropper-gravity .overlay{
width: 14px;
height: 14px;
text-align: center;
border-radius: 20px;
background: @turquoise;
border: 3px solid @white;
opacity: 0.8;
width: 14px;
height: 14px;
text-align: center;
border-radius: 20px;
background: @turquoise;
border: 3px solid @white;
opacity: 0.8;
}
.umb-cropper-gravity .overlay i {
font-size: 26px;
line-height: 26px;
opacity: 0.8 !important;
font-size: 26px;
line-height: 26px;
opacity: 0.8 !important;
}
.umb-cropper .crop-container {
@@ -361,16 +400,16 @@ ul.color-picker li a {
}
.umb-cropper .crop-slider {
padding: 10px;
border-top: 1px solid @gray-10;
margin-top: 10px;
display: flex;
align-items: center;
justify-content: center;
flex-wrap: wrap;
@media (min-width: 769px) {
padding: 10px;
border-top: 1px solid @gray-10;
margin-top: 10px;
display: flex;
align-items: center;
justify-content: center;
flex-wrap: wrap;
@media (min-width: 769px) {
padding: 10px 50px 10px 50px;
}
}
}
.umb-cropper .crop-slider i {
@@ -16,7 +16,11 @@
maxFileSize: Umbraco.Sys.ServerVariables.umbracoSettings.maxFileSize + "KB",
acceptedFileTypes: mediaHelper.formatFileTypes(Umbraco.Sys.ServerVariables.umbracoSettings.imageFileTypes),
uploaded: false
}
}
$scope.togglePassword = function () {
var elem = $("form[name='loginForm'] input[name='password']");
elem.attr("type", (elem.attr("type") === "text" ? "password" : "text"));
}
function init() {
// Check if it is a new user
@@ -48,7 +52,7 @@
]).then(function () {
$scope.inviteStep = Number(inviteVal);
});
}
}
@@ -82,7 +86,7 @@
var progressPercentage = parseInt(100.0 * evt.loaded / evt.total, 10);
// set percentage property on file
$scope.avatarFile.uploadProgress = progressPercentage;
$scope.avatarFile.uploadProgress = progressPercentage;
}
}).success(function (data, status, headers, config) {
@@ -149,11 +153,11 @@
//error
formHelper.handleError(err);
$scope.invitedUserPasswordModel.buttonState = "error";
});
}
}
};
var setFieldFocus = function (form, field) {
@@ -180,7 +184,7 @@
}
function resetInputValidation() {
$scope.confirmPassword = "";
$scope.confirmPassword = "";
$scope.password = "";
$scope.login = "";
if ($scope.loginForm) {
@@ -255,7 +259,7 @@
//TODO: Do validation properly like in the invite password update
//if the login and password are not empty we need to automatically
//if the login and password are not empty we need to automatically
// validate them - this is because if there are validation errors on the server
// then the user has to change both username & password to resubmit which isn't ideal,
// so if they're not empty, we'll just make sure to set them to valid.
@@ -289,7 +293,7 @@
});
//setup a watch for both of the model values changing, if they change
// while the form is invalid, then revalidate them so that the form can
// while the form is invalid, then revalidate them so that the form can
// be submitted again.
$scope.loginForm.username.$viewChangeListeners.push(function () {
if ($scope.loginForm.username.$invalid) {
@@ -24,8 +24,8 @@
</label>
<input type="password" ng-model="invitedUserPasswordModel.password" name="password" class="-full-width-input" umb-auto-focus required val-server-field="value" autocomplete="off" ng-minlength="{{invitedUserPasswordModel.passwordPolicies.minPasswordLength}}" />
<span class="help-inline" val-msg-for="password" val-toggle-msg="required"><localize key="user_passwordIsBlank">Your new password cannot be blank!</localize></span>
<span class="help-inline" val-msg-for="password" val-toggle-msg="minlength">Minimum {{invitedUserPasswordModel.passwordPolicies.minPasswordLength}} characters</span>
<span class="help-inline" val-msg-for="password" val-toggle-msg="valServerField"></span>
<span class="help-inline" val-msg-for="password" val-toggle-msg="minlength">Minimum {{invitedUserPasswordModel.passwordPolicies.minPasswordLength}} characters</span>
<span class="help-inline" val-msg-for="password" val-toggle-msg="valServerField"></span>
</div>
<div class="control-group" ng-class="{error: setPasswordForm.confirmPassword.$invalid}">
@@ -49,15 +49,15 @@
<div class="form" ng-if="inviteStep === 2">
<div class="flex justify-center items-center">
<ng-form name="avatarForm">
<umb-progress-bar style="max-width: 100px; margin-bottom: 5px;"
ng-show="avatarFile.uploadStatus === 'uploading'"
progress="{{ avatarFile.uploadProgress }}"
size="s">
</umb-progress-bar>
<div class="umb-info-local-item text-error mt3" ng-if="avatarFile.uploadStatus === 'error'">
{{ avatarFile.serverErrorMessage }}
</div>
@@ -69,7 +69,7 @@
ngf-multiple="false"
ngf-pattern="{{avatarFile.acceptedFileTypes}}"
ngf-max-size="{{ avatarFile.maxFileSize }}">
<umb-avatar color="gray"
size="xl"
unknown-char="+"
@@ -77,7 +77,7 @@
img-srcset="{{invitedUser.avatars[4]}} 2x, {{invitedUser.avatars[4]}} 3x">
</umb-avatar>
</a>
</ng-form>
</div>
@@ -149,7 +149,9 @@
<div class="control-group" ng-class="{error: loginForm.password.$invalid}">
<label><localize key="general_password">Password</localize></label>
<input type="password" ng-model="password" name="password" class="-full-width-input" localize="placeholder" placeholder="@placeholders_password" autocomplete="off" />
<div class="password-toggle">
<input type="password" ng-model="password" name="password" class="-full-width-input" localize="placeholder" placeholder="@placeholders_password" autocomplete="off" /><a ng-click="togglePassword()">Toggle</a>
</div>
</div>
<div class="flex justify-between items-center">
@@ -2,7 +2,7 @@
<umb-control-group label="@general_url">
<input id="url" class="umb-editor input-block-level" type="text" style="margin-bottom: 10px;" ng-model="model.embed.url" ng-keyup="$event.keyCode == 13 ? vm.showPreview() : null" required />
<input type="button" ng-click="vm.showPreview()" class="btn" localize="value" value="@general_retrieve" />
<input type="button" ng-click="vm.showPreview()" class="btn" value="@general_retrieve" localize="value" />
</umb-control-group>
<umb-control-group>
@@ -12,15 +12,15 @@
<div ng-show="model.embed.supportsDimensions">
<umb-control-group label="@general_width">
<input type="text" ng-model="model.embed.width" on-blur="vm.changeSize('width')" />
<input type="number" pattern="[0-9]*" min="0" ng-model="model.embed.width" on-blur="vm.changeSize('width')" />
</umb-control-group>
<umb-control-group label="@general_height">
<input type="text" ng-model="model.embed.height" on-blur="vm.changeSize('height')" />
<input type="number" pattern="[0-9]*" min="0" ng-model="model.embed.height" on-blur="vm.changeSize('height')" />
</umb-control-group>
<umb-control-group label="@general_constrain">
<input id="constrain" type="checkbox" ng-model="model.embed.constrain" />
<input id="constrain" type="checkbox" ng-model="model.embed.constrain" />
</umb-control-group>
</div>
@@ -31,7 +31,7 @@
<div class="umb-el-wrap">
<label class="control-label" for="altField"><localize key="templateEditor_fallbackField">Fallback field</localize></label>
<div class="controls">
<select ng-model="vm.altField" >
<select ng-model="vm.altField" id="altField">
<optgroup localize="label" label="@templateEditor_customFields">
<option ng-repeat="(key, value) in vm.properties" value="{{value}}">{{value}}</option>
</optgroup>
@@ -43,6 +43,7 @@
</div>
</div>
</div>
</div>
<!-- Default value -->
<div>
@@ -55,7 +56,7 @@
<div class="umb-el-wrap">
<label class="control-label" for="altText"><localize key="templateEditor_defaultValue">Default value</localize></label>
<div class="controls">
<input type="text" name="altText" ng-model="vm.altText" umb-auto-focus>
<input type="text" id="altText" name="altText" ng-model="vm.altText" umb-auto-focus>
</div>
</div>
</div>
@@ -65,11 +66,13 @@
<div class="control-group umb-control-group">
<div class="umb-el-wrap">
<div class="controls">
<label class="control-label" for="recursive">
<label class="control-label" >
<localize key="templateEditor_recursive">Recursive</localize>
</label>
<input type="checkbox" name="recursive" ng-model="vm.recursive">
<localize key="templateEditor_recursiveDescr">Yes, make it recursive</localize>
<label for="recursive">
<input id="recursive" type="checkbox" name="recursive" ng-model="vm.recursive">
<localize key="templateEditor_recursiveDescr">Yes, make it recursive</localize>
</label>
</div>
</div>
</div>
@@ -134,7 +137,7 @@
<small><localize key="templateEditor_insertedBefore">Will be inserted before the field value</localize></small>
</label>
<div class="controls">
<input type="text" name="insertBefore" class="-full-width-input" ng-model="vm.insertBefore">
<input type="text" id="insertBefore" name="insertBefore" class="-full-width-input" ng-model="vm.insertBefore">
</div>
</div>
</div>
@@ -147,7 +150,7 @@
<small><localize key="templateEditor_insertedAfter">Will be inserted after the field value</localize></small>
</label>
<div class="controls">
<input type="text" name="insertAfter" class="-full-width-input" ng-model="vm.insertAfter">
<input type="text" id="insertAfter" name="insertAfter" class="-full-width-input" ng-model="vm.insertAfter">
</div>
</div>
</div>
@@ -162,8 +165,10 @@
<small><localize key="templateEditor_convertLineBreaksHelp">Replaces line breaks with break html tag</localize></small>
</label>
</div>
<input type="checkbox" name="linebreaks" ng-model="vm.convertLinebreaks">
<localize key="templateEditor_convertLineBreaksDescription">Yes, convert line breaks</localize>
<label for="linebreaks">
<input type="checkbox" id="linebreaks" name="linebreaks" ng-model="vm.convertLinebreaks">
<localize key="templateEditor_convertLineBreaksDescription">Yes, convert line breaks</localize>
</label>
</div>
</div>
</div>
@@ -56,6 +56,46 @@ angular.module("umbraco")
$scope.target = dialogOptions.currentTarget;
}
function onInit() {
if ($scope.startNodeId !== -1) {
entityResource.getById($scope.startNodeId, "media")
.then(function (ent) {
$scope.startNodeId = ent.id;
run();
});
} else {
run();
}
}
function run() {
//default root item
if (!$scope.target) {
if ($scope.lastOpenedNode && $scope.lastOpenedNode !== -1) {
entityResource.getById($scope.lastOpenedNode, "media")
.then(ensureWithinStartNode, gotoStartNode);
} else {
gotoStartNode();
}
} else {
//if a target is specified, go look it up - generally this target will just contain ids not the actual full
//media object so we need to look it up
var id = $scope.target.udi ? $scope.target.udi : $scope.target.id
var altText = $scope.target.altText;
mediaResource.getById(id)
.then(function (node) {
$scope.target = node;
if (ensureWithinStartNode(node)) {
selectImage(node);
$scope.target.url = mediaHelper.resolveFile(node);
$scope.target.altText = altText;
$scope.openDetailsDialog();
}
},
gotoStartNode);
}
}
$scope.upload = function(v) {
angular.element(".umb-file-dropzone-directive .file-select").click();
};
@@ -107,7 +147,7 @@ angular.module("umbraco")
if (folder.id > 0) {
entityResource.getAncestors(folder.id, "media")
.then(function(anc) {
.then(function(anc) {
$scope.path = _.filter(anc,
function(f) {
return f.path.indexOf($scope.startNodeId) !== -1;
@@ -218,32 +258,6 @@ angular.module("umbraco")
$scope.gotoFolder({ id: $scope.startNodeId, name: "Media", icon: "icon-folder" });
}
//default root item
if (!$scope.target) {
if ($scope.lastOpenedNode && $scope.lastOpenedNode !== -1) {
entityResource.getById($scope.lastOpenedNode, "media")
.then(ensureWithinStartNode, gotoStartNode);
} else {
gotoStartNode();
}
} else {
//if a target is specified, go look it up - generally this target will just contain ids not the actual full
//media object so we need to look it up
var id = $scope.target.udi ? $scope.target.udi : $scope.target.id
var altText = $scope.target.altText;
mediaResource.getById(id)
.then(function(node) {
$scope.target = node;
if (ensureWithinStartNode(node)) {
selectImage(node);
$scope.target.url = mediaHelper.resolveFile(node);
$scope.target.altText = altText;
$scope.openDetailsDialog();
}
},
gotoStartNode);
}
$scope.openDetailsDialog = function() {
$scope.mediaPickerDetailsOverlay = {};
@@ -368,4 +382,7 @@ angular.module("umbraco")
}
}
}
onInit();
});
@@ -48,14 +48,14 @@
<span class="umb-breadcrumbs__seperator">&#47;</span>
</li>
<li class="umb-breadcrumbs__ancestor" ng-if="!lockedFolder">
<li class="umb-breadcrumbs__ancestor" ng-show="!lockedFolder">
<a href ng-hide="showFolderInput" ng-click="showFolderInput = true">
<i class="icon icon-add small"></i>
</a>
<input
type="text"
class="input-foldername input-mini inline"
class="umb-breadcrumbs__add-ancestor"
ng-show="showFolderInput"
ng-model="newFolderName"
ng-keydown="enterSubmitFolder($event)"
@@ -98,7 +98,7 @@
<localize key="contentTypeEditor_inheritedFrom"></localize> {{ tab.inheritedFromName }}
<span ng-repeat="contentTypeName in tab.parentTabContentTypeNames">
{{ contentTypeName }}
<a href="#/settings/documentTypes/edit/{{tab.contentTypeId}}">{{ contentTypeName }}</a>
<span ng-if="!$last">, </span>
</span>
</div>
@@ -1,5 +1,5 @@
<h3>Hours of Umbraco training videos are only a click away</h3>
<p>Want to master Umbraco? Spend a couple of minutes learning some best practices by watching one of these videos about using Umbraco. And visit <a class="btn-link -underline" href="http://umbraco.tv" target="_blank">umbraco.tv</a> for even more Umbraco videos</p>
<p>Want to master Umbraco? Spend a couple of minutes learning some best practices by watching one of these videos about using Umbraco, then visit <a class="btn-link -underline" href="http://umbraco.tv" target="_blank">umbraco.tv</a> for even more Umbraco videos.</p>
<div class="row-fluid"
ng-init="init('http://umbraco.tv/videos/developer/chapterrss?sort=no')"
@@ -7,14 +7,12 @@
<ul class="thumbnails" >
<li class="span2" ng-repeat="video in videos">
<div class="thumbnail" style="margin-right: 20px; padding: 20px;">
<a class="btn-link -underline" target="_blank" href="{{video.link}}" title="{{video.title}}">
<img ng-src="{{video.thumbnail}}" alt="{{video.title}}">
</a>
<a target="_blank" href="{{video.link}}" title="{{video.title}}">
<div style="font-weight: bold; text-align: center; margin: 20px 0 0;">{{video.title}}</div>
</a>
</div>
<a class="btn-link" target="_blank" href="{{video.link}}" title="{{video.title}}">
<div class="thumbnail" style="margin-right: 20px; padding: 20px;">
<img ng-src="{{video.thumbnail}}" alt="{{video.title}}">
<div style="font-weight: bold; text-align: center; margin: 20px 0 0;">{{video.title}}</div>
</div>
</a>
</li>
</ul>
</div>
@@ -19,7 +19,7 @@
<button
ng-if="vm.dashboard.urlTrackerDisabled === true"
type="button"
class="umb-era-button umb-button--s -blue"
class="umb-era-button umb-button--s -green"
ng-click="vm.enableUrlTracker()">
<span><localize key="redirectUrls_enableUrlTracker">Enable URL Tracker</localize></span>
</button>
@@ -172,9 +172,7 @@
notificationsService.error(value);
});
});
});
}
}];
}
@@ -185,34 +183,24 @@
//we are creating so get an empty data type item
contentTypeResource.getScaffold($routeParams.id)
.then(function (dt) {
init(dt);
vm.page.loading = false;
});
.then(function(dt) {
init(dt);
vm.page.loading = false;
});
}
else {
loadDocumentType();
}
function loadDocumentType() {
vm.page.loading = true;
contentTypeResource.getById($routeParams.id).then(function (dt) {
init(dt);
syncTreeNode(vm.contentType, dt.path, true);
vm.page.loading = false;
});
}
/* ---------- SAVE ---------- */
function save() {
@@ -241,7 +229,6 @@
vm.contentType.id = savedContentType.id;
vm.contentType.groups.forEach(function(group) {
if (!group.name) return;
var k = 0;
while (k < savedContentType.groups.length && savedContentType.groups[k].name != group.name)
k++;
@@ -249,13 +236,11 @@
group.id = 0;
return;
}
var savedGroup = savedContentType.groups[k];
if (!group.id) group.id = savedGroup.id;
group.properties.forEach(function (property) {
if (property.id || !property.alias) return;
k = 0;
while (k < savedGroup.properties.length && savedGroup.properties[k].alias != property.alias)
k++;
@@ -263,7 +248,6 @@
property.id = 0;
return;
}
var savedProperty = savedGroup.properties[k];
property.id = savedProperty.id;
});
@@ -289,13 +273,10 @@
});
}
vm.page.saveButtonState = "error";
deferred.reject(err);
});
return deferred.promise;
}
}
function init(contentType) {
@@ -343,12 +324,11 @@
function getDataTypeDetails(property) {
if (property.propertyState !== "init") {
dataTypeResource.getById(property.dataTypeId)
.then(function (dataType) {
property.dataTypeIcon = dataType.icon;
property.dataTypeName = dataType.name;
});
.then(function(dataType) {
property.dataTypeIcon = dataType.icon;
property.dataTypeName = dataType.name;
});
}
}
@@ -369,7 +349,6 @@
eventsService.unsubscribe(evts[e]);
}
});
}
angular.module("umbraco").controller("Umbraco.Editors.DocumentTypes.EditController", DocumentTypesEditController);
@@ -0,0 +1,12 @@
<div>
<input name="numberField" class="umb-editor umb-number"
type="number"
ng-model="model.value"
val-server="value"
min="0"
max="500"
fix-number />
<span class="help-inline" val-msg-for="numberField" val-toggle-msg="number">Not a number</span>
<span class="help-inline" val-msg-for="numberField" val-toggle-msg="valServer">{{propertyForm.requiredField.errorMsg}}</span>
</div>
@@ -1,25 +1,131 @@
function ColorPickerController($scope) {
$scope.toggleItem = function (color) {
if ($scope.model.value == color) {
$scope.model.value = "";
//this is required to re-validate
$scope.propertyForm.modelValue.$setViewValue($scope.model.value);
}
else {
$scope.model.value = color;
//this is required to re-validate
$scope.propertyForm.modelValue.$setViewValue($scope.model.value);
}
};
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.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 {
// select
$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);
};
// Method required by the valPropertyValidator directive (returns true if the property editor has at least one color selected)
$scope.validateMandatory = function () {
$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: !$scope.model.validation.mandatory || ($scope.model.value != null && $scope.model.value != ""),
isValid: isValid,
errorMsg: "Value cannot be empty",
errorKey: "required"
};
}
$scope.isConfigured = $scope.model.config && $scope.model.config.items && _.keys($scope.model.config.items).length > 0;
$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";
}
}
angular.module("umbraco").controller("Umbraco.PropertyEditors.ColorPickerController", ColorPickerController);
@@ -5,10 +5,10 @@
</div>
<ul class="thumbnails color-picker">
<li ng-repeat="(key, val) in model.config.items" ng-class="{active: model.value === val}">
<a ng-click="toggleItem(val)" class="thumbnail" hex-bg-color="{{val}}">
</a>
<li ng-repeat="(key, val) in model.config.items" ng-class="{active: isActiveColor(val)}">
<a ng-click="toggleItem(val)" class="thumbnail" hex-bg-color="{{val.value}}">
</a>
<span class="color-label" ng-if="model.useLabel" ng-bind="val.label"></span>
</li>
</ul>
@@ -1,12 +1,13 @@
<div ng-controller="Umbraco.PrevalueEditors.MultiColorPickerController">
<div class="control-group color-picker-preval">
<input name="newColor" type="hidden" />
<label for="newColor" val-highlight="hasError">#{{newColor}}</label>
<input name="newLabel" type="text" ng-model="newLabel" class="umb-editor color-label" placeholder="Label" />
<button class="btn add" ng-click="add($event)"><localize key="general_add">Add</localize></button>
<label for="newColor" val-highlight="hasError">{{newColor}}</label>
</div>
<div class="control-group color-picker-preval" ng-repeat="item in model.value">
<div class="thumbnail span1" hex-bg-color="{{item.value}}" bg-orig="transparent"></div>
<pre>{{item.value}}</pre>
<div class="color-picker-prediv"><pre>#{{item.value}} - {{item.label}}</pre></div>
<button class="btn btn-danger" ng-click="remove(item, $event)"><localize key="general_remove">Remove</localize></button>
</div>
</div>
@@ -2,15 +2,17 @@
function ($scope, $timeout, assetsService, angularHelper, $element) {
//NOTE: We need to make each color an object, not just a string because you cannot 2-way bind to a primitive.
var defaultColor = "000000";
var defaultLabel = null;
$scope.newColor = defaultColor;
$scope.newLavel = defaultLabel;
$scope.hasError = false;
assetsService.load([
//"lib/spectrum/tinycolor.js",
"lib/spectrum/spectrum.js"
"lib/spectrum/spectrum.js"
], $scope).then(function () {
var elem = $element.find("input");
var elem = $element.find("input[name='newColor']");
elem.spectrum({
color: null,
showInitial: false,
@@ -21,7 +23,7 @@
clickoutFiresChange: true,
hide: function (color) {
//show the add butotn
$element.find(".btn.add").show();
$element.find(".btn.add").show();
},
change: function (color) {
angularHelper.safeApply($scope, function () {
@@ -39,21 +41,41 @@
//make an array from the dictionary
var items = [];
for (var i in $scope.model.value) {
items.push({
value: $scope.model.value[i],
id: i
});
var oldValue = $scope.model.value[i];
if (oldValue.hasOwnProperty("value")) {
items.push({
value: oldValue.value,
label: oldValue.label,
id: i
});
} else {
items.push({
value: oldValue,
label: oldValue,
id: i
});
}
}
//now make the editor model the array
$scope.model.value = items;
}
// ensure labels
for (var i = 0; i < $scope.model.value.length; i++) {
var item = $scope.model.value[i];
item.label = item.hasOwnProperty("label") ? item.label : item.value;
}
function validLabel(label) {
return label !== null && typeof label !== "undefined" && label !== "" && label.length && label.length > 0;
}
$scope.remove = function (item, evt) {
evt.preventDefault();
$scope.model.value = _.reject($scope.model.value, function (x) {
return x.value === item.value;
return x.value === item.value && x.label === item.label;
});
};
@@ -63,15 +85,15 @@
evt.preventDefault();
if ($scope.newColor) {
var newLabel = validLabel($scope.newLabel) ? $scope.newLabel : $scope.newColor;
var exists = _.find($scope.model.value, function(item) {
return item.value.toUpperCase() == $scope.newColor.toUpperCase();
return item.value.toUpperCase() === $scope.newColor.toUpperCase() || item.label.toUpperCase() === newLabel.toUpperCase();
});
if (!exists) {
$scope.model.value.push({ value: $scope.newColor });
//$scope.newColor = defaultColor;
// set colorpicker to default color
//var elem = $element.find("input");
//elem.spectrum("set", $scope.newColor);
$scope.model.value.push({
value: $scope.newColor,
label: newLabel
});
$scope.hasError = false;
return;
}
@@ -1,7 +1,7 @@
//this controller simply tells the dialogs service to open a mediaPicker window
//with a specified callback, this callback will receive an object with a selection on it
function contentPickerController($scope, entityResource, editorState, iconHelper, $routeParams, angularHelper, navigationService, $location, miniEditorHelper) {
function contentPickerController($scope, entityResource, editorState, iconHelper, $routeParams, angularHelper, navigationService, $location, miniEditorHelper, localizationService) {
var unsubscribe;
@@ -154,7 +154,6 @@ function contentPickerController($scope, entityResource, editorState, iconHelper
}
}
if ($routeParams.section === "settings" && $routeParams.tree === "documentTypes") {
//if the content-picker is being rendered inside the document-type editor, we don't need to process the startnode query
dialogOptions.startNodeId = -1;
@@ -287,8 +286,12 @@ function contentPickerController($scope, entityResource, editorState, iconHelper
entityResource.getUrl(entity.id, entityType).then(function(data){
// update url
angular.forEach($scope.renderModel, function(item){
if(item.id === entity.id) {
item.url = data;
if (item.id === entity.id) {
if (entity.trashed) {
item.url = localizationService.dictionary.general_recycleBin;
} else {
item.url = data;
}
}
});
});
@@ -330,6 +333,7 @@ function contentPickerController($scope, entityResource, editorState, iconHelper
"icon": item.icon,
"path": item.path,
"url": item.url,
"trashed": item.trashed,
"published": (item.metaData && item.metaData.IsPublished === false && entityType === "Document") ? false : true
// only content supports published/unpublished content so we set everything else to published so the UI looks correct
});
@@ -1,5 +1,8 @@
<div ng-controller="Umbraco.PropertyEditors.ContentPickerController" class="umb-editor umb-contentpicker">
<p ng-if="(renderModel|filter:{trashed:true}).length == 1"><localize key="contentPicker_pickedTrashedItem"></localize></p>
<p ng-if="(renderModel|filter:{trashed:true}).length > 1"><localize key="contentPicker_pickedTrashedItems"></localize></p>
<ng-form name="contentPickerForm">
<div ui-sortable="sortableOptions" ng-model="renderModel">
@@ -8,6 +8,6 @@
val-server="value" />
<span class="help-inline" val-msg-for="textbox" val-toggle-msg="required"><localize key="general_required">Required</localize></span>
<span class="help-inline" val-msg-for="textbox" val-toggle-msg="valEmail"><localize key="valiation_invalidEmail">Invalid email</localize></span>
<span class="help-inline" val-msg-for="textbox" val-toggle-msg="valEmail"><localize key="validation_invalidEmail">Invalid email</localize></span>
<span class="help-inline" val-msg-for="textbox" val-toggle-msg="valServer"></span>
</div>
@@ -48,14 +48,18 @@
<a href ng-click="scaleDown(currentCell)">
<i class="icon icon-remove"></i>
</a>
{{currentCell.grid}}
{{currentCell.grid}}
<a href ng-click="scaleUp(currentCell, availableRowSpace, true)">
<i class="icon icon-add"></i>
</a>
</div>
</umb-control-group>
<umb-control-group label="@grid_maxItems" description="@grid_maxItemsDescription">
<input type="number" ng-model="currentCell.maxItems" class="umb-editor-tiny" placeholder="Max" min="0" />
</umb-control-group>
<umb-control-group hide-label="true">
<umb-control-group hide-label="true">
<i class="icon-delete red"></i>
<a class="btn btn-small btn-link" href="" ng-click="deleteArea(currentCell, currentRow)">
<localize key="general_delete" class="ng-isolate-scope ng-scope">Delete</localize>
@@ -81,6 +81,7 @@ angular.module("umbraco")
var notIncludedRte = [];
var cancelMove = false;
var startingArea;
$scope.sortableOptionsCell = {
distance: 10,
@@ -112,9 +113,11 @@ angular.module("umbraco")
},
over: function (event, ui) {
var allowedEditors = $(event.target).scope().area.allowed;
var area = $(event.target).scope().area;
var allowedEditors = area.allowed;
if ($.inArray(ui.item.scope().control.editor.alias, allowedEditors) < 0 && allowedEditors) {
if (($.inArray(ui.item.scope().control.editor.alias, allowedEditors) < 0 && allowedEditors) ||
(startingArea != area && area.maxItems != '' && area.maxItems > 0 && area.maxItems < area.controls.length + 1)) {
$scope.$apply(function () {
$(event.target).scope().area.dropNotAllowed = true;
@@ -168,6 +171,10 @@ angular.module("umbraco")
start: function (e, ui) {
//Get the starting area for reference
var area = $(e.target).scope().area;
startingArea = area;
// fade out control when sorting
ui.item.context.style.display = "block";
ui.item.context.style.opacity = "0.5";
@@ -224,7 +224,7 @@
<!-- Controls repeat end -->
<!-- if area is empty tools -->
<div class="umb-grid-add-more-content" ng-if="area.controls.length > 0 && !sortMode">
<div class="umb-grid-add-more-content" ng-if="area.controls.length > 0 && !sortMode && (area.maxItems == undefined || area.maxItems == '' || area.maxItems == 0 || area.maxItems > area.controls.length)">
<div class="cell-tools-add -bar newbtn" ng-click="openEditorOverlay($event, area, 0, area.$uniqueId);"><localize key="grid_addElement" /></div>
</div>
@@ -65,7 +65,9 @@
ng-repeat="area in layout.areas | filter:zeroWidthFilter"
ng-style="{width: percentage(area.grid) + '%', 'max-width': '100%'}">
<div class="preview-cell"></div>
<div class="preview-cell">
<p style="font-size: 6px; line-height: 8px; text-align: center" ng-show="area.maxItems > 0">{{area.maxItems}}</p>
</div>
</div>
</div>
</div>
@@ -1,7 +1,7 @@
//this controller simply tells the dialogs service to open a mediaPicker window
//with a specified callback, this callback will receive an object with a selection on it
angular.module('umbraco').controller("Umbraco.PropertyEditors.MediaPickerController",
function ($rootScope, $scope, dialogService, entityResource, mediaResource, mediaHelper, $timeout, userService, $location) {
function ($rootScope, $scope, dialogService, entityResource, mediaResource, mediaHelper, $timeout, userService, $location, localizationService) {
//check the pre-values for multi-picker
var multiPicker = $scope.model.config.multiPicker && $scope.model.config.multiPicker !== '0' ? true : false;
@@ -26,17 +26,47 @@ angular.module('umbraco').controller("Umbraco.PropertyEditors.MediaPickerControl
// the mediaResource has server side auth configured for which the user must have
// access to the media section, if they don't they'll get auth errors. The entityResource
// acts differently in that it allows access if the user has access to any of the apps that
// might require it's use. Therefore we need to use the metatData property to get at the thumbnail
// might require it's use. Therefore we need to use the metaData property to get at the thumbnail
// value.
entityResource.getByIds(ids, "Media").then(function (medias) {
entityResource.getByIds(ids, "Media").then(function(medias) {
_.each(medias, function (media, i) {
// The service only returns item results for ids that exist (deleted items are silently ignored).
// This results in the picked items value to be set to contain only ids of picked items that could actually be found.
// Since a referenced item could potentially be restored later on, instead of changing the selected values here based
// on whether the items exist during a save event - we should keep "placeholder" items for picked items that currently
// could not be fetched. This will preserve references and ensure that the state of an item does not differ depending
// on whether it is simply resaved or not.
// This is done by remapping the int/guid ids into a new array of items, where we create "Deleted item" placeholders
// when there is no match for a selected id. This will ensure that the values being set on save, are the same as before.
medias = _.map(ids,
function(id) {
var found = _.find(medias,
function(m) {
// We could use coercion (two ='s) here .. but not sure if this works equally well in all browsers and
// it's prone to someone "fixing" it at some point without knowing the effects. Rather use toString()
// compares and be completely sure it works.
return m.udi.toString() === id.toString() || m.id.toString() === id.toString();
});
if (found) {
return found;
} else {
return {
name: localizationService.dictionary.mediaPicker_deletedItem,
id: $scope.model.config.idType !== "udi" ? id : null,
udi: $scope.model.config.idType === "udi" ? id : null,
icon: "icon-picture",
thumbnail: null,
trashed: true
};
}
});
//only show non-trashed items
if (media.parentId >= -1) {
if (!media.thumbnail) {
_.each(medias,
function(media, i) {
// if there is no thumbnail, try getting one if the media is not a placeholder item
if (!media.thumbnail && media.id && media.metaData) {
media.thumbnail = mediaHelper.resolveFileFromEntity(media, true);
}
@@ -44,12 +74,10 @@ angular.module('umbraco').controller("Umbraco.PropertyEditors.MediaPickerControl
if ($scope.model.config.idType === "udi") {
$scope.ids.push(media.udi);
}
else {
} else {
$scope.ids.push(media.id);
}
}
});
});
$scope.sync();
});
@@ -82,8 +110,8 @@ angular.module('umbraco').controller("Umbraco.PropertyEditors.MediaPickerControl
submit: function(model) {
_.each(model.selectedImages, function(media, i) {
if (!media.thumbnail) {
// if there is no thumbnail, try getting one if the media is not a placeholder item
if (!media.thumbnail && media.id && media.metaData) {
media.thumbnail = mediaHelper.resolveFileFromEntity(media, true);
}
@@ -101,10 +129,8 @@ angular.module('umbraco').controller("Umbraco.PropertyEditors.MediaPickerControl
$scope.mediaPickerOverlay.show = false;
$scope.mediaPickerOverlay = null;
}
};
};
$scope.sortableOptions = {
@@ -142,5 +168,4 @@ angular.module('umbraco').controller("Umbraco.PropertyEditors.MediaPickerControl
//update the display val again if it has changed from the server
setupViewModel();
};
});
@@ -1,47 +1,47 @@
<div class="umb-editor umb-mediapicker" ng-controller="Umbraco.PropertyEditors.MediaPickerController">
<ul ui-sortable="sortableOptions" ng-model="images" class="umb-sortable-thumbnails">
<li style="width: 120px; height: 100px; overflow: hidden;" ng-repeat="image in images">
<p ng-if="(images|filter:{trashed:true}).length == 1"><localize key="mediaPicker_pickedTrashedItem"></localize></p>
<p ng-if="(images|filter:{trashed:true}).length > 1"><localize key="mediaPicker_pickedTrashedItems"></localize></p>
<!-- IMAGE -->
<img ng-src="{{image.thumbnail}}" alt="" ng-show="image.thumbnail" title="{{image.name}}" />
<div class="flex error">
<ul ui-sortable="sortableOptions" ng-model="images" class="umb-sortable-thumbnails">
<li style="width: 120px; height: 100px; overflow: hidden;" ng-repeat="image in images">
<!-- SVG -->
<img ng-if="image.metaData.umbracoExtension.Value === 'svg'" ng-src="{{image.metaData.umbracoFile.Value}}" alt="" title="{{image.name}}" />
<img ng-if="image.extension === 'svg'" ng-src="{{image.file}}" alt="" />
<!-- IMAGE -->
<img ng-class="{'trashed': image.trashed}" ng-src="{{image.thumbnail}}" alt="" ng-show="image.thumbnail" title="{{image.trashed ? 'Trashed: ' + image.name : image.name}}" />
<!-- FILE -->
<span class="umb-icon-holder" ng-hide="image.thumbnail || image.metaData.umbracoExtension.Value === 'svg' || image.extension === 'svg'">
<i class="icon {{image.icon}} large"></i>
<small>{{image.name}}</small>
</span>
<!-- SVG -->
<img ng-class="{'trashed': image.trashed}" ng-if="image.metaData.umbracoExtension.Value === 'svg'" ng-src="{{image.metaData.umbracoFile.Value}}" alt="" title="{{image.trashed ? 'Trashed: ' + image.name : image.name}}" />
<img ng-class="{'trashed': image.trashed}" ng-if="image.extension === 'svg'" ng-src="{{image.file}}" alt="" />
<div class="umb-sortable-thumbnails__actions">
<a class="umb-sortable-thumbnails__action" href="" ng-click="goToItem(image)">
<i class="icon icon-edit"></i>
</a>
<a class="umb-sortable-thumbnails__action -red" href="" ng-click="remove($index)">
<i class="icon icon-delete"></i>
</a>
</div>
<!-- FILE -->
<span class="umb-icon-holder" ng-hide="image.thumbnail || image.metaData.umbracoExtension.Value === 'svg' || image.extension === 'svg'">
<i class="icon {{image.icon}} large"></i>
<small>{{image.name}}</small>
</span>
</li>
</ul>
<div class="umb-sortable-thumbnails__actions">
<a class="umb-sortable-thumbnails__action" href="" ng-click="goToItem(image)">
<i class="icon icon-edit"></i>
</a>
<a class="umb-sortable-thumbnails__action -red" href="" ng-click="remove($index)">
<i class="icon icon-delete"></i>
</a>
</div>
</li>
<ul class="umb-sortable-thumbnails" ng-if="showAdd()">
<li style="border: none">
<a href="#" class="add-link" ng-click="add()" prevent-default>
<i class="icon icon-add large"></i>
</a>
</li>
</ul>
</ul>
<a href="#" class="add-link" ng-click="add()" ng-class="{'add-link-square': images.length === 0}" ng-if="showAdd()" prevent-default>
<i class="icon icon-add large"></i>
</a>
</div>
<umb-overlay
ng-if="mediaPickerOverlay.show"
model="mediaPickerOverlay"
position="right"
view="mediaPickerOverlay.view">
</umb-overlay>
<umb-overlay
ng-if="mediaPickerOverlay.show"
model="mediaPickerOverlay"
position="right"
view="mediaPickerOverlay.view">
</umb-overlay>
</div>
@@ -86,6 +86,10 @@
};
$scope.add = function ($event) {
if (!angular.isArray($scope.model.value)) {
$scope.model.value = [];
}
if ($scope.newCaption == "") {
$scope.hasError = true;
} else {
@@ -76,6 +76,7 @@ angular.module("umbraco").controller("Umbraco.PrevalueEditors.RteController",
icon.isCustom = false;
break;
case "styleselect":
case "fontsizeselect":
icon.name = "icon-list";
icon.isCustom = true;
break;
@@ -1,37 +1,42 @@
function textboxController($scope) {
// macro parameter editor doesn't contains a config object,
// so we create a new one to hold any properties
// so we create a new one to hold any properties
if (!$scope.model.config) {
$scope.model.config = {};
}
if (!$scope.model.config.maxChars) {
$scope.model.config.maxChars = false;
}
$scope.model.maxlength = false;
if ($scope.model.config && $scope.model.config.maxChars) {
$scope.model.maxlength = true;
if($scope.model.value == undefined) {
}
if (!$scope.model.config.maxChars) {
// 500 is the maximum number that can be stored
// in the database, so set it to the max, even
// if no max is specified in the config
$scope.model.config.maxChars = 500;
}
if ($scope.model.maxlength) {
if ($scope.model.value === undefined) {
$scope.model.count = ($scope.model.config.maxChars * 1);
} else {
$scope.model.count = ($scope.model.config.maxChars * 1) - $scope.model.value.length;
}
}
$scope.model.change = function() {
$scope.model.change = function () {
if ($scope.model.config && $scope.model.config.maxChars) {
if($scope.model.value == undefined) {
if ($scope.model.value === undefined) {
$scope.model.count = ($scope.model.config.maxChars * 1);
} else {
$scope.model.count = ($scope.model.config.maxChars * 1) - $scope.model.value.length;
}
if($scope.model.count < 0) {
if ($scope.model.count < 0) {
$scope.model.value = $scope.model.value.substring(0, ($scope.model.config.maxChars * 1));
$scope.model.count = 0;
}
}
}
}
angular.module('umbraco').controller("Umbraco.PropertyEditors.textboxController", textboxController);
angular.module('umbraco').controller("Umbraco.PropertyEditors.textboxController", textboxController);
@@ -4,11 +4,11 @@
val-server="value"
ng-required="model.validation.mandatory"
ng-trim="false"
ng-keyup="model.change()" />
ng-keyup="model.change()" />
<span class="help-inline" val-msg-for="textbox" val-toggle-msg="valServer"></span>
<span class="help-inline" val-msg-for="textbox" val-toggle-msg="required"><localize key="general_required">Required</localize></span>
<div class="help" ng-if="model.maxlength">
<strong>{{model.count}}</strong>
<localize key="textbox_characters_left">characters left</localize>
</div>
</div>
<div class="help" ng-if="model.maxlength">
<strong>{{model.count}}</strong>
<localize key="textbox_characters_left">characters left</localize>
</div>
</div>
+10 -11
View File
@@ -127,18 +127,18 @@
<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>
</Reference>
<Reference Include="Examine, Version=0.1.85.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\Examine.0.1.85\lib\net45\Examine.dll</HintPath>
<Reference Include="Examine, Version=0.1.88.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\Examine.0.1.88\lib\net45\Examine.dll</HintPath>
</Reference>
<Reference Include="ICSharpCode.SharpZipLib, Version=0.86.0.518, Culture=neutral, PublicKeyToken=1b03e6acf1164f73, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\SharpZipLib.0.86.0\lib\20\ICSharpCode.SharpZipLib.dll</HintPath>
</Reference>
<Reference Include="ImageProcessor, Version=2.5.3.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\ImageProcessor.2.5.3\lib\net45\ImageProcessor.dll</HintPath>
<Reference Include="ImageProcessor, Version=2.5.6.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\ImageProcessor.2.5.6\lib\net45\ImageProcessor.dll</HintPath>
</Reference>
<Reference Include="ImageProcessor.Web, Version=4.8.3.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\ImageProcessor.Web.4.8.3\lib\net45\ImageProcessor.Web.dll</HintPath>
<Reference Include="ImageProcessor.Web, Version=4.8.7.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\ImageProcessor.Web.4.8.7\lib\net45\ImageProcessor.Web.dll</HintPath>
</Reference>
<Reference Include="log4net, Version=2.0.8.0, Culture=neutral, PublicKeyToken=669e0ddf0bb1aa2a, processorArchitecture=MSIL">
<HintPath>..\packages\log4net.2.0.8\lib\net45-full\log4net.dll</HintPath>
@@ -162,9 +162,8 @@
<HintPath>..\packages\Microsoft.CodeAnalysis.CSharp.1.0.0\lib\net45\Microsoft.CodeAnalysis.CSharp.dll</HintPath>
</Reference>
<Reference Include="Microsoft.CSharp" />
<Reference Include="Microsoft.IO.RecyclableMemoryStream, Version=1.2.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.IO.RecyclableMemoryStream.1.2.1\lib\net45\Microsoft.IO.RecyclableMemoryStream.dll</HintPath>
<Private>True</Private>
<Reference Include="Microsoft.IO.RecyclableMemoryStream, Version=1.2.2.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.IO.RecyclableMemoryStream.1.2.2\lib\net45\Microsoft.IO.RecyclableMemoryStream.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Owin, Version=3.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.Owin.3.1.0\lib\net45\Microsoft.Owin.dll</HintPath>
@@ -1027,9 +1026,9 @@ xcopy "$(ProjectDir)"..\packages\SqlServerCE.4.0.0.1\x86\*.* "$(TargetDir)x86\"
<WebProjectProperties>
<UseIIS>True</UseIIS>
<AutoAssignPort>True</AutoAssignPort>
<DevelopmentServerPort>7720</DevelopmentServerPort>
<DevelopmentServerPort>7770</DevelopmentServerPort>
<DevelopmentServerVPath>/</DevelopmentServerVPath>
<IISUrl>http://localhost:7720</IISUrl>
<IISUrl>http://localhost:7770</IISUrl>
<NTLMAuthentication>False</NTLMAuthentication>
<UseCustomServer>False</UseCustomServer>
<CustomServerUrl>
@@ -771,7 +771,7 @@
<key alias="sortCreationDate">Creation date</key>
<key alias="sortDone">Třídění bylo ukončeno.</key>
<key alias="sortHelp">Abyste nastavili, jak mají být položky seřazeny, přetáhněte jednotlivé z nich nahoru či dolů. Anebo klikněte na hlavičku sloupce pro setřídění celé kolekce</key>
<key alias="sortPleaseWait"><![CDATA[ Čekejte, prosím. Položky jsou tříděny a může to chvíli trvat.<br/> <br/> Během třídění nezavírejte toto okno]]></key>
<key alias="sortPleaseWait"><![CDATA[ Čekejte, prosím. Položky jsou tříděny a může to chvíli trvat.]]></key>
</area>
<area alias="speechBubbles">
<key alias="contentPublishedFailedByEvent">Publikování bylo zrušeno doplňkem třetí strany</key>
+13 -2
View File
@@ -422,7 +422,7 @@
<key alias="showPageOnSend">Hvilken side skal vises etter at skjemaet er sendt</key>
<key alias="size">Størrelse</key>
<key alias="sort">Sorter</key>
<key alias="submit">Submit</key> <!-- TODO: Translate this -->
<key alias="submit">Send</key>
<key alias="type">Type</key>
<key alias="typeToSearch">Søk...</key>
<key alias="up">Opp</key>
@@ -439,6 +439,17 @@
<key alias="yes">Ja</key>
<key alias="folder">Mappe</key>
<key alias="searchResults">Søkeresultater</key>
<key alias="reorder">Sorter</key>
<key alias="reorderDone">Avslutt sortering</key>
<key alias="preview">Eksempel</key>
<key alias="changePassword">Bytt passord</key>
<key alias="to">til</key>
<key alias="listView">Listevisning</key>
<key alias="saving">Lagrer...</key>
<key alias="current">nåværende</key>
<key alias="embed">Innbygging</key>
<key alias="retrieve">Hent</key>
<key alias="selected">valgt</key>
</area>
<area alias="graphicheadline">
<key alias="backgroundcolor">Bakgrunnsfarge</key>
@@ -733,7 +744,7 @@ Vennlig hilsen Umbraco roboten
<key alias="sortCreationDate">Creation date</key>
<key alias="sortDone">Sortering ferdig.</key>
<key alias="sortHelp">Dra elementene opp eller ned for å arrangere dem. Du kan også klikke kolonneoverskriftene for å sortere alt på en gang.</key>
<key alias="sortPleaseWait"><![CDATA[Vennligst vent. Elementene blir sortert, dette kan ta litt tid.<br/> <br/> Ikke lukk dette vinduet under sortering]]></key>
<key alias="sortPleaseWait"><![CDATA[Vennligst vent. Elementene blir sortert, dette kan ta litt tid.]]></key>
</area>
<area alias="speechBubbles">
<key alias="operationFailedHeader">En feil oppsto</key>
@@ -905,7 +905,7 @@
<key alias="sortCreationDate">增添時間</key>
<key alias="sortDone">排序完成。</key>
<key alias="sortHelp">上下拖拽項目或按一下列頭進行排序</key>
<key alias="sortPleaseWait"><![CDATA[ 請稍後。項目正在排序,這需要一點時間。<br/> <br/>排序中請不要關閉視窗。]]></key>
<key alias="sortPleaseWait"><![CDATA[ 請稍後。項目正在排序,這需要一點時間。]]></key>
</area>
<area alias="speechBubbles">
<key alias="validationFailedHeader">驗證</key>
@@ -60,21 +60,29 @@
JObject cfg = contentItem.config;
if(cfg != null)
foreach (JProperty property in cfg.Properties()) {
attrs.Add(property.Name + "='" + property.Value.ToString() + "'");
foreach (JProperty property in cfg.Properties())
{
var propertyValue = HttpUtility.HtmlAttributeEncode(property.Value.ToString());
attrs.Add(property.Name + "=\"" + propertyValue + "\"");
}
JObject style = contentItem.styles;
if (style != null) {
var cssVals = new List<string>();
foreach (JProperty property in style.Properties())
cssVals.Add(property.Name + ":" + property.Value.ToString() + ";");
if (style != null) {
var cssVals = new List<string>();
foreach (JProperty property in style.Properties())
{
var propertyValue = property.Value.ToString();
if (string.IsNullOrWhiteSpace(propertyValue) == false)
{
cssVals.Add(property.Name + ":" + propertyValue + ";");
}
}
if (cssVals.Any())
attrs.Add("style='" + string.Join(" ", cssVals) + "'");
if (cssVals.Any())
attrs.Add("style=\"" + HttpUtility.HtmlAttributeEncode(string.Join(" ", cssVals)) + "\"");
}
return new MvcHtmlString(string.Join(" ", attrs));
}
}
@@ -60,21 +60,29 @@
JObject cfg = contentItem.config;
if(cfg != null)
foreach (JProperty property in cfg.Properties()) {
attrs.Add(property.Name + "='" + property.Value.ToString() + "'");
foreach (JProperty property in cfg.Properties())
{
var propertyValue = HttpUtility.HtmlAttributeEncode(property.Value.ToString());
attrs.Add(property.Name + "=\"" + propertyValue + "\"");
}
JObject style = contentItem.styles;
if (style != null) {
var cssVals = new List<string>();
foreach (JProperty property in style.Properties())
cssVals.Add(property.Name + ":" + property.Value.ToString() + ";");
if (style != null) {
var cssVals = new List<string>();
foreach (JProperty property in style.Properties())
{
var propertyValue = property.Value.ToString();
if (string.IsNullOrWhiteSpace(propertyValue) == false)
{
cssVals.Add(property.Name + ":" + propertyValue + ";");
}
}
if (cssVals.Any())
attrs.Add("style='" + string.Join(" ", cssVals) + "'");
if (cssVals.Any())
attrs.Add("style=\"" + HttpUtility.HtmlAttributeEncode(string.Join(" ", cssVals)) + "\"");
}
return new MvcHtmlString(string.Join(" ", attrs));
}
}
@@ -4,9 +4,13 @@
@if (Model.editor.config.markup != null)
{
string markup = Model.editor.config.markup.ToString();
markup = markup.Replace("#value#", Model.value.ToString());
markup = markup.Replace("#style#", Model.editor.config.style.ToString());
var umbracoHelper = new UmbracoHelper(UmbracoContext.Current);
markup = markup.Replace("#value#", umbracoHelper.ReplaceLineBreaksForHtml(HttpUtility.HtmlEncode(Model.value.ToString())));
if (Model.editor.config.style != null)
{
markup = markup.Replace("#style#", Model.editor.config.style.ToString());
}
<text>
@Html.Raw(markup)
@@ -14,6 +14,7 @@
<plugin name="Filter" type="ImageProcessor.Web.Processors.Filter, ImageProcessor.Web" />
<plugin name="Flip" type="ImageProcessor.Web.Processors.Flip, ImageProcessor.Web" />
<plugin name="Format" type="ImageProcessor.Web.Processors.Format, ImageProcessor.Web" enabled="true" />
<plugin name="Gamma" type="ImageProcessor.Web.Processors.Gamma, ImageProcessor.Web" />
<plugin name="GaussianBlur" type="ImageProcessor.Web.Processors.GaussianBlur, ImageProcessor.Web">
<settings>
<setting key="MaxSize" value="22" />
+5 -5
View File
@@ -4,10 +4,10 @@
<package id="ClientDependency" version="1.9.2" 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.85" targetFramework="net45" />
<package id="ImageProcessor" version="2.5.3" targetFramework="net45" />
<package id="ImageProcessor.Web" version="4.8.3" targetFramework="net45" />
<package id="ImageProcessor.Web.Config" version="2.3.0" targetFramework="net45" />
<package id="Examine" version="0.1.88" targetFramework="net45" />
<package id="ImageProcessor" version="2.5.6" targetFramework="net45" />
<package id="ImageProcessor.Web" version="4.8.7" targetFramework="net45" />
<package id="ImageProcessor.Web.Config" version="2.3.1" targetFramework="net45" />
<package id="log4net" version="2.0.8" targetFramework="net45" />
<package id="Lucene.Net" version="2.9.4.1" targetFramework="net45" />
<package id="Microsoft.AspNet.Identity.Core" version="2.2.1" targetFramework="net45" />
@@ -22,7 +22,7 @@
<package id="Microsoft.CodeAnalysis.Analyzers" version="1.0.0" targetFramework="net45" />
<package id="Microsoft.CodeAnalysis.Common" version="1.0.0" targetFramework="net45" />
<package id="Microsoft.CodeAnalysis.CSharp" version="1.0.0" targetFramework="net45" />
<package id="Microsoft.IO.RecyclableMemoryStream" version="1.2.1" targetFramework="net45" />
<package id="Microsoft.IO.RecyclableMemoryStream" version="1.2.2" targetFramework="net45" />
<package id="Microsoft.Owin" version="3.1.0" targetFramework="net45" />
<package id="Microsoft.Owin.Host.SystemWeb" version="3.1.0" targetFramework="net45" />
<package id="Microsoft.Owin.Security" version="3.1.0" targetFramework="net45" />
+14 -2
View File
@@ -586,7 +586,6 @@
<key alias="sort">Sortér</key>
<key alias="status">Status</key>
<key alias="submit">Indsend</key>
<!-- TODO: Translate this -->
<key alias="type">Type</key>
<key alias="typeToSearch">Skriv for at søge...</key>
<key alias="up">Op</key>
@@ -612,6 +611,7 @@
<key alias="saving">Gemmer...</key>
<key alias="current">nuværende</key>
<key alias="embed">Indlejring</key>
<key alias="retrieve">Hent</key>
<key alias="selected">valgt</key>
</area>
@@ -935,6 +935,15 @@ Mange hilsner fra Umbraco robotten
<area alias="colorpicker">
<key alias="noColors">Du har ikke konfigureret nogen godkendte farver</key>
</area>
<area alias="contentPicker">
<key alias="pickedTrashedItem">Du har valgt et dokument som er slettet eller lagt i papirkurven</key>
<key alias="pickedTrashedItems">Du har valgt dokumenter som er slettede eller lagt i papirkurven</key>
</area>
<area alias="mediaPicker">
<key alias="pickedTrashedItem">Du har valgt et medie som er slettet eller lagt i papirkurven</key>
<key alias="pickedTrashedItems">Du har valgt medier som er slettede eller lagt i papirkurven</key>
<key alias="deletedItem">Slettet medie</key>
</area>
<area alias="relatedlinks">
<key alias="enterExternal">indtast eksternt link</key>
<key alias="chooseInternal">vælg en intern side</key>
@@ -1005,7 +1014,7 @@ Mange hilsner fra Umbraco robotten
<key alias="sortCreationDate">Oprettelsesdato</key>
<key alias="sortDone">Sortering udført</key>
<key alias="sortHelp">Træk de forskellige sider op eller ned for at indstille hvordan de skal arrangeres, eller klik på kolonnehovederne for at sortere hele rækken af sider</key>
<key alias="sortPleaseWait"><![CDATA[Vent venligst mens siderne sorteres. Det kan tage et stykke tid<br/><br/>Luk ikke dette vindue imens]]></key>
<key alias="sortPleaseWait"><![CDATA[Vent venligst mens siderne sorteres. Det kan tage et stykke tid.]]></key>
</area>
<area alias="speechBubbles">
<key alias="operationCancelledHeader">Annulleret</key>
@@ -1251,6 +1260,9 @@ Mange hilsner fra Umbraco robotten
<key alias="chooseDefault">Vælg standard</key>
<key alias="areAdded">er tilføjet</key>
<key alias="maxItems">Maksimalt emner</key>
<key alias="maxItemsDescription">Efterlad blank eller sat til 0 ubegrænset for</key>
</area>
<area alias="contentTypeEditor">
@@ -764,7 +764,7 @@ Wenn Sie sich für Runway entscheiden, können Sie optional Blöcke nutzen, die
<key alias="sortCreationDate">Erstellungsdatum</key>
<key alias="sortDone">Sortierung abgeschlossen.</key>
<key alias="sortHelp">Ziehen Sie die Elemente an ihre gewünschte neue Position.</key>
<key alias="sortPleaseWait">Bitte warten, die Seiten werden sortiert. Das kann einen Moment dauern. Bitte schließen Sie dieses Fenster nicht, bis der Sortiervorgang abgeschlossen ist.</key>
<key alias="sortPleaseWait">Bitte warten, die Seiten werden sortiert. Das kann einen Moment dauern.</key>
</area>
<area alias="speechBubbles">
<key alias="operationFailedHeader">Fehlgeschlagen</key>
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff

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