Compare commits

..

132 Commits

Author SHA1 Message Date
Niels Lyngsoe 92453c4652 fix front-end requirement of umb-checkbox 2019-03-06 11:18:07 +01:00
Shannon Deminick 5ddba3e64e Merge pull request #3851 from umbraco/temp-fix-formdatacollection-3796
Fixes binding of FormDataCollection for GET requests which fixes the …
2019-03-05 13:39:37 +10:00
Niels Lyngsø c72a5c07fe Merge pull request #3464 from BatJan/feature/temp-U4-3463
3463 - Suggestion: Make checkboxes look prettier in checkbox lists
2019-03-04 11:39:08 +01:00
Niels Lyngsoe 409ae99bf7 renaming of umb-form-control to umb-form-check 2019-03-04 10:29:58 +01:00
Jan Skovgaard 969a9c1193 Update radiobuttons view to make use of the umb-radiobutton directive 2019-02-27 09:56:22 +01:00
Jan Skovgaard 3643e170c5 Add radiobutton directive 2019-02-27 09:55:52 +01:00
Jan Skovgaard afc872de5a Refactor checkboxlist to make use of the umbcheckbox directive 2019-02-27 09:40:48 +01:00
Jan Skovgaard 56aef39014 Add checkbox directive 2019-02-27 09:40:25 +01:00
Jan Skovgaard ae07b2b299 Refactor modifiers so they're done on the top level of the block instead 2019-02-26 21:42:24 +01:00
Jan Skovgaard b99cf238e0 Fix order of pseudo selectors to :focus is actually also set on the focused radio button 2019-02-26 21:26:14 +01:00
Jan Skovgaard 68457b7eaf Refactor styling of checkbox and radiobuttons so they're now both "umb-form-control" with modifiers, which makes it easier to reuse especially the checkbox throughout the UI. The umb-editor has been extented to have a item element and a list modfier too. Overall less code too 2019-02-26 21:21:55 +01:00
Jan Skovgaard 24c74676f6 Merge branch 'dev-v7' into feature/temp-U4-3463 2019-02-26 19:45:51 +01:00
Per Søndergaard Jensen ac1ee2fe0c #4428 - Replaced Log.Add calls with AuditService.Add in translations 2019-02-26 11:17:08 +01:00
Skid Vis 4f30dd32f1 Updates link to dev-v8
Was linked to temp8 which no longer exists and results in 404
2019-02-25 17:20:35 +01:00
Sebastiaan Janssen 8f17d6fcd2 Merge branch 'patch-7.13.2' into dev-v7
# Conflicts:
#	src/Umbraco.Web.UI.Client/src/views/propertyeditors/colorpicker/colorpicker.controller.js
2019-02-19 11:22:59 +01:00
SimonHilo 1300389ce6 Skip the check for approved/locked out members if not using Umbracos built-in MembershipProvider (#4607) 2019-02-18 20:49:27 +01:00
Kenn Jacobsen ea8d8ba771 Make the image crop slider move at 66 hertz 2019-02-18 20:39:16 +01:00
Kenn Jacobsen 1eb6ae10c9 Fix the initial zoom offset for new crops in the image cropper 2019-02-18 20:38:11 +01:00
Jan Skovgaard 5d3e1fb95f v7: User history showing even if it's empty (#4524) 2019-02-18 20:36:36 +01:00
Mathieu Deslauriers 62463ecc21 Issue 4634 : Fixed colorpicker unselection condition
When the user remove the selection the model is set to null.
When the user tries to select another value after that, the condition is trying to check the "value" property for a null object.
2019-02-18 14:52:13 +01:00
Rasmus John Pedersen 3a469cdc77 Multi Url Picker fixes (#4527)
*  Fix not being able to save link with only an anchor

* Don't allow Multi Url Picker as a parameter editor
2019-02-14 18:11:44 +01:00
matthew-hair 6665695986 Added null check for context.Identity
Signed-off-by: matthew-hair <matthew.hair@sedgwick.gov>
2019-02-14 12:55:56 +01:00
Kenn Jacobsen 19aae9ffdc Make sure the color picker label is stored on first select (#4325)
(cherry picked from commit 4dd51f645a)
2019-01-30 16:14:09 +01:00
Kenn Jacobsen 4dd51f645a Make sure the color picker label is stored on first select (#4325) 2019-01-30 16:12:50 +01:00
Vigan Shemsiu cca1393f2b Validate both width and height
Make sure to validate both width and height before running "setDimensions();". 

The focus point will not work if we have "img { width: 100%; }" in the stylesheet. 

This pull request will fix the bug.
2019-01-29 22:26:26 +01:00
Kenn Jacobsen 69548aed20 Fix the offset in the crop editor 2019-01-29 22:22:34 +01:00
Damiaan Peeters 7656de693c Add unittest 2019-01-29 22:18:53 +01:00
Damiaan Peeters 4806920179 Do not allow a empty name with for the MemberGroup 2019-01-29 22:18:53 +01:00
Kenn Jacobsen 5637c44f69 Explicitly set the form dirty when toggling a boolean 2019-01-29 17:41:28 +01:00
Sebastiaan Janssen 218995f9e0 Set version to 7.13.2 2019-01-29 17:34:05 +01:00
Kenn Jacobsen 0d167c4f2d Fix callback
(cherry picked from commit 99f0e6c05a)
2019-01-29 14:13:22 +01:00
Kenn Jacobsen d44e0d8664 Set form dirty on color picker value change + update selected item label + clean up unused code
(cherry picked from commit 2c40e46d56)
2019-01-29 14:13:14 +01:00
Kenn Jacobsen 99f0e6c05a Fix callback 2019-01-29 14:11:04 +01:00
Kenn Jacobsen 2c40e46d56 Set form dirty on color picker value change + update selected item label + clean up unused code 2019-01-29 14:11:04 +01:00
Benjamin Carleski 2c3a2b29b2 Obsolete direct hash generation methods, and switch to generic GenerateHash
As noted in https://github.com/umbraco/Umbraco-CMS/issues/4292, using direct hash methods can break compliance when on restricted systems that require FIPS compliance.  This has been addressed in a few commits.  This commit goes further to obsolete methods not previously obsoleted relating to direct hashing calls, and switches a direct call to one of these methods to use the correct, generic GenerateHash.
2019-01-29 12:58:51 +01:00
Jan Skovgaard 94a4e34e0c Make sure to hide the whole state element for screen readers rather than just the icon 2019-01-27 15:32:52 +01:00
Jan Skovgaard 7d42583177 Fix animation 2019-01-27 15:30:02 +01:00
Jan Skovgaard 77a8697ca7 Make sure the border is green when the checkbox is checked and that it's darker gray when it is focused (also while checked) 2019-01-27 15:24:49 +01:00
Jan Skovgaard 7462686778 Add styles and minor refactoring so we no longer use the "wing" icon when a radio button is checked but rather make it look like a readio button 2019-01-27 15:22:37 +01:00
Jan Skovgaard 44d5ce4a2e Include the radiobuttonlist component 2019-01-27 15:21:54 +01:00
Jan Skovgaard 34888f31e6 Place the ul styling in the proper context 2019-01-27 14:50:15 +01:00
Jan Skovgaard 0994aac656 Restructure markup to ensure the label text is properly wrapped and make sure it all aligns nicely on small breakpoints too 2019-01-27 14:38:27 +01:00
Jan Skovgaard 0e0d38be30 Refactor styling of the checkbox so the boxes are now a tad smaller and better aligned with one another and the UI in general 2019-01-27 14:18:41 +01:00
Jan Skovgaard 91735e7e3f Fix bad merge 2019-01-27 14:17:59 +01:00
Jan Skovgaard 0d4b3e4173 Merge branch 'dev-v7' into feature/temp-U4-3463
# Conflicts:
#	src/Umbraco.Web.UI.Client/src/less/components/umb-radiobuttons-list.less
#	src/Umbraco.Web.UI.Client/src/views/propertyeditors/checkboxlist/checkboxlist.html
#	src/Umbraco.Web.UI.Client/src/views/propertyeditors/radiobuttons/radiobuttons.html
2019-01-27 13:31:33 +01:00
Sebastiaan Janssen d174499e50 Fixes #4260 incorrect permissions required for Notifications sign up 2019-01-27 13:30:44 +01:00
Kenn Jacobsen df20feb703 Make cache properties on PublishedContentRequest public 2019-01-27 10:39:34 +01:00
Nathan Woulfe a4c5b7118d check for editorstate.current before attempting to access properties object 2019-01-26 17:33:45 +01:00
Ronald Barendse 52a56c8852 Only add TLS 1.2 if explicit protocols are defined 2019-01-26 17:09:47 +01:00
Ronald Barendse 7a2f09643a Changed health check to indicate HTTPS endpoint connectivity using TLS 1.2 2019-01-26 15:30:47 +01:00
Paul Seal c9819b2d89 - disabled the duplicated community health checks (#4175) 2019-01-26 15:01:03 +01:00
Christian Alkærsig 7acafe67a4 Delete template2.cshtml
Auto-generated test file
2019-01-23 00:28:21 +01:00
Alkaersig 9eb2b28232 Added (Doctype) Name and Description to PublishedContentType 2019-01-23 00:28:21 +01:00
Paul Seal 832ec68140 - tls check to check if the site is set up to use at least TLS 1.2 for outgoing connections.
- added translations for all languages which have a healthcheck section in the language file.
2019-01-23 00:11:35 +01:00
Bjarne Fyrstenborg d8f0af1a94 Fix plural localization 2019-01-22 22:59:52 +01:00
Kenn Jacobsen a8d5bd6d1f Don't let the users empty the recycle bin without delete permissions (#3699) 2019-01-22 22:05:12 +01:00
Kenn Jacobsen e252a0849b Add "default empty" prevalue to date and datetime 2019-01-22 21:58:17 +01:00
Sebastiaan Janssen ba4b84d7f4 Fixes #4166 - Outgoing connections sometimes fail because they require TLS 1.2 2019-01-21 11:10:01 +01:00
Rasmus John Pedersen e1c9b1818e Add Multi Url Picker to core (#2323) 2019-01-20 21:12:00 +01:00
Abi Noda 76bece07ef add pull reminders badge to readme 2019-01-20 21:10:02 +01:00
Dave Woestenborghs 7729dc946e Fix 4058 : restore from recycle bin when item has multiple relations (#4073) 2019-01-20 20:47:13 +01:00
Kenn Jacobsen 5b285f71fa Remove hardcoded "Root" when restoring to tree root 2019-01-18 14:39:54 +01:00
Callum Whyte e60417925b Consistency is king! Fix up " vs ' in installer service facts array 2019-01-17 15:41:44 +01:00
Callum Whyte 5a78c000a0 Correcting punctuation in installer screen facts 2019-01-17 15:41:44 +01:00
Callum Whyte 54faeee837 Updating number of active Umbraco sites in installer screen facts 2019-01-17 15:41:44 +01:00
Nicholas-Westby cefa2c9040 Typo ("thist"). 2019-01-17 15:34:52 +01:00
Kenn Jacobsen 77cf071e04 Add "Move" option for deleted items in the media tree (#3914) 2019-01-17 12:20:13 +01:00
Sebastiaan Janssen 0d0179cb47 Use constants in upgrade migration 2019-01-17 12:14:17 +01:00
Sebastiaan Janssen f7671ec9a7 Fixes #4071 - Error executing scheduled task - This instance has already started one or more requests. 2019-01-15 08:39:43 +01:00
Kenn Jacobsen b9430158ce Move member group picker property data store from NVarchar to NText (#3712) 2019-01-14 09:25:59 +01:00
Kenn Jacobsen db8954e0a5 Verify that the current member is approved and not locked out (#3588) 2019-01-14 08:52:02 +01:00
Sebastiaan Janssen 05f1a24caf Fix duplicate IIS Express settings 2019-01-14 08:28:58 +01:00
Kenn Jacobsen b08e922600 Only allow setting up scheduled publishing if the user has the correct permissions to do so 2019-01-14 08:21:58 +01:00
Kenn Jacobsen fbf60fbac4 Don't add the "Notification" tree menu item if Umbraco can't send emails 2019-01-14 08:13:10 +01:00
Kenn Jacobsen 941baf09ce Fix linkpicker overlay issues (#3718) 2019-01-13 16:17:44 +01:00
Anders Bjerner be44741bf9 Localized parts of the codefile and template resources (#3495) 2019-01-13 15:58:31 +01:00
christophnz 282ac2b9c5 Added 2 HtmlHelper extension methods for rendering RelatedLinks, including Unit tests 2019-01-13 15:17:13 +01:00
Jannik Anker 1224f68297 Issue 3018 - non-admin users cannot create groups (derpness cleanup) 2019-01-13 15:13:26 +01:00
Jannik Anker 8d1733fd12 Issue 3018 - non-admin users cannot create groups 2019-01-13 15:13:26 +01:00
Bjarne Fyrstenborg 1213551ca9 Only show extension if media item has a file
(cherry picked from commit 168febae24)
2019-01-13 14:55:44 +01:00
Steve f620d0deca Fixes #4016 unpublished content styling in list view 2019-01-13 14:43:24 +01:00
Kenn Jacobsen d1cfe84723 Set the form dirty when changing focal point and editing crops 2019-01-13 14:01:11 +01:00
Kenn Jacobsen cd6cdcfda4 Visualize image transparency in upload and image cropper thumbnails (#4050) 2019-01-13 13:54:30 +01:00
Bjarne Fyrstenborg 2ebd7a077c Fix placeholder text when empty alias input after generating alias (#4032)
(cherry picked from commit c619b79276)
2019-01-13 13:16:00 +01:00
Sebastiaan Janssen 9e33581391 Merge branch 'patch-7.13.1' into dev-v7
# Conflicts:
#	src/SolutionInfo.cs
#	src/Umbraco.Core/Configuration/UmbracoVersion.cs
2019-01-11 09:53:50 +01:00
Quan Tran 59349dd355 Fix - refine code 2019-01-10 19:35:51 +01:00
Quan Tran 4170faf76e add null checking 2019-01-10 19:35:51 +01:00
Sebastian Hoffback cc13b99787 Removed already deleted file canvasdesigner.panel.js from canvasdesigner.loader.js 2019-01-10 19:32:59 +01:00
Sebastiaan Janssen d69f0fe9dd #3993 Move color picker fix to correct method and update backwards compatibility test 2019-01-10 15:35:48 +01:00
Kenn Jacobsen d2baf03119 Fix content picker dirty checking (#4003)
(cherry picked from commit d41dbce601)
2019-01-10 09:54:39 +01:00
Sebastiaan Janssen ff085c97ce Revert "Added eslintignore file"
This reverts commit 673735c2fe.
2019-01-09 14:57:17 +01:00
Kenn Jacobsen d41dbce601 Fix content picker dirty checking (#4003) 2019-01-09 11:20:34 +01:00
Sebastiaan Janssen ec60ba142a Fixes #3993 Recent changes in color picker has caused incompatibility with existing picker 2019-01-09 10:50:27 +01:00
Kenn Jacobsen a16e31c671 Safeguard the tags value converter against empty tags
(cherry picked from commit cc6c16894c)
2019-01-08 21:52:58 +01:00
Floris Robbemont d19a23eec6 Fix for wrong sorting overload in MediaService (#3948)
(cherry picked from commit 0852b20b31)
2019-01-08 21:50:58 +01:00
Sebastiaan Janssen 0f61de8bcd Bumps version to 7.14.0 2019-01-08 21:49:17 +01:00
Sebastiaan Janssen 5b17072d55 Bump version to 7.13.1 2019-01-08 21:45:34 +01:00
Sebastiaan Janssen 51875539b9 Fixes #4000 - 7.13.0 Creating new node as an editor causes exception
(cherry picked from commit caf7a6a1ca)
2019-01-08 21:44:17 +01:00
Sebastiaan Janssen 030fd4d375 Git clone includes a directory to clone to now,
should fix Azure Gallery release.
Tightened up the variables and paths.

(cherry picked from commit e0a38a4d9b)
2019-01-08 21:44:07 +01:00
Sebastiaan Janssen 7658fba725 Fixes #3990 All images uploaded to media section have umbracoHeight / umbracoWidth of 200x200px
(cherry picked from commit 086157cff8)
2019-01-08 21:43:53 +01:00
Sebastiaan Janssen caf7a6a1ca Fixes #4000 - 7.13.0 Creating new node as an editor causes exception 2019-01-08 21:32:47 +01:00
Sebastiaan Janssen e0a38a4d9b Git clone includes a directory to clone to now,
should fix Azure Gallery release.
Tightened up the variables and paths.
2019-01-08 15:53:58 +01:00
Sebastiaan Janssen 086157cff8 Fixes #3990 All images uploaded to media section have umbracoHeight / umbracoWidth of 200x200px 2019-01-08 12:51:14 +01:00
Sebastiaan Janssen 21612454d0 Update umbtoggle.directive.js 2019-01-07 13:45:43 +01:00
Sebastiaan Janssen d53d0b4271 Add disabled state to toggle (#3967)
(cherry picked from commit d231db8ef2)

# Conflicts:
#	src/Umbraco.Web.UI.Client/src/views/languages/edit.html
2019-01-07 12:53:31 +01:00
Kenn Jacobsen 4564623899 Don't use a hardcoded folder type alias to determine folder types in the list view 2019-01-07 12:31:05 +01:00
Kenn Jacobsen cc6c16894c Safeguard the tags value converter against empty tags 2019-01-07 10:36:05 +01:00
Floris Robbemont 0852b20b31 Fix for wrong sorting overload in MediaService (#3948) 2019-01-04 11:55:52 +00:00
Claus 08e13ac530 Merge pull request #3814 from umbraco/temp7-269-xss-stylesheets
Removing malicious code from the name of a Stylesheet.
2019-01-04 10:11:25 +01:00
Claus 71f2b7ee06 updating unit tests. 2019-01-04 09:40:55 +01:00
Claus 7ead62730b reverting changes to StripHtml method. 2019-01-04 09:34:24 +01:00
Kenn Jacobsen 0150b97278 Show password change validation errors at the correct fields (#3918)
* Show password change validation errors at the correct password fields + remove the redundant "Could not reset password, errors: " message text

* Explicitly find the user instead of mapping it.
2018-12-31 14:02:59 +00:00
Kenn Jacobsen af2f531d31 Add missing localization of dialogs (#3844) 2018-12-31 13:37:58 +00:00
Sebastiaan Janssen 5e680e80e6 Deletes commented out code 2018-12-31 12:49:54 +00:00
Dave Woestenborghs ee8b4c5884 #3916 fix multiple enumerations of ienumerable...so usernames and avatars are displayed correctly 2018-12-31 12:49:54 +00:00
Dave Woestenborghs 0ce54847b0 #3916 mapping to a IEnumerable resulted in all items in the result list being the same. Now map items indiviually. Could be caused by this : https://stackoverflow.com/questions/17268362/automapper-for-a-list-scenario-only-seems-to-repeat-mapping-the-first-object-in 2018-12-31 12:49:54 +00:00
Callum Whyte b852c78861 Fixing spelling mistakes in helveticons CSS class names
The icon picker uses these class names as labels, kept the old class names for backwards compatibility
2018-12-31 12:47:04 +00:00
Kenn Jacobsen debbf87a04 Support image crop data set when overwriting files using the API 2018-12-31 12:43:06 +00:00
Brian Juul Andersen b2a1b11a5b Fixed minor grammatical error 2018-12-29 20:20:02 +00:00
elitsa 0aa1dc1dc7 Adding tests for verifying that malicious code input will be cleaned for XSS. 2018-12-27 10:02:49 +01:00
elitsa bb60d5e035 Reverting changes made from merge. 2018-12-27 09:57:31 +01:00
elitsa 247f213d26 Merge remote-tracking branch 'origin/dev-v7' into temp7-269-xss-stylesheets 2018-12-27 08:50:44 +01:00
elitsa d7696e8d91 Making a variable const 2018-12-18 11:34:50 +01:00
Shannon a0f15bba44 Fixes binding of FormDataCollection for GET requests which fixes the compatibility with the latest WebApi 5.2.7 version 2018-12-11 11:58:39 +11:00
elitsa 8518aaf4c1 Merge branch 'temp7-269-xss-stylesheets' of https://github.com/umbraco/Umbraco-CMS into temp7-269-xss-stylesheets
# Conflicts:
#	src/Umbraco.Core/StringExtensions.cs
2018-12-10 11:00:31 +01:00
elitsa 9edafe37e1 Merge branch 'dev-v7' into temp7-269-xss-stylesheets
# Conflicts resolved:
#	src/Umbraco.Core/StringExtensions.cs
2018-12-10 10:57:30 +01:00
Elitsa Marinovska 914d956ada Merge branch 'dev-v7' into temp7-269-xss-stylesheets 2018-12-03 12:50:40 +01:00
Jan Skovgaard 007cdeb9ab Fix long label issue on RADIO button list 2018-10-31 21:48:47 +01:00
Jan Skovgaard 5716353518 Offset the state 1 px to align it with the radio button list if they ever occur as properties beneath each other 2018-10-31 21:46:00 +01:00
Jan Skovgaard 87340d6c2c Fix width issue on the checkbox label 2018-10-31 21:24:35 +01:00
Jan Skovgaard fc742bcf18 Merge branch 'dev-v7' into feature/temp-U4-3463 2018-10-31 20:03:05 +01:00
Jan Skovgaard 4eb4cd8962 Refactor checkboxlist to show a prettier checkbox than the default browser one 2018-10-28 16:35:37 +01:00
139 changed files with 2468 additions and 892 deletions
+2 -2
View File
@@ -1,4 +1,4 @@
_Looking for Umbraco version 8? [Click here](https://github.com/umbraco/Umbraco-CMS/blob/temp8/.github/V8_GETTING_STARTED.md) to go to the v8 branch_
_Looking for Umbraco version 8? [Click here](https://github.com/umbraco/Umbraco-CMS/blob/dev-v8/.github/V8_GETTING_STARTED.md) to go to the v8 branch_
# Contributing to Umbraco CMS
👍🎉 First off, thanks for taking the time to contribute! 🎉👍
@@ -16,7 +16,7 @@ This document gives you a quick overview on how to get started, we will link to
## Guidelines for contributions we welcome
Not all changes are wanted, so on occassion we might close a PR without merging it. We will give you feedback why we can't accept your changes and we'll be nice about it, thanking you for spending your valueable time.
Not all changes are wanted, so on occassion we might close a PR without merging it. We will give you feedback why we can't accept your changes and we'll be nice about it, thanking you for spending your valuable time.
We have [documented what we consider small and large changes](CONTRIBUTION_GUIDELINES.md). Make sure to talk to us before making large changes.
+1
View File
@@ -1,4 +1,5 @@
[![Build status](https://ci.appveyor.com/api/projects/status/6by6harxtxt0ocdx/branch/dev-v7?svg=true)](https://ci.appveyor.com/project/Umbraco/umbraco-cms-b2cri/branch/dev-v7)
[![pullreminders](https://pullreminders.com/badge.svg)](https://pullreminders.com?ref=badge)
_Looking for Umbraco version 8? [Click here](https://github.com/umbraco/Umbraco-CMS/tree/temp8) to go to the v8 branch_
+20 -20
View File
@@ -3,57 +3,57 @@
[string]$Directory
)
$workingDirectory = $Directory
CD $workingDirectory
CD "$($workingDirectory)"
# Clone repo
$fullGitUrl = "https://$env:GIT_URL/$env:GIT_REPOSITORYNAME.git"
git clone $fullGitUrl 2>&1 | % { $_.ToString() }
$fullGitUrl = "https://$($env:GIT_URL)/$($env:GIT_REPOSITORYNAME).git"
git clone $($fullGitUrl) $($env:GIT_REPOSITORYNAME) 2>&1 | % { $_.ToString() }
# Remove everything so that unzipping the release later will update everything
# Don't remove the readme file nor the git directory
Write-Host "Cleaning up git directory before adding new version"
Remove-Item -Recurse $workingDirectory\$env:GIT_REPOSITORYNAME\* -Exclude README.md,.git
Remove-Item -Recurse "$($workingDirectory)\$($env:GIT_REPOSITORYNAME)\*" -Exclude README.md,.git
# Find release zip
$zipsDir = "$workingDirectory\$env:BUILD_DEFINITIONNAME\zips"
$zipsDir = "$($workingDirectory)\$($env:BUILD_DEFINITIONNAME)\zips"
$pattern = "UmbracoCms.([0-9]{1,2}.[0-9]{1,3}.[0-9]{1,3}).zip"
Write-Host "Searching for Umbraco release files in $workingDirectory\$zipsDir for a file with pattern $pattern"
$file = (Get-ChildItem $zipsDir | Where-Object { $_.Name -match "$pattern" })
Write-Host "Searching for Umbraco release files in $($zipsDir) for a file with pattern $($pattern)"
$file = (Get-ChildItem "$($zipsDir)" | Where-Object { $_.Name -match "$($pattern)" })
if($file)
{
# Get release name
$version = [regex]::Match($file.Name, $pattern).captures.groups[1].value
$releaseName = "Umbraco $version"
Write-Host "Found $releaseName"
$version = [regex]::Match($($file.Name), $($pattern)).captures.groups[1].value
$releaseName = "Umbraco $($version)"
Write-Host "Found $($releaseName)"
# Unzip into repository to update release
Add-Type -AssemblyName System.IO.Compression.FileSystem
Write-Host "Unzipping $($file.FullName) to $workingDirectory\$env:GIT_REPOSITORYNAME"
[System.IO.Compression.ZipFile]::ExtractToDirectory("$($file.FullName)", "$workingDirectory\$env:GIT_REPOSITORYNAME")
Write-Host "Unzipping $($file.FullName) to $($workingDirectory)\$($env:GIT_REPOSITORYNAME)"
[System.IO.Compression.ZipFile]::ExtractToDirectory("$($file.FullName)", "$($workingDirectory)\$($env:GIT_REPOSITORYNAME)")
# Telling git who we are
git config --global user.email "coffee@umbraco.com" 2>&1 | % { $_.ToString() }
git config --global user.name "Umbraco HQ" 2>&1 | % { $_.ToString() }
# Commit
CD $env:GIT_REPOSITORYNAME
Write-Host "Committing Umbraco $version Release from Build Output"
CD "$($workingDirectory)\$($env:GIT_REPOSITORYNAME)"
Write-Host "Committing Umbraco $($version) Release from Build Output"
git add . 2>&1 | % { $_.ToString() }
git commit -m " Release $releaseName from Build Output" 2>&1 | % { $_.ToString() }
git commit -m " Release $($releaseName) from Build Output" 2>&1 | % { $_.ToString() }
# Tag the release
git tag -a "v$version" -m "v$version"
git tag -a "v$($version)" -m "v$($version)"
# Push release to master
$fullGitAuthUrl = "https://$($env:GIT_USERNAME):$GitHubPersonalAccessToken@$env:GIT_URL/$env:GIT_REPOSITORYNAME.git"
git push $fullGitAuthUrl 2>&1 | % { $_.ToString() }
$fullGitAuthUrl = "https://$($env:GIT_USERNAME):$($GitHubPersonalAccessToken)@$($env:GIT_URL)/$($env:GIT_REPOSITORYNAME).git"
git push $($fullGitAuthUrl) 2>&1 | % { $_.ToString() }
#Push tag to master
git push $fullGitAuthUrl --tags 2>&1 | % { $_.ToString() }
git push $($fullGitAuthUrl) --tags 2>&1 | % { $_.ToString() }
}
else
{
Write-Error "Umbraco release file not found, searched in $workingDirectory\$zipsDir for a file with pattern $pattern - cancelling"
Write-Error "Umbraco release file not found, searched in $($workingDirectory)\$($zipsDir) for a file with pattern $($pattern) - canceling"
}
+2 -2
View File
@@ -11,5 +11,5 @@ using System.Resources;
[assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyFileVersion("7.13.0")]
[assembly: AssemblyInformationalVersion("7.13.0")]
[assembly: AssemblyFileVersion("7.14.0")]
[assembly: AssemblyInformationalVersion("7.14.0")]
@@ -6,7 +6,7 @@ namespace Umbraco.Core.Configuration
{
public class UmbracoVersion
{
private static readonly Version Version = new Version("7.13.0");
private static readonly Version Version = new Version("7.14.0");
/// <summary>
/// Gets the current version of Umbraco.
@@ -447,6 +447,11 @@ namespace Umbraco.Core
/// </summary>
public const string NestedContentAlias = "Umbraco.NestedContent";
/// <summary>
/// Alias for the multi url picker editor.
/// </summary>
public const string MultiUrlPickerAlias = "Umbraco.MultiUrlPicker";
public static class PreValueKeys
{
/// <summary>
+11 -2
View File
@@ -1,4 +1,6 @@
using System;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;
@@ -293,6 +295,12 @@ namespace Umbraco.Core.IO
{
var property = GetProperty(content, propertyTypeAlias);
var svalue = property.Value as string;
if (svalue != null && svalue.DetectIsJson())
{
// the property value is a JSON serialized image crop data set - grab the "src" property as the file source
var jObject = JsonConvert.DeserializeObject<JObject>(svalue);
svalue = jObject != null ? jObject.GetValueAsString("src") : svalue;
}
var oldpath = svalue == null ? null : GetRelativePath(svalue);
var filepath = StoreFile(content, property.PropertyType, filename, filestream, oldpath);
property.Value = GetUrl(filepath);
@@ -357,7 +365,8 @@ namespace Umbraco.Core.IO
{
var jpgInfo = ImageFile.FromStream(stream);
if (jpgInfo.Format != ImageFileFormat.Unknown
if (jpgInfo != null
&& jpgInfo.Format != ImageFileFormat.Unknown
&& jpgInfo.Properties.ContainsKey(ExifTag.PixelYDimension)
&& jpgInfo.Properties.ContainsKey(ExifTag.PixelXDimension))
{
+5 -4
View File
@@ -118,9 +118,9 @@ namespace Umbraco.Core.Media.Exif
/// <param name="encoding">The encoding to be used for text metadata when the source encoding is unknown.</param>
/// <returns>The <see cref="ImageFile"/> created from the file.</returns>
public static ImageFile FromStream(Stream stream, Encoding encoding)
{
{
// JPEG
if(JPEGDetector.IsOfType(stream))
if (JPEGDetector.IsOfType(stream))
{
return new JPEGFile(stream, encoding);
}
@@ -137,8 +137,9 @@ namespace Umbraco.Core.Media.Exif
return new SVGFile(stream);
}
throw new NotValidImageFileException ();
}
// We don't know
return null;
}
#endregion
}
}
@@ -7,8 +7,7 @@ namespace Umbraco.Core.Media.TypeDetector
public static bool IsOfType(Stream fileStream)
{
var header = GetFileHeader(fileStream);
return header[0] == 0xff && header[1] == 0xD8;
return header != null && header[0] == 0xff && header[1] == 0xD8;
}
}
}
@@ -7,9 +7,13 @@ namespace Umbraco.Core.Media.TypeDetector
public static byte[] GetFileHeader(Stream fileStream)
{
fileStream.Seek(0, SeekOrigin.Begin);
byte[] header = new byte[8];
var header = new byte[8];
fileStream.Seek(0, SeekOrigin.Begin);
// Invalid header
if (fileStream.Read(header, 0, header.Length) != header.Length)
return null;
return header;
}
}
@@ -7,17 +7,17 @@ namespace Umbraco.Core.Media.TypeDetector
{
public static bool IsOfType(Stream fileStream)
{
string tiffHeader = GetFileHeader(fileStream);
return tiffHeader == "MM\x00\x2a" || tiffHeader == "II\x2a\x00";
var tiffHeader = GetFileHeader(fileStream);
return tiffHeader != null && tiffHeader == "MM\x00\x2a" || tiffHeader == "II\x2a\x00";
}
public static string GetFileHeader(Stream fileStream)
{
var header = RasterizedTypeDetector.GetFileHeader(fileStream);
if (header == null)
return null;
string tiffHeader = Encoding.ASCII.GetString(header, 0, 4);
var tiffHeader = Encoding.ASCII.GetString(header, 0, 4);
return tiffHeader;
}
}
@@ -25,6 +25,8 @@ namespace Umbraco.Core.Models.PublishedContent
{
Id = contentType.Id;
Alias = contentType.Alias;
Name = contentType.Name;
Description = contentType.Description;
_compositionAliases = new HashSet<string>(contentType.CompositionAliases(), StringComparer.InvariantCultureIgnoreCase);
_propertyTypes = contentType.CompositionPropertyTypes
.Select(x => new PublishedPropertyType(this, x))
@@ -33,10 +35,12 @@ namespace Umbraco.Core.Models.PublishedContent
}
// internal so it can be used for unit tests
internal PublishedContentType(int id, string alias, IEnumerable<string> compositionAliases, IEnumerable<PublishedPropertyType> propertyTypes)
internal PublishedContentType(int id, string alias, string name, string description, IEnumerable<string> compositionAliases, IEnumerable<PublishedPropertyType> propertyTypes)
{
Id = id;
Alias = alias;
Name = name;
Description = description;
_compositionAliases = new HashSet<string>(compositionAliases, StringComparer.InvariantCultureIgnoreCase);
_propertyTypes = propertyTypes.ToArray();
foreach (var propertyType in _propertyTypes)
@@ -46,7 +50,7 @@ namespace Umbraco.Core.Models.PublishedContent
// create detached content type - ie does not match anything in the DB
internal PublishedContentType(string alias, IEnumerable<string> compositionAliases, IEnumerable<PublishedPropertyType> propertyTypes)
: this(0, alias, compositionAliases, propertyTypes)
: this(0, alias, string.Empty, string.Empty, compositionAliases, propertyTypes)
{ }
private void InitializeIndexes()
@@ -63,6 +67,8 @@ namespace Umbraco.Core.Models.PublishedContent
public int Id { get; private set; }
public string Alias { get; private set; }
public string Name { get; private set; }
public string Description { get; private set; }
public HashSet<string> CompositionAliases { get { return _compositionAliases; } }
#endregion
@@ -0,0 +1,36 @@
using Umbraco.Core.Logging;
using Umbraco.Core.Persistence.SqlSyntax;
namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenFourteenZero
{
/// <summary>
/// Migrates member group picker properties from NVarchar to NText. See https://github.com/umbraco/Umbraco-CMS/issues/3268.
/// </summary>
[Migration("7.14.0", 1, Constants.System.UmbracoMigrationName)]
public class UpdateMemberGroupPickerData : MigrationBase
{
public UpdateMemberGroupPickerData(ISqlSyntaxProvider sqlSyntax, ILogger logger) : base(sqlSyntax, logger)
{
}
public override void Up()
{
// move the data for all member group properties from the NVarchar to the NText column and clear the NVarchar column
Execute.Sql($@"UPDATE cmsPropertyData SET dataNtext = dataNvarchar, dataNvarchar = NULL
WHERE dataNtext IS NULL AND id IN (
SELECT id FROM cmsPropertyData WHERE propertyTypeId in (
SELECT id from cmsPropertyType where dataTypeID IN (
SELECT nodeId FROM cmsDataType WHERE propertyEditorAlias = '{Constants.PropertyEditors.MemberGroupPickerAlias}'
)
)
)");
// ensure that all exising member group properties are defined as NText
Execute.Sql($"UPDATE cmsDataType SET dbType = 'Ntext' WHERE propertyEditorAlias = '{Constants.PropertyEditors.MemberGroupPickerAlias}'");
}
public override void Down()
{
}
}
}
@@ -53,6 +53,12 @@ namespace Umbraco.Core.PropertyEditors
nestedContentEditorFromPackage.Name = "(Obsolete) " + nestedContentEditorFromPackage.Name;
nestedContentEditorFromPackage.IsDeprecated = true;
}
var multiUrlPickerEditorFromPackage = editors.FirstOrDefault(x => x.Alias == "RJP.MultiUrlPicker");
if (multiUrlPickerEditorFromPackage != null)
{
multiUrlPickerEditorFromPackage.Name = "(Obsolete) " + multiUrlPickerEditorFromPackage.Name;
multiUrlPickerEditorFromPackage.IsDeprecated = true;
}
return editors;
}
@@ -42,16 +42,22 @@ namespace Umbraco.Core.PropertyEditors.ValueConverters
public override object ConvertDataToSource(PublishedPropertyType propertyType, object source, bool preview)
{
var sourceAsString = source?.ToString();
if(sourceAsString.IsNullOrWhiteSpace())
{
return new string[0];
}
// if Json storage type deserialzie and return as string array
if (JsonStorageType(propertyType.DataTypeId))
{
var jArray = JsonConvert.DeserializeObject<JArray>(source.ToString());
var jArray = JsonConvert.DeserializeObject<JArray>(sourceAsString);
return jArray.ToObject<string[]>();
}
// Otherwise assume CSV storage type and return as string array
var csvTags =
source.ToString()
sourceAsString
.Split(new[] { "," }, StringSplitOptions.RemoveEmptyEntries)
.ToArray();
return csvTags;
@@ -107,6 +107,11 @@ namespace Umbraco.Core.Security
await EnsureValidSessionId(context);
if (context?.Identity == null)
{
context?.OwinContext.Authentication.SignOut(context.Options.AuthenticationType);
return;
}
await base.ValidateIdentity(context);
}
+1 -1
View File
@@ -509,7 +509,7 @@ namespace Umbraco.Core.Services
public IEnumerable<IMedia> GetPagedChildren(int id, long pageIndex, int pageSize, out long totalChildren,
string orderBy, Direction orderDirection, bool orderBySystemField, string filter)
{
return GetPagedChildren(id, pageIndex, pageSize, out totalChildren, orderBy, orderDirection, true, filter, null);
return GetPagedChildren(id, pageIndex, pageSize, out totalChildren, orderBy, orderDirection, orderBySystemField, filter, null);
}
/// <summary>
@@ -1,3 +1,4 @@
using System;
using System.Collections.Generic;
using Umbraco.Core.Events;
using Umbraco.Core.Logging;
@@ -69,6 +70,11 @@ namespace Umbraco.Core.Services
public void Save(IMemberGroup memberGroup, bool raiseEvents = true)
{
if (string.IsNullOrWhiteSpace(memberGroup.Name))
{
throw new InvalidOperationException("The name of a MemberGroup can not be empty");
}
using (var uow = UowProvider.GetUnitOfWork())
{
var saveEventArgs = new SaveEventArgs<IMemberGroup>(memberGroup);
@@ -133,4 +139,4 @@ namespace Umbraco.Core.Services
/// </remarks>
public static event TypedEventHandler<IMemberGroupService, SaveEventArgs<IMemberGroup>> Saved;
}
}
}
+3 -2
View File
@@ -189,7 +189,6 @@ namespace Umbraco.Core
outputArray[i] = char.IsLetterOrDigit(inputArray[i]) ? inputArray[i] : replacement;
return new string(outputArray);
}
private static readonly char[] CleanForXssChars = "*?(){}[];:%<>/\\|&'\"".ToCharArray();
/// <summary>
@@ -542,7 +541,7 @@ namespace Umbraco.Core
public static string StripHtml(this string text)
{
const string pattern = @"<(.|\n)*?>";
return Regex.Replace(text, pattern, String.Empty);
return Regex.Replace(text, pattern, string.Empty);
}
/// <summary>
@@ -732,6 +731,7 @@ namespace Umbraco.Core
/// </summary>
/// <param name="stringToConvert">Referrs to itself</param>
/// <returns>The MD5 hashed string</returns>
[Obsolete("Please use the GenerateHash method instead. This may be removed in future versions")]
public static string ToMd5(this string stringToConvert)
{
return stringToConvert.GenerateHash("MD5");
@@ -742,6 +742,7 @@ namespace Umbraco.Core
/// </summary>
/// <param name="stringToConvert">referrs to itself</param>
/// <returns>The SHA1 hashed string</returns>
[Obsolete("Please use the GenerateHash method instead. This may be removed in future versions")]
public static string ToSHA1(this string stringToConvert)
{
return stringToConvert.GenerateHash("SHA1");
+1
View File
@@ -572,6 +572,7 @@
<Compile Include="Persistence\Migrations\Upgrades\TargetVersionSevenEightZero\AddInstructionCountColumn.cs" />
<Compile Include="Persistence\Migrations\Upgrades\TargetVersionSevenEightZero\AddCmsMediaTable.cs" />
<Compile Include="Persistence\Migrations\Upgrades\TargetVersionSevenEightZero\AddUserLoginTable.cs" />
<Compile Include="Persistence\Migrations\Upgrades\TargetVersionSevenFourteenZero\UpdateMemberGroupPickerData.cs" />
<Compile Include="Persistence\Migrations\Upgrades\TargetVersionSevenTwelveZero\RenameTrueFalseField.cs" />
<Compile Include="Persistence\Migrations\Upgrades\TargetVersionSevenTwelveZero\SetDefaultTagsStorageType.cs" />
<Compile Include="Persistence\Migrations\Upgrades\TargetVersionSevenNineZero\AddUmbracoAuditTable.cs" />
@@ -83,7 +83,7 @@ namespace Umbraco.Tests.CodeFirst
new PublishedPropertyType("articleDate", 0, "?"),
new PublishedPropertyType("pageTitle", 0, "?"),
};
var type = new AutoPublishedContentType(0, "anything", propertyTypes);
var type = new AutoPublishedContentType(0, "anything", "anything", "anything", propertyTypes);
PublishedContentType.GetPublishedContentTypeCallback = (alias) => type;
Debug.Print("INIT STRONG {0}",
PublishedContentType.Get(PublishedItemType.Content, "anything")
@@ -148,4 +148,4 @@ namespace Umbraco.Tests.CodeFirst
}
#endregion
}
}
}
+1 -1
View File
@@ -43,7 +43,7 @@ namespace Umbraco.Tests
// AutoPublishedContentType will auto-generate other properties
new PublishedPropertyType("content", 0, "?"),
};
var type = new AutoPublishedContentType(0, "anything", propertyTypes);
var type = new AutoPublishedContentType(0, "anything", "anything", "anything", propertyTypes);
PublishedContentType.GetPublishedContentTypeCallback = (alias) => type;
Debug.Print("INIT LIB {0}",
PublishedContentType.Get(PublishedItemType.Content, "anything")
@@ -41,7 +41,7 @@ namespace Umbraco.Tests.Membership
new PublishedPropertyType("bodyText", 0, "?"),
new PublishedPropertyType("author", 0, "?")
};
var type = new AutoPublishedContentType(0, "anything", propertyTypes);
var type = new AutoPublishedContentType(0, "anything", "anything", "anything", propertyTypes);
PublishedContentType.GetPublishedContentTypeCallback = (alias) => type;
}
@@ -50,7 +50,7 @@ namespace Umbraco.Tests.PublishedContent
new PublishedPropertyType("creatorName", 0, "?"),
new PublishedPropertyType("blah", 0, "?"), // ugly error when that one is missing...
};
var type = new AutoPublishedContentType(0, "anything", propertyTypes);
var type = new AutoPublishedContentType(0, "anything", "anything", "anything", propertyTypes);
PublishedContentType.GetPublishedContentTypeCallback = (alias) => type;
}
@@ -729,4 +729,4 @@ namespace Umbraco.Tests.PublishedContent
return s.Contains(val.ToString());
}
}
}
}
@@ -24,7 +24,7 @@ namespace Umbraco.Tests.PublishedContent
// need to specify a custom callback for unit tests
// AutoPublishedContentTypes generates properties automatically
var type = new AutoPublishedContentType(0, "anything", new PublishedPropertyType[] {});
var type = new AutoPublishedContentType(0, "anything", "anything", "anything", new PublishedPropertyType[] {});
PublishedContentType.GetPublishedContentTypeCallback = (alias) => type;
// need to specify a different callback for testing
@@ -251,4 +251,4 @@ namespace Umbraco.Tests.PublishedContent
}
}
}
}
}
@@ -234,9 +234,9 @@ namespace Umbraco.Tests.PublishedContent
new PublishedPropertyType("prop1", 1, "?"),
};
var contentType1 = new PublishedContentType(1, "ContentType1", Enumerable.Empty<string>(), props);
var contentType2 = new PublishedContentType(2, "ContentType2", Enumerable.Empty<string>(), props);
var contentType2s = new PublishedContentType(3, "ContentType2Sub", Enumerable.Empty<string>(), props);
var contentType1 = new PublishedContentType(1, "ContentType1", "ContentType1", "ContentType1", Enumerable.Empty<string>(), props);
var contentType2 = new PublishedContentType(2, "ContentType2", "ContentType2", "ContentType2", Enumerable.Empty<string>(), props);
var contentType2s = new PublishedContentType(3, "ContentType2Sub", "ContentType2Sub", "ContentType2Sub", Enumerable.Empty<string>(), props);
cache.Add(new SolidPublishedContent(contentType1)
{
@@ -29,7 +29,7 @@ namespace Umbraco.Tests.PublishedContent
// AutoPublishedContentType will auto-generate other properties
new PublishedPropertyType("content", 0, Constants.PropertyEditors.TinyMCEAlias),
};
var type = new AutoPublishedContentType(0, "anything", propertyTypes);
var type = new AutoPublishedContentType(0, "anything", "anything", "anything", propertyTypes);
PublishedContentType.GetPublishedContentTypeCallback = (alias) => type;
var rCtx = GetRoutingContext("/test", 1234);
@@ -65,4 +65,4 @@ namespace Umbraco.Tests.PublishedContent
UmbracoContext.Current = null;
}
}
}
}
@@ -354,12 +354,12 @@ namespace Umbraco.Tests.PublishedContent
{
private static readonly PublishedPropertyType Default = new PublishedPropertyType("*", 0, "?");
public AutoPublishedContentType(int id, string alias, IEnumerable<PublishedPropertyType> propertyTypes)
: base(id, alias, Enumerable.Empty<string>(), propertyTypes)
public AutoPublishedContentType(int id, string alias, string name, string description, IEnumerable<PublishedPropertyType> propertyTypes)
: base(id, alias, name, description, Enumerable.Empty<string>(), propertyTypes)
{ }
public AutoPublishedContentType(int id, string alias, IEnumerable<string> compositionAliases, IEnumerable<PublishedPropertyType> propertyTypes)
: base(id, alias, compositionAliases, propertyTypes)
public AutoPublishedContentType(int id, string alias, string name, string description, IEnumerable<string> compositionAliases, IEnumerable<PublishedPropertyType> propertyTypes)
: base(id, alias, name, description, compositionAliases, propertyTypes)
{ }
public override PublishedPropertyType GetPropertyType(string alias)
@@ -49,7 +49,7 @@ namespace Umbraco.Tests.PublishedContent
new PublishedPropertyType("testRecursive", 0, "?"),
};
var compositionAliases = new[] { "MyCompositionAlias" };
var type = new AutoPublishedContentType(0, "anything", compositionAliases, propertyTypes);
var type = new AutoPublishedContentType(0, "anything", "anything", "anything", compositionAliases, propertyTypes);
PublishedContentType.GetPublishedContentTypeCallback = (alias) => type;
}
@@ -0,0 +1,39 @@
using System;
using System.Linq;
using NUnit.Framework;
using Umbraco.Core;
using Umbraco.Core.Models;
using Umbraco.Core.Models.Rdbms;
using Umbraco.Tests.TestHelpers;
using Umbraco.Tests.TestHelpers.Entities;
namespace Umbraco.Tests.Services
{
[DatabaseTestBehavior(DatabaseBehavior.NewDbFileAndSchemaPerTest)]
[TestFixture, RequiresSTA]
public class MemberGroupServiceTests : BaseServiceTest
{
[SetUp]
public override void Initialize()
{
base.Initialize();
}
[TearDown]
public override void TearDown()
{
base.TearDown();
}
[Test]
[ExpectedException("System.InvalidOperationException")]
public void New_MemberGroup_Is_Not_Allowed_With_Empty_Name()
{
var service = ServiceContext.MemberGroupService;
service.Save(new MemberGroup {Name = ""});
Assert.Fail("An exception should have been thrown");
}
}
}
@@ -61,6 +61,17 @@ namespace Umbraco.Tests.Strings
Assert.AreEqual(stripped, result);
}
[TestCase("'+alert(1234)+'", "+alert1234+")]
[TestCase("'+alert(56+78)+'", "+alert56+78+")]
[TestCase("{{file}}", "file")]
[TestCase("'+alert('hello')+'", "+alerthello+")]
[TestCase("Test", "Test")]
public void Clean_From_XSS(string input, string result)
{
var cleaned = input.CleanForXss();
Assert.AreEqual(cleaned, result);
}
[TestCase("This is a string to encrypt")]
[TestCase("This is a string to encrypt\nThis is a second line")]
[TestCase(" White space is preserved ")]
+1 -1
View File
@@ -15,7 +15,7 @@ namespace Umbraco.Tests.TestHelpers
// need to specify a custom callback for unit tests
// AutoPublishedContentTypes generates properties automatically
var type = new AutoPublishedContentType(0, "anything", new PublishedPropertyType[] {});
var type = new AutoPublishedContentType(0, "anything", "anything", "anything", new PublishedPropertyType[] {});
PublishedContentType.GetPublishedContentTypeCallback = (alias) => type;
}
+1
View File
@@ -193,6 +193,7 @@
<Compile Include="PublishedContent\StronglyTypedModels\Home.cs" />
<Compile Include="Services\AuditServiceTests.cs" />
<Compile Include="Services\ConsentServiceTests.cs" />
<Compile Include="Services\MemberGroupServiceTests.cs" />
<Compile Include="TestHelpers\ControllerTesting\AuthenticateEverythingExtensions.cs" />
<Compile Include="TestHelpers\ControllerTesting\AuthenticateEverythingMiddleware.cs" />
<Compile Include="TestHelpers\ControllerTesting\SpecificAssemblyResolver.cs" />
@@ -29,5 +29,30 @@ namespace Umbraco.Tests.Web.Mvc
var output = _htmlHelper.Wrap("div", "hello world", new {style = "color:red;", onclick = "void();"});
Assert.AreEqual("<div style=\"color:red;\" onclick=\"void();\">hello world</div>", output.ToHtmlString());
}
}
}
[Test]
public void GetRelatedLinkHtml_Simple()
{
var relatedLink = new Umbraco.Web.Models.RelatedLink {
Caption = "Link Caption",
NewWindow = true,
Link = "https://www.google.com/"
};
var output = _htmlHelper.GetRelatedLinkHtml(relatedLink);
Assert.AreEqual("<a href=\"https://www.google.com/\" target=\"_blank\">Link Caption</a>", output.ToHtmlString());
}
[Test]
public void GetRelatedLinkHtml_HtmlAttributes()
{
var relatedLink = new Umbraco.Web.Models.RelatedLink
{
Caption = "Link Caption",
NewWindow = true,
Link = "https://www.google.com/"
};
var output = _htmlHelper.GetRelatedLinkHtml(relatedLink, new { @class = "test-class"});
Assert.AreEqual("<a class=\"test-class\" href=\"https://www.google.com/\" target=\"_blank\">Link Caption</a>", output.ToHtmlString());
}
}
}
@@ -11,8 +11,7 @@ LazyLoad.js([
'../js/umbraco.security.js',
'../ServerVariables',
'../lib/spectrum/spectrum.js',
'../js/umbraco.canvasdesigner.js',
'../js/canvasdesigner.panel.js'
'../js/umbraco.canvasdesigner.js'
], function () {
jQuery(document).ready(function () {
angular.bootstrap(document, ['Umbraco.canvasdesigner']);
@@ -18,6 +18,7 @@
<umb-toggle
checked="vm.checked"
disabled="vm.disabled"
on-click="vm.toggle()"
show-labels="true"
label-on="Start"
@@ -38,6 +39,7 @@
var vm = this;
vm.checked = false;
vm.disabled = false;
vm.toggle = toggle;
@@ -52,6 +54,7 @@
</pre>
@param {boolean} checked Set to <code>true</code> or <code>false</code> to toggle the switch.
@param {boolean} disabled Set to <code>true</code> or <code>false</code> to disable/enable the switch.
@param {callback} onClick The function which should be called when the toggle is clicked.
@param {string=} showLabels Set to <code>true</code> or <code>false</code> to show a "On" or "Off" label next to the switch.
@param {string=} labelOn Set a custom label for when the switched is turned on. It will default to "On".
@@ -115,6 +118,7 @@
templateUrl: 'views/components/buttons/umb-toggle.html',
scope: {
checked: "=",
disabled: "=",
onClick: "&",
labelOn: "@?",
labelOff: "@?",
@@ -53,6 +53,9 @@
if (scope.documentType !== null) {
scope.previewOpenUrl = '#/settings/documenttypes/edit/' + scope.documentType.id;
}
// only allow configuring scheduled publishing if the user has publish ("U") and unpublish ("Z") permissions on this node
scope.allowScheduledPublishing = _.contains(scope.node.allowedActions, "U") && _.contains(scope.node.allowedActions, "Z");
}
scope.auditTrailPageChange = function (pageNumber) {
@@ -0,0 +1,55 @@
/**
@ngdoc directive
@name umbraco.directives.directive:umbCheckbox
@restrict E
@scope
@description
<b>Added in Umbraco version 7.14.0</b> Use this directive to render an umbraco checkbox.
<h3>Markup example</h3>
<pre>
<div ng-controller="My.Controller as vm">
<umb-checkbox
name="checkboxlist"
value="{{key}}"
model="true"
text="{{text}}">
</umb-checkbox>
</div>
</pre>
@param {boolean} model Set to <code>true</code> or <code>false</code> to set the checkbox to checked or unchecked.
@param {string} value Set the value of the checkbox.
@param {string} name Set the name of the checkbox.
@param {string} text Set the text for the checkbox label.
**/
(function () {
'use strict';
function CheckboxDirective() {
var directive = {
restrict: 'E',
replace: true,
templateUrl: 'views/components/forms/umb-checkbox.html',
scope: {
model: "=",
value: "@",
name: "@",
text: "@",
required: "="
}
};
return directive;
}
angular.module('umbraco.directives').directive('umbCheckbox', CheckboxDirective);
})();
@@ -0,0 +1,54 @@
/**
@ngdoc directive
@name umbraco.directives.directive:umbRadiobutton
@restrict E
@scope
@description
<b>Added in Umbraco version 7.14.0</b> Use this directive to render an umbraco radio button.
<h3>Markup example</h3>
<pre>
<div ng-controller="My.Controller as vm">
<umb-radiobutton
name="checkboxlist"
value="{{key}}"
model="true"
text="{{text}}">
</umb-radiobutton>
</div>
</pre>
@param {boolean} model Set to <code>true</code> or <code>false</code> to set the radiobutton to checked or unchecked.
@param {string} value Set the value of the radiobutton.
@param {string} name Set the name of the radiobutton.
@param {string} text Set the text for the radiobutton label.
**/
(function () {
'use strict';
function RadiobuttonDirective() {
var directive = {
restrict: 'E',
replace: true,
templateUrl: 'views/components/forms/umb-radiobutton.html',
scope: {
model: "=",
value: "@",
name: "@",
text: "@"
}
};
return directive;
}
angular.module('umbraco.directives').directive('umbRadiobutton', RadiobuttonDirective);
})();
@@ -103,34 +103,6 @@ angular.module("umbraco.directives")
scope.dimensions.cropper.height = _viewPortH; // scope.dimensions.viewport.height - 2 * scope.dimensions.margin;
};
//when loading an image without any crop info, we center and fit it
var resizeImageToEditor = function(){
//returns size fitting the cropper
var size = cropperHelper.calculateAspectRatioFit(
scope.dimensions.image.width,
scope.dimensions.image.height,
scope.dimensions.cropper.width,
scope.dimensions.cropper.height,
true);
//sets the image size and updates the scope
scope.dimensions.image.width = size.width;
scope.dimensions.image.height = size.height;
//calculate the best suited ratios
scope.dimensions.scale.min = size.ratio;
scope.dimensions.scale.max = 2;
scope.dimensions.scale.current = size.ratio;
//center the image
var position = cropperHelper.centerInsideViewPort(scope.dimensions.image, scope.dimensions.cropper);
scope.dimensions.top = position.top;
scope.dimensions.left = position.left;
setConstraints();
};
//resize to a given ratio
var resizeImageToScale = function(ratio){
//do stuff
@@ -227,12 +199,19 @@ angular.module("umbraco.directives")
//set dimensions on image, viewport, cropper etc
setDimensions(image);
//if we have a crop already position the image
if(scope.crop){
resizeImageToCrop();
}else{
resizeImageToEditor();
}
//create a default crop if we haven't got one already
var createDefaultCrop = !scope.crop;
if (createDefaultCrop) {
calculateCropBox();
}
resizeImageToCrop();
//if we're creating a new crop, make sure to zoom out fully
if (createDefaultCrop) {
scope.dimensions.scale.current = scope.dimensions.scale.min;
resizeImageToScale(scope.dimensions.scale.min);
}
//sets constaints for the cropper
setConstraints();
@@ -253,7 +232,7 @@ angular.module("umbraco.directives")
var throttledResizing = _.throttle(function(){
resizeImageToScale(scope.dimensions.scale.current);
calculateCropBox();
}, 100);
}, 16);
//happens when we change the scale
@@ -14,7 +14,8 @@ angular.module("umbraco.directives")
scope: {
src: '=',
center: "=",
onImageLoaded: "&"
onImageLoaded: "&",
onGravityChanged: "&"
},
link: function(scope, element, attrs) {
@@ -34,7 +35,7 @@ angular.module("umbraco.directives")
var $overlay = element.find(".overlay");
scope.style = function () {
if (scope.dimensions.width <= 0) {
if (scope.dimensions.width <= 0 || scope.dimensions.height <= 0) {
setDimensions();
}
@@ -52,7 +53,7 @@ angular.module("umbraco.directives")
calculateGravity(offsetX, offsetY);
lazyEndEvent();
gravityChanged();
};
var setDimensions = function () {
@@ -77,12 +78,11 @@ angular.module("umbraco.directives")
scope.center.top = (scope.dimensions.top+10) / scope.dimensions.height;
};
var lazyEndEvent = _.debounce(function(){
scope.$apply(function(){
scope.$emit("imageFocalPointStop");
});
}, 2000);
var gravityChanged = function () {
if (angular.isFunction(scope.onGravityChanged)) {
scope.onGravityChanged();
}
};
//Drag and drop positioning, using jquery ui draggable
//TODO ensure that the point doesnt go outside the box
@@ -100,7 +100,7 @@ angular.module("umbraco.directives")
calculateGravity(offsetX, offsetY);
});
lazyEndEvent();
gravityChanged();
}
});
@@ -86,20 +86,21 @@ angular.module("umbraco.directives")
function generateAlias(value) {
if (generateAliasTimeout) {
$timeout.cancel(generateAliasTimeout);
$timeout.cancel(generateAliasTimeout);
}
if( value !== undefined && value !== "" && value !== null) {
if (value !== undefined && value !== "" && value !== null) {
scope.alias = "";
scope.alias = "";
scope.placeholderText = scope.labels.busy;
generateAliasTimeout = $timeout(function () {
updateAlias = true;
entityResource.getSafeAlias(encodeURIComponent(value), true).then(function (safeAlias) {
if (updateAlias) {
scope.alias = safeAlias.alias;
}
scope.alias = safeAlias.alias;
}
scope.placeholderText = scope.labels.idle;
});
}, 500);
@@ -108,7 +109,6 @@ angular.module("umbraco.directives")
scope.alias = "";
scope.placeholderText = scope.labels.idle;
}
}
// if alias gets unlocked - stop watching alias
@@ -119,17 +119,17 @@ angular.module("umbraco.directives")
}));
// validate custom entered alias
eventBindings.push(scope.$watch('alias', function(newValue, oldValue){
if(scope.alias === "" && bindWatcher === true || scope.alias === null && bindWatcher === true) {
// add watcher
eventBindings.push(scope.$watch('aliasFrom', function(newValue, oldValue) {
if(bindWatcher) {
generateAlias(newValue);
}
}));
}
eventBindings.push(scope.$watch('alias', function (newValue, oldValue) {
if (scope.alias === "" || scope.alias === null || scope.alias === undefined) {
if (bindWatcher === true) {
// add watcher
eventBindings.push(scope.$watch('aliasFrom', function (newValue, oldValue) {
if (bindWatcher) {
generateAlias(newValue);
}
}));
}
}
}));
// clean up
@@ -38,7 +38,7 @@ Use this directive to generate color swatches to pick from.
scope.selectedColor = color;
if (scope.onSelect) {
scope.onSelect(color);
scope.onSelect({color: color });
}
};
}
@@ -3,7 +3,7 @@
* @name umbraco.resources.codefileResource
* @description Loads in data for files that contain code such as js scripts, partial views and partial view macros
**/
function codefileResource($q, $http, umbDataFormatter, umbRequestHelper) {
function codefileResource($q, $http, umbDataFormatter, umbRequestHelper, localizationService) {
return {
@@ -106,13 +106,16 @@ function codefileResource($q, $http, umbDataFormatter, umbRequestHelper) {
*
*/
deleteByPath: function (type, virtualpath) {
var promise = localizationService.localize("codefile_deleteItemFailed", [virtualpath]);
return umbRequestHelper.resourcePromise(
$http.post(
umbRequestHelper.getApiUrl(
"codeFileApiBaseUrl",
"Delete",
[{ type: type }, { virtualPath: virtualpath}])),
"Failed to delete item: " + virtualpath);
promise);
},
/**
@@ -236,13 +239,19 @@ function codefileResource($q, $http, umbDataFormatter, umbRequestHelper) {
*
*/
createContainer: function(type, parentId, name) {
createContainer: function (type, parentId, name) {
// Is the parent ID numeric?
var key = "codefile_createFolderFailedBy" + (isNaN(parseInt(parentId)) ? "Name" : "Id");
var promise = localizationService.localize(key, [parentId]);
return umbRequestHelper.resourcePromise(
$http.post(umbRequestHelper.getApiUrl(
"codeFileApiBaseUrl",
"PostCreateContainer",
{ type: type, parentId: parentId, name: encodeURIComponent(name) })),
'Failed to create a folder under parent id ' + parentId);
promise);
}
};
@@ -26,7 +26,7 @@ function relationResource($q, $http, umbRequestHelper) {
umbRequestHelper.getApiUrl(
"relationApiBaseUrl",
"GetByChildId",
[{ childId: id, relationTypeAlias: alias }])),
{ childId: id, relationTypeAlias: alias })),
"Failed to get relation by child ID " + id + " and type of " + alias);
},
@@ -62,4 +62,4 @@ function relationResource($q, $http, umbRequestHelper) {
};
}
angular.module('umbraco.resources').factory('relationResource', relationResource);
angular.module('umbraco.resources').factory('relationResource', relationResource);
@@ -3,7 +3,7 @@
* @name umbraco.resources.templateResource
* @description Loads in data for templates
**/
function templateResource($q, $http, umbDataFormatter, umbRequestHelper) {
function templateResource($q, $http, umbDataFormatter, umbRequestHelper, localizationService) {
return {
@@ -152,13 +152,16 @@ function templateResource($q, $http, umbDataFormatter, umbRequestHelper) {
*
*/
deleteById: function(id) {
var promise = localizationService.localize("template_deleteByIdFailed", [id]);
return umbRequestHelper.resourcePromise(
$http.post(
umbRequestHelper.getApiUrl(
"templateApiBaseUrl",
"DeleteById",
[{ id: id }])),
"Failed to delete item " + id);
promise);
},
/**
@@ -123,13 +123,6 @@ function cropperHelper(umbRequestHelper, $http) {
return crop;
},
centerInsideViewPort : function(img, viewport){
var left = viewport.width/ 2 - img.width / 2,
top = viewport.height / 2 - img.height / 2;
return {left: left, top: top};
},
alignToCoordinates : function(image, center, viewport){
var min_left = (image.width) - (viewport.width);
@@ -16,17 +16,17 @@ 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 440 000 websites are currently powered by Umbraco',
var facts = ["Umbraco helped millions of people watch a man jump from the edge of space",
"Over 500 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',
'You can find the world\'s friendliest CMS community at <a target="_blank" href="https://our.umbraco.com">our.umbraco.com</a>',
'You can become a certified Umbraco developer by attending one of the official courses',
'Umbraco works really well on tablets',
'You have 100% control over your markup and design when crafting a website in Umbraco',
'Umbraco is the best of both worlds: 100% free and open source, and backed by a professional and profitable company',
"There's a pretty big chance, you've visited a website powered by Umbraco today",
"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",
"You can find the world's friendliest CMS community at <a target='_blank' href='https://our.umbraco.com/'>our.umbraco.com</a>",
"You can become a certified Umbraco developer by attending one of the official courses",
"Umbraco works really well on tablets",
"You have 100% control over your markup and design when crafting a website in Umbraco",
"Umbraco is the best of both worlds: 100% free and open source, and backed by a professional and profitable company",
"There's a pretty big chance you've visited a website powered by Umbraco today",
"'Umbraco-spotting' is the game of spotting big brands running Umbraco",
"At least 4 people have the Umbraco logo tattooed on them",
"'Umbraco' is the Danish name for an allen key",
@@ -101,6 +101,7 @@
@import "components/umb-confirm-action.less";
@import "components/umb-keyboard-shortcuts-overview.less";
@import "components/umb-checkbox-list.less";
@import "components/umb-form-check.less";
@import "components/umb-locked-field.less";
@import "components/umb-tabs.less";
@import "components/umb-load-indicator.less";
@@ -28,7 +28,8 @@
.umb-toggle__toggle {
cursor: pointer;
display: inline-block;
align-items: center;
display: flex;
width: 48px;
height: 24px;
background: @gray-8;
@@ -41,6 +42,11 @@
background-color: @green;
}
.umb-toggle--disabled .umb-toggle__toggle {
cursor: not-allowed;
opacity: 0.8;
}
.umb-toggle--checked .umb-toggle__handler {
transform: translate3d(24px, 0, 0) rotate(0);
}
@@ -63,7 +69,7 @@
.umb-toggle__icon {
position: absolute;
top: 3px;
line-height: 1em;
text-decoration: none;
transition: all 0.2s ease;
}
@@ -1,3 +1,6 @@
@checkboxWidth: 15px;
@checkboxHeight: 15px;
.umb-checkbox-list {
list-style: none;
margin-left: 0;
@@ -0,0 +1,125 @@
@checkboxWidth: 15px;
@checkboxHeight: 15px;
.umb-form-check {
display: flex;
flex-wrap: wrap;
align-items: center;
position: relative;
padding: 0;
margin: 0;
&__text{
margin: 0 0 0 26px;
position: relative;
top: 2px;
}
&__input{
position: absolute;
top: 0;
left: 0;
opacity: 0;
&:checked ~ .umb-form-check__state .umb-form-check__check{
border-color: @green;
}
&:focus:checked ~ .umb-form-check .umb-form-check__check,
&:focus ~ .umb-form-check__state .umb-form-check__check{
border-color: @gray-5;
}
&:checked ~ .umb-form-check__state{
.umb-form-check__check{
// This only happens if the state has a radiobutton modifier
.umb-form-check--radiobutton &{
&:before{
opacity: 1;
transform: scale(1);
}
}
// This only happens if state has the checkbox modifier
.umb-form-check--checkbox &{
&:before{
width: @checkboxWidth;
height: @checkboxHeight;
}
}
}
// This only happens if state has the checkbox modifier
.umb-form-check--checkbox &{
.umb-form-check__icon{
opacity: 1;
}
}
}
}
&__state{
height: 17px;
position: absolute;
top: 2px;
left: 0;
}
&__check{
position: relative;
border: 1px solid @gray-7;
width: @checkboxWidth;
height: @checkboxHeight;
&:before{
content: "";
background: @green;
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
margin: auto;
}
// This only happens if state has the radiobutton modifier
.umb-form-check--radiobutton &{
border-radius: 100%;
&:before{
width: 9px;
height: 9px;
border-radius: 100%;
opacity: 0;
transform: scale(0);
transition: .15s ease-out;
}
}
// This only happens if state has the checkbox modifier
.umb-form-check--checkbox &{
&:before{
width: 0;
height: 0;
transition: .05s ease-out;
}
}
}
&__icon{
color: @white;
text-align: center;
font-size: 10px;
opacity: 0;
transition: .2s ease-out;
&:before{
position: absolute;
top: -2px;
right: 0;
left: 0;
bottom: 0;
margin: auto;
}
}
}
@@ -165,7 +165,7 @@ input.umb-table__input {
}
.-content :not(.with-unpublished-version).-unpublished {
.-content .-unpublished:not(.with-unpublished-version) {
.umb-table__name > * {
opacity: .4;
}
@@ -21,6 +21,12 @@
cursor: pointer;
}
.umb-permission--disabled .umb-permission__toggle,
.umb-permission--disabled .umb-permission__content {
cursor: not-allowed;
opacity: 0.8;
}
.umb-permission__description {
font-size: 13px;
color: @gray-5;
@@ -17,12 +17,14 @@
-webkit-font-smoothing: antialiased;
*margin-right: .3em;
}
[class^="icon-"]:before,
[class*=" icon-"]:before {
text-decoration: inherit;
display: inline-block;
speak: none;
}
/*
[class^="icon-"]:before, [class*=" icon-"]:before {
font-family: 'icomoon';
@@ -38,7 +40,6 @@
i.large{
font-size: 32px;
}
i.medium{
font-size: 24px;
}
@@ -187,8 +188,6 @@ i.small{
.icon-umb-translation:before, .traytranslation:before {
content: "\e1fd";
}
.icon-tv:before {
content: "\e02e";
}
@@ -213,7 +212,8 @@ i.small{
.icon-train:before {
content: "\e035";
}
.icon-trafic:before {
.icon-trafic:before,
.icon-traffic:before {
content: "\e036";
}
.icon-traffic-alt:before {
@@ -255,6 +255,7 @@ i.small{
.icon-target:before {
content: "\e043";
}
.icon-temperature-alt:before,
.icon-temperatrure-alt:before {
content: "\e044";
}
@@ -267,6 +268,7 @@ i.small{
.icon-theater:before {
content: "\e047";
}
.icon-thief:before,
.icon-theif:before {
content: "\e048";
}
@@ -375,6 +377,7 @@ i.small{
.icon-shuffle:before {
content: "\e06b";
}
.icon-science:before,
.icon-sience:before {
content: "\e06c";
}
@@ -747,6 +750,7 @@ i.small{
.icon-pictures-alt-2:before {
content: "\e0e7";
}
.icon-panel-close:before,
.icon-pannel-close:before {
content: "\e0e8";
}
@@ -1627,6 +1631,7 @@ i.small{
.icon-alarm-clock:before {
content: "\e20c";
}
.icon-addressbook:before,
.icon-adressbook:before {
content: "\e20d";
}
@@ -1,3 +1,5 @@
@checkered-background: url(../img/checkered-background.png);
//
// Container styles
// --------------------------------------------------
@@ -11,7 +13,16 @@
&-push {
float:right;
}
}
&--list{
float: left;
}
&__item{
line-height: 1;
margin: 0 0 5px;
}
}
.umb-editor-tiny {
@@ -244,7 +255,7 @@ div.umb-codeeditor .umb-btn-toolbar {
margin: 24px 0 0;
display: flex;
}
&__input {
width: 100%;
&-wrap{
@@ -386,7 +397,7 @@ div.umb-codeeditor .umb-btn-toolbar {
max-height:100%;
margin:auto;
display:block;
background-image: url(../img/checkered-background.png);
background-image: @checkered-background;
}
.umb-sortable-thumbnails li .trashed {
@@ -599,12 +610,18 @@ div.umb-codeeditor .umb-btn-toolbar {
vertical-align: top;
}
.gravity-container .viewport {
max-width: 600px;
}
.gravity-container {
border: 1px solid @gray-8;
line-height: 0;
.gravity-container .viewport:hover {
cursor: pointer;
.viewport {
max-width: 600px;
background: @checkered-background;
&:hover {
cursor: pointer;
}
}
}
.imagecropper {
@@ -617,6 +634,10 @@ div.umb-codeeditor .umb-btn-toolbar {
float: left;
max-width: 100%;
}
.viewport img {
background: @checkered-background;
}
}
.imagecropper .umb-cropper__container {
@@ -884,6 +905,10 @@ div.umb-codeeditor .umb-btn-toolbar {
list-style: none;
vertical-align: middle;
margin-bottom: 0;
img {
background: @checkered-background;
}
}
.umb-fileupload label {
@@ -25,30 +25,31 @@ angular.module("umbraco").controller("Umbraco.Overlays.LinkPickerController",
$scope.showTarget = $scope.model.hideTarget !== true;
if (dialogOptions.currentTarget) {
$scope.model.target = dialogOptions.currentTarget;
// clone the current target so we don't accidentally update the caller's model while manipulating $scope.model.target
$scope.model.target = angular.copy(dialogOptions.currentTarget);
//if we have a node ID, we fetch the current node to build the form data
if ($scope.model.target.id || $scope.model.target.udi) {
//will be either a udi or an int
var id = $scope.model.target.udi ? $scope.model.target.udi : $scope.model.target.id;
if (!$scope.model.target.path) {
// is it a content link?
if (!$scope.model.target.isMedia) {
// get the content path
entityResource.getPath(id, "Document").then(function(path) {
//now sync the tree to this path
$scope.dialogTreeEventHandler.syncTree({
path: path,
tree: "content"
});
});
entityResource.getPath(id, "Document").then(function (path) {
$scope.model.target.path = path;
//now sync the tree to this path
$scope.dialogTreeEventHandler.syncTree({
path: $scope.model.target.path,
tree: "content"
});
});
}
// if a link exists, get the properties to build the anchor name list
contentResource.getById(id).then(function (resp) {
$scope.model.target.url = resp.urls[0];
$scope.anchorValues = tinyMceService.getAnchorNames(JSON.stringify(resp.properties));
});
// get the content properties to build the anchor name list
contentResource.getById(id).then(function (resp) {
$scope.model.target.url = resp.urls[0];
$scope.anchorValues = tinyMceService.getAnchorNames(JSON.stringify(resp.properties));
});
}
} else if ($scope.model.target.url.length) {
// a url but no id/udi indicates an external link - trim the url to remove the anchor/qs
// only do the substring if there's a # or a ?
@@ -122,6 +123,12 @@ angular.module("umbraco").controller("Umbraco.Overlays.LinkPickerController",
$scope.mediaPickerOverlay.show = false;
$scope.mediaPickerOverlay = null;
// make sure the content tree has nothing highlighted
$scope.dialogTreeEventHandler.syncTree({
path: "-1",
tree: "content"
});
}
};
});
@@ -1,7 +0,0 @@
<div>
<form ng-submit="model.submit(model)">
<umb-property property="property" ng-repeat="property in model.properties">
<umb-property-editor model="property"></umb-property-editor>
</umb-property>
</form>
</div>
@@ -1,5 +1,4 @@
<div ng-controller="Umbraco.Overlays.UserController">
<div class="umb-control-group" ng-if="!showPasswordFields">
<h5><localize key="user_yourProfile" /></h5>
@@ -78,7 +77,7 @@
</div>
<div class="umb-control-group" ng-if="!showPasswordFields">
<div class="umb-control-group" ng-if="!showPasswordFields && history.length">
<h5><localize key="user_yourHistory" /></h5>
<ul class="umb-tree">
<li ng-repeat="item in history | orderBy:'time':true">
@@ -126,7 +125,7 @@
</div>
<div class="umb-control-group">
<div class="umb-control-group" ng-if="tab.length">
<div ng-repeat="tab in dashboard">
<div ng-repeat="property in tab.properties">
<div>
@@ -1,4 +1,4 @@
<button ng-click="click()" type="button" class="umb-toggle" ng-class="{'umb-toggle--checked': checked}">
<button ng-click="click()" type="button" class="umb-toggle" ng-disabled="disabled" ng-class="{'umb-toggle--checked': checked, 'umb-toggle--disabled': disabled}">
<span ng-if="!labelPosition && showLabels === 'true' || labelPosition === 'left' && showLabels === 'true'">
<span ng-if="!checked" class="umb-toggle__label umb-toggle__label--left">{{ displayLabelOff }}</span>
@@ -107,7 +107,7 @@
</div>
<div class="umb-package-details__sidebar">
<umb-box data-element="node-info-scheduled-publishing">
<umb-box data-element="node-info-scheduled-publishing" ng-if="allowScheduledPublishing">
<umb-box-header title-key="general_scheduledPublishing"></umb-box-header>
<umb-box-content class="block-form">
@@ -0,0 +1,14 @@
<label class="checkbox umb-form-check umb-form-check--checkbox">
<input type="checkbox" name="{{name}}"
value="{{value}}"
ng-model="model"
class="umb-form-check__input"
ng-required="required" />
<div class="umb-form-check__state umb-form-check__state" aria-hidden="true">
<div class="umb-form-check__check">
<i class="umb-form-check__icon icon-check"></i>
</div>
</div>
<span class="umb-form-check__text">{{text}}</span>
</label>
@@ -0,0 +1,11 @@
<label class="radio umb-form-check umb-form-check--radiobutton">
<input type="radio" name="radiobuttons-{{name}}"
value="{{value}}"
ng-model="model"
class="umb-form-check__input" />
<div class="umb-form-check__state umb-form-check__state" aria-hidden="true">
<div class="umb-form-check__check"></div>
</div>
<span class="umb-form-check__text">{{text}}</span>
</label>
@@ -6,7 +6,7 @@
</div>
</div>
<div class="crop-slider">
<div class="crop-slider" ng-if="loaded">
<i class="icon-picture"></i>
<input
type="range"
@@ -16,4 +16,4 @@
ng-model="dimensions.scale.current" />
<i class="icon-picture" style="font-size: 22px"></i>
</div>
</div>
</div>
@@ -23,7 +23,7 @@
<!-- Icon for files -->
<span class="umb-media-grid__item-file-icon" ng-if="!item.thumbnail && item.extension != 'svg'">
<i class="umb-media-grid__item-icon {{item.icon}}"></i>
<span>.{{item.extension}}</span>
<span ng-if="item.extension">.{{item.extension}}</span>
</span>
</div>
</div>
@@ -3,7 +3,8 @@
$scope,
contentResource,
navigationService,
angularHelper) {
angularHelper,
localizationService) {
var vm = this;
var currentForm;
vm.notifyOptions = [];
@@ -11,7 +12,8 @@
vm.cancel = cancel;
vm.message = {
name: $scope.currentNode.name
};;
};
vm.labels = {};
function onInit() {
vm.loading = true;
contentResource.getNotifySettingsById($scope.currentNode.id).then(function (options) {
@@ -19,6 +21,9 @@
vm.loading = false;
vm.notifyOptions = options;
});
localizationService.localize("notifications_editNotifications", [$scope.currentNode.name]).then(function(value) {
vm.labels.headline = value;
});
}
function cancel() {
navigationService.hideMenu();
@@ -1,5 +1,5 @@
angular.module("umbraco").controller("Umbraco.Editors.Content.RestoreController",
function ($scope, relationResource, contentResource, navigationService, appState, treeService, userService) {
function ($scope, relationResource, contentResource, navigationService, appState, treeService, userService, localizationService) {
var dialogOptions = $scope.dialogOptions;
$scope.source = _.clone(dialogOptions.currentNode);
@@ -21,6 +21,10 @@ angular.module("umbraco").controller("Umbraco.Editors.Content.RestoreController"
userService.getCurrentUser().then(function (userData) {
$scope.treeModel.hideHeader = userData.startContentIds.length > 0 && userData.startContentIds.indexOf(-1) == -1;
});
$scope.labels = {};
localizationService.localizeMany(["treeHeaders_content"]).then(function (data) {
$scope.labels.treeRoot = data[0];
});
function nodeSelectHandler(ev, args) {
@@ -96,7 +100,7 @@ angular.module("umbraco").controller("Umbraco.Editors.Content.RestoreController"
$scope.relation = data[0];
if ($scope.relation.parentId == -1) {
$scope.target = { id: -1, name: "Root" };
$scope.target = { id: -1, name: $scope.labels.treeRoot };
} else {
$scope.loading = true;
@@ -11,14 +11,17 @@
<div ng-show="success">
<div class="alert alert-success">
<strong>{{currentNode.name}}</strong> was copied to
<strong>{{currentNode.name}}</strong>
<localize key="actions_wasCopiedTo">was copied to</localize>
<strong>{{target.name}}</strong>
</div>
<button class="btn btn-primary" ng-click="nav.hideDialog()">Ok</button>
</div>
<p class="abstract" ng-hide="success">
Choose where to copy <strong>{{currentNode.name}}</strong> to in the tree structure below
<localize key="actions_chooseWhereToCopy">Choose where to copy</localize>
<strong>{{currentNode.name}}</strong>
<localize key="actions_toInTheTreeStructureBelow">to in the tree structure below</localize>
</p>
<div class="umb-loader-wrapper" ng-show="busy">
@@ -11,7 +11,9 @@
<div ng-show="success">
<div class="alert alert-success">
<strong>{{currentNode.name}}</strong> was moved underneath&nbsp;<strong>{{target.name}}</strong>
<strong>{{currentNode.name}}</strong>
<localize key="actions_wasMovedTo">was moved to</localize>
<strong>{{target.name}}</strong>
</div>
<button class="btn btn-primary" ng-click="nav.hideDialog()">Ok</button>
</div>
@@ -13,13 +13,13 @@
</div>
<div ng-show="vm.saveSuccces" ng-cloak>
<div class="alert alert-success">
<localize key="notify_notificationsSavedFor"></localize><strong> {{currentNode.name}}</strong>
<localize key="notifications_notificationsSavedFor"></localize> <strong>{{currentNode.name}}</strong>
</div>
<button class="btn btn-primary" ng-click="vm.cancel()"><localize key="general_ok">Ok</localize></button>
</div>
<div ng-hide="vm.saveSuccces || vm.saveError" ng-cloak>
<div class="block-form" ng-show="!vm.loading">
<localize key="notify_notifySet">Set your notification for</localize> <strong>{{ currentNode.name }}</strong>
<span ng-bind-html="vm.labels.headline"></span>
<umb-control-group>
<umb-permission ng-repeat="option in vm.notifyOptions"
name="option.name"
@@ -1,63 +1,138 @@
angular.module("umbraco").controller("Umbraco.Editors.Media.RestoreController",
function ($scope, relationResource, mediaResource, navigationService, appState, treeService, localizationService) {
function ($scope, relationResource, mediaResource, navigationService, appState, treeService, userService, localizationService) {
var dialogOptions = $scope.dialogOptions;
var node = dialogOptions.currentNode;
$scope.source = _.clone(dialogOptions.currentNode);
$scope.error = null;
$scope.success = false;
$scope.error = null;
$scope.loading = true;
$scope.moving = false;
$scope.success = false;
relationResource.getByChildId(node.id, "relateParentDocumentOnDelete").then(function (data) {
$scope.dialogTreeEventHandler = $({});
$scope.searchInfo = {
showSearch: false,
results: [],
selectedSearchResults: []
}
$scope.treeModel = {
hideHeader: false
}
userService.getCurrentUser().then(function (userData) {
$scope.treeModel.hideHeader = userData.startContentIds.length > 0 && userData.startContentIds.indexOf(-1) == -1;
});
$scope.labels = {};
localizationService.localizeMany(["treeHeaders_media"]).then(function (data) {
$scope.labels.treeRoot = data[0];
});
if (data.length == 0) {
$scope.success = false;
$scope.error = {
errorMsg: localizationService.localize('recycleBin_itemCannotBeRestored'),
data: {
Message: localizationService.localize('recycleBin_noRestoreRelation')
}
}
return;
function nodeSelectHandler(ev, args) {
if (args && args.event) {
args.event.preventDefault();
args.event.stopPropagation();
}
if ($scope.target) {
//un-select if there's a current one selected
$scope.target.selected = false;
}
$scope.target = args.node;
$scope.target.selected = true;
}
function nodeExpandedHandler(ev, args) {
// open mini list view for list views
if (args.node.metaData.isContainer) {
openMiniListView(args.node);
}
}
$scope.hideSearch = function () {
$scope.searchInfo.showSearch = false;
$scope.searchInfo.results = [];
}
// method to select a search result
$scope.selectResult = function (evt, result) {
result.selected = result.selected === true ? false : true;
nodeSelectHandler(evt, { event: evt, node: result });
};
//callback when there are search results
$scope.onSearchResults = function (results) {
$scope.searchInfo.results = results;
$scope.searchInfo.showSearch = true;
};
$scope.dialogTreeEventHandler.bind("treeNodeSelect", nodeSelectHandler);
$scope.dialogTreeEventHandler.bind("treeNodeExpanded", nodeExpandedHandler);
$scope.$on('$destroy', function () {
$scope.dialogTreeEventHandler.unbind("treeNodeSelect", nodeSelectHandler);
$scope.dialogTreeEventHandler.unbind("treeNodeExpanded", nodeExpandedHandler);
});
// Mini list view
$scope.selectListViewNode = function (node) {
node.selected = node.selected === true ? false : true;
nodeSelectHandler({}, { node: node });
};
$scope.closeMiniListView = function () {
$scope.miniListView = undefined;
};
function openMiniListView(node) {
$scope.miniListView = node;
}
relationResource.getByChildId($scope.source.id, "relateParentMediaFolderOnDelete").then(function (data) {
$scope.loading = false;
if (!data.length) {
$scope.moving = true;
return;
}
$scope.relation = data[0];
if ($scope.relation.parentId == -1) {
$scope.target = { id: -1, name: "Root" };
$scope.target = { id: -1, name: $scope.labels.treeRoot };
} else {
$scope.loading = true;
mediaResource.getById($scope.relation.parentId).then(function (data) {
$scope.loading = false;
$scope.target = data;
// make sure the target item isn't in the recycle bin
if ($scope.target.path.indexOf("-20") !== -1) {
$scope.error = {
errorMsg: localizationService.localize('recycleBin_itemCannotBeRestored'),
data: {
Message: localizationService.localize('recycleBin_restoreUnderRecycled').then(function (value) {
value.replace('%0%', $scope.target.name);
})
}
};
$scope.success = false;
// make sure the target item isn't in the recycle bin
if ($scope.target.path.indexOf("-21") !== -1) {
$scope.moving = true;
$scope.target = null;
}
}, function (err) {
$scope.success = false;
$scope.loading = false;
$scope.error = err;
});
}
}, function (err) {
$scope.success = false;
$scope.error = err;
$scope.loading = false;
$scope.error = err;
});
$scope.restore = function () {
$scope.restore = function () {
$scope.loading = true;
// this code was copied from `content.move.controller.js`
mediaResource.move({ parentId: $scope.target.id, id: node.id })
mediaResource.move({ parentId: $scope.target.id, id: $scope.source.id })
.then(function (path) {
$scope.loading = false;
$scope.success = true;
//first we need to remove the node that launched the dialog
@@ -78,7 +153,7 @@ angular.module("umbraco").controller("Umbraco.Editors.Media.RestoreController",
});
}, function (err) {
$scope.success = false;
$scope.loading = false;
$scope.error = err;
});
};
@@ -11,7 +11,9 @@
<div ng-show="success">
<div class="alert alert-success">
<strong>{{currentNode.name}}</strong> was moved underneath <strong>{{target.name}}</strong>
<strong>{{currentNode.name}}</strong>
<localize key="actions_wasMovedTo">was moved to</localize>
<strong>{{target.name}}</strong>
</div>
<button class="btn btn-primary" ng-click="nav.hideDialog()">Ok</button>
</div>
@@ -1,25 +1,96 @@
<div ng-controller="Umbraco.Editors.Media.RestoreController">
<div class="umb-dialog-body">
<div class="umb-dialog-body" ng-cloak>
<umb-pane>
<umb-load-indicator
ng-if="loading">
</umb-load-indicator>
<p class="abstract" ng-hide="error != null || success == true">
<localize key="actions_restore">Restore</localize> <strong>{{currentNode.name}}</strong> <localize key="general_under">under</localize> <strong>{{target.name}}</strong>?
</p>
<div ng-show="error">
<div class="alert alert-error">
<div><strong>{{error.errorMsg}}</strong></div>
<div>{{error.data.Message}}</div>
</div>
</div>
<div class="alert alert-error" ng-show="error != null">
<div><strong>{{error.errorMsg}}</strong></div>
<div>{{error.data.Message}}</div>
</div>
<div ng-show="success">
<div class="alert alert-success">
<strong>{{source.name}}</strong>
<span ng-hide="moving"><localize key="recycleBin_wasRestored">was restored under</localize></span>
<span ng-show="moving"><localize key="editdatatype_wasMoved">was moved underneath</localize></span>
<strong>{{target.name}}</strong>
</div>
<button class="btn btn-primary" ng-click="nav.hideDialog()">Ok</button>
</div>
<div class="alert alert-success" ng-show="success == true">
<p><strong>{{currentNode.name}}</strong> <localize key="editdatatype_wasMoved">was moved underneath</localize> <strong>{{target.name}}</strong></p>
<button class="btn btn-primary" ng-click="nav.hideDialog()"><localize key="general_ok">OK</localize></button>
</div>
<div ng-hide="moving || loading || success">
<p class="abstract" ng-hide="error || success">
<localize key="actions_restore">Restore</localize> <strong>{{source.name}}</strong> <localize key="general_under">under</localize> <strong>{{target.name}}</strong>?
</p>
</div>
<div ng-hide="!moving || loading || success">
<div>
<div class="alert alert-info">
<div><strong><localize key="recycleBin_itemCannotBeRestored">Cannot automatically restore this item</localize></strong></div>
<div><localize key="recycleBin_itemCannotBeRestoredHelpText">There is no location where this item can be automatically restored. You can move the item manually using the tree below.</localize></div>
</div>
</div>
<div ng-hide="miniListView">
<umb-tree-search-box
hide-search-callback="hideSearch"
search-callback="onSearchResults"
show-search="{{searchInfo.showSearch}}"
section="media">
</umb-tree-search-box>
<br />
<umb-tree-search-results
ng-if="searchInfo.showSearch"
results="searchInfo.results"
select-result-callback="selectResult">
</umb-tree-search-results>
<div ng-hide="searchInfo.showSearch">
<umb-tree
section="media"
hideheader="{{treeModel.hideHeader}}"
hideoptions="true"
isdialog="true"
eventhandler="dialogTreeEventHandler"
enablelistviewexpand="true"
enablecheckboxes="true">
</umb-tree>
</div>
</div>
<umb-mini-list-view
ng-if="miniListView"
node="miniListView"
entity-type="Document"
on-select="selectListViewNode(node)"
on-close="closeMiniListView()">
</umb-mini-list-view>
</div>
</umb-pane>
</div>
<div class="umb-dialog-footer btn-toolbar umb-btn-toolbar" ng-hide="success == true">
<div class="umb-dialog-footer btn-toolbar umb-btn-toolbar" ng-hide="loading || moving || success">
<a class="btn btn-link" ng-click="nav.hideDialog()"><localize key="general_cancel">Cancel</localize></a>
<button class="btn btn-primary" ng-click="restore()" ng-show="error == null"><localize key="actions_restore">Restore</localize></button>
</div>
<div class="umb-dialog-footer btn-toolbar umb-btn-toolbar" ng-hide="loading || !moving || success">
<a class="btn btn-link" ng-click="nav.hideDialog()"><localize key="general_cancel">Cancel</localize></a>
<button class="btn btn-primary" ng-click="restore()" ng-show="error == null" ng-disabled="!target"><localize key="actions_move">Move</localize></button>
</div>
<div class="umb-dialog-footer btn-toolbar umb-btn-toolbar" ng-hide="success == true">
<a class="btn btn-link" ng-click="nav.hideDialog()"><localize key="general_cancel">Cancel</localize></a>
<button class="btn btn-primary" ng-click="restore()" ng-show="error == null"><localize key="actions_restore">Restore</localize></button>
</div>
@@ -57,7 +57,7 @@
</div>
</div>
<umb-control-group label="Enter a folder name" hide-label="false">
<umb-control-group label="@create_enterFolderName" localize="label" hide-label="false">
<input type="text" name="folderName" ng-model="vm.folderName" class="umb-textstring textstring input-block-level" umb-auto-focus required />
</umb-control-group>
@@ -12,6 +12,9 @@ function PartialViewsDeleteController($scope, codefileResource, treeService, nav
//mark it for deletion (used in the UI)
$scope.currentNode.loading = true;
// Reset the error message
$scope.error = null;
codefileResource.deleteByPath('partialViews', $scope.currentNode.id)
.then(function() {
@@ -21,6 +24,9 @@ function PartialViewsDeleteController($scope, codefileResource, treeService, nav
//TODO: Need to sync tree, etc...
treeService.removeNode($scope.currentNode);
navigationService.hideMenu();
}, function (err) {
$scope.currentNode.loading = false;
$scope.error = err;
});
};
@@ -1,6 +1,13 @@
<div class="umb-dialog umb-pane" ng-controller="Umbraco.Editors.PartialViews.DeleteController">
<div class="umb-dialog-body">
<div ng-show="error">
<div class="alert alert-error">
<div><strong>{{error.errorMsg}}</strong></div>
<div>{{error.data.message}}</div>
</div>
</div>
<p class="umb-abstract">
<localize key="defaultdialogs_confirmdelete">Are you sure you want to delete</localize> <strong>{{currentNode.name}}</strong> ?
</p>
@@ -1,4 +1,4 @@
function booleanEditorController($scope) {
function booleanEditorController($scope, angularHelper) {
function setupViewModel() {
$scope.renderModel = {
@@ -28,7 +28,8 @@ function booleanEditorController($scope) {
};
// Update the value when the toggle is clicked
$scope.toggle = function(){
$scope.toggle = function () {
angularHelper.getCurrentForm($scope).$setDirty();
if($scope.renderModel.value){
$scope.model.value = "0";
setupViewModel();
@@ -1,14 +1,8 @@
<div class="umb-editor umb-checkboxlist" ng-controller="Umbraco.PropertyEditors.CheckboxListController">
<div class="umb-editor umb-editor--list" ng-controller="Umbraco.PropertyEditors.CheckboxListController">
<ul class="unstyled">
<li ng-repeat="item in selectedItems">
<label class="checkbox">
<input type="checkbox" name="checkboxlist"
value="{{item.key}}"
ng-model="item.checked"
ng-required="model.validation.mandatory && !model.value.length" />
{{item.val}}
</label>
<li ng-repeat="item in selectedItems" class="umb-editor__item">
<umb-checkbox name="checkboxlist" value="{{item.key}}" model="item.checked" text="{{item.val}}" required="model.validation.mandatory && !model.value.length"></umb-checkbox>
</li>
</ul>
@@ -1,4 +1,4 @@
function ColorPickerController($scope) {
function ColorPickerController($scope, angularHelper) {
//setup the default config
var config = {
@@ -12,32 +12,13 @@ function ColorPickerController($scope) {
//map back to the model
$scope.model.config = config;
function convertArrayToDictionaryArray(model) {
//now we need to format the items in the dictionary because we always want to have an array
var newItems = [];
for (var i = 0; i < model.length; i++) {
newItems.push({ id: model[i], sortOrder: 0, value: model[i] });
}
return newItems;
}
function convertObjectToDictionaryArray(model) {
//now we need to format the items in the dictionary because we always want to have an array
var newItems = [];
var vals = _.values($scope.model.config.items);
var keys = _.keys($scope.model.config.items);
for (var i = 0; i < vals.length; i++) {
var label = vals[i].value ? vals[i].value : vals[i];
newItems.push({ id: keys[i], sortOrder: vals[i].sortOrder, value: label });
}
return newItems;
}
$scope.isConfigured = $scope.model.config && $scope.model.config.items && _.keys($scope.model.config.items).length > 0;
$scope.model.activeColor = {
value: "",
label: ""
};
if ($scope.isConfigured) {
for (var key in $scope.model.config.items) {
@@ -77,29 +58,7 @@ function ColorPickerController($scope) {
//now make the editor model the array
$scope.model.config.items = items;
}
$scope.toggleItem = function (color) {
var currentColor = ($scope.model.value && $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 () {
var isValid = !$scope.model.validation.mandatory || (
@@ -115,33 +74,48 @@ function ColorPickerController($scope) {
}
$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) {
$scope.onSelect = function (color) {
// did the value change?
if ($scope.model.value != null && $scope.model.value.value === color) {
// User clicked the currently selected color
// to remove the selection, they don't want
// to select any color after all.
// Unselect the color and mark as dirty
$scope.model.activeColor = null;
$scope.model.value = null;
angularHelper.getCurrentForm($scope).$setDirty();
// no value
if (!$scope.model.value)
return false;
return;
}
// 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;
};
// yes, update the model (label + value) according to the new color
var selectedItem = _.find($scope.model.config.items, function (item) {
return item.value === color;
});
if (!selectedItem) {
return;
}
$scope.model.value = {
label: selectedItem.label,
value: selectedItem.value
};
// make sure to set dirty
angularHelper.getCurrentForm($scope).$setDirty();
}
// 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
// no value - initialize default value
if (!$scope.model.value)
return;
// Complex color (value and label)?
if (!$scope.model.value.hasOwnProperty("value"))
return;
// Backwards compatibility, the color used to be stored as a hex value only
if (typeof $scope.model.value === "string") {
$scope.model.value = { value: $scope.model.value, label: $scope.model.value };
}
var modelColor = $scope.model.value.value;
var modelLabel = $scope.model.value.label;
@@ -182,8 +156,8 @@ function ColorPickerController($scope) {
// 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;
$scope.model.activeColor.value = foundItem.value;
$scope.model.activeColor.label = foundItem.label;
}
}
@@ -6,9 +6,10 @@
</div>
<umb-color-swatches colors="model.config.items"
selected-color="model.value.value"
selected-color="model.activeColor.value"
size="m"
use-label="model.useLabel">
use-label="model.useLabel"
on-select="onSelect(color)">
</umb-color-swatches>
<input type="hidden" name="modelValue" ng-model="model.value" val-property-validator="validateMandatory" />
@@ -35,7 +35,6 @@ function contentPickerController($scope, entityResource, editorState, iconHelper
return $scope.model.config.idType === "udi" ? i.udi : i.id;
});
$scope.model.value = trim(currIds.join(), ",");
angularHelper.getCurrentForm($scope).$setDirty();
//Validate!
if ($scope.model.config && $scope.model.config.minNumber && parseInt($scope.model.config.minNumber) > $scope.renderModel.length) {
@@ -84,7 +83,10 @@ function contentPickerController($scope, entityResource, editorState, iconHelper
opacity: 0.7,
tolerance: "pointer",
scroll: true,
zIndex: 6000
zIndex: 6000,
update: function (e, ui) {
angularHelper.getCurrentForm($scope).$setDirty();
}
};
if ($scope.model.config) {
@@ -145,9 +145,9 @@ function dateTimePickerController($scope, notificationsService, assetsService, a
var element = $element.find("div:first");
// Open the datepicker and add a changeDate eventlistener
// Open the datepicker and add a changeDate eventlistener
element
.datetimepicker(angular.extend({ useCurrent: true }, $scope.model.config))
.datetimepicker(angular.extend({ useCurrent: $scope.model.config.defaultEmpty !== "1" }, $scope.model.config))
.on("dp.change", applyDate)
.on("dp.error", function(a, b, c) {
$scope.hasDatetimePickerValue = false;
@@ -52,6 +52,7 @@ angular.module('umbraco')
});
editedCrop.coordinates = $scope.currentCrop.coordinates;
$scope.close();
angularHelper.getCurrentForm($scope).$setDirty();
};
//reset the current crop
@@ -98,6 +99,10 @@ angular.module('umbraco')
$scope.hasDimensions = hasDimensions;
};
$scope.focalPointChanged = function () {
angularHelper.getCurrentForm($scope).$setDirty();
}
//on image selected, update the cropper
$scope.$on("filesSelected", function (ev, args) {
$scope.model.value = config;
@@ -40,7 +40,8 @@
<umb-image-gravity
src="imageSrc"
center="model.value.focalPoint"
on-image-loaded="imageLoaded(isCroppable, hasDimensions)">
on-image-loaded="imageLoaded(isCroppable, hasDimensions)"
on-gravity-changed="focalPointChanged()">
</umb-image-gravity>
<a href class="btn btn-link btn-crop-delete" ng-click="clear()"><i class="icon-delete red"></i> <localize key="content_uploadClear">Remove file</localize></a>
</div>
@@ -1,4 +1,4 @@
function listViewController($rootScope, $scope, $routeParams, $injector, $cookieStore, notificationsService, iconHelper, dialogService, editorState, localizationService, $location, appState, $timeout, $q, mediaResource, listViewHelper, userService, navigationService, treeService) {
function listViewController($rootScope, $scope, $routeParams, $injector, $cookieStore, notificationsService, iconHelper, dialogService, editorState, localizationService, $location, appState, $timeout, $q, mediaResource, listViewHelper, userService, navigationService, treeService, mediaHelper) {
//this is a quick check to see if we're in create mode, if so just exit - we cannot show children for content
// that isn't created yet, if we continue this will use the parent id in the route params which isn't what
@@ -269,10 +269,12 @@ function listViewController($rootScope, $scope, $routeParams, $injector, $cookie
$scope.listViewResultSet = data;
//update all values for display
var section = appState.getSectionState("currentSection");
if ($scope.listViewResultSet.items) {
_.each($scope.listViewResultSet.items, function (e, index) {
setPropertyValues(e);
if (e.contentTypeAlias === 'Folder') {
// create the folders collection (only for media list views)
if (section === "media" && !mediaHelper.hasFilePropertyType(e)) {
$scope.folders.push(e);
}
});
@@ -0,0 +1,133 @@
function multiUrlPickerController($scope, angularHelper, localizationService, entityResource, iconHelper) {
$scope.renderModel = [];
if ($scope.preview) {
return;
}
if (!Array.isArray($scope.model.value)) {
$scope.model.value = [];
}
var currentForm = angularHelper.getCurrentForm($scope);
$scope.sortableOptions = {
distance: 10,
tolerance: "pointer",
scroll: true,
zIndex: 6000,
update: function () {
currentForm.$setDirty();
}
};
$scope.model.value.forEach(function (link) {
link.icon = iconHelper.convertFromLegacyIcon(link.icon);
$scope.renderModel.push(link);
});
$scope.$on("formSubmitting", function () {
$scope.model.value = $scope.renderModel;
});
$scope.$watch(
function () {
return $scope.renderModel.length;
},
function () {
if ($scope.model.config && $scope.model.config.minNumber) {
$scope.multiUrlPickerForm.minCount.$setValidity(
"minCount",
+$scope.model.config.minNumber <= $scope.renderModel.length
);
}
if ($scope.model.config && $scope.model.config.maxNumber) {
$scope.multiUrlPickerForm.maxCount.$setValidity(
"maxCount",
+$scope.model.config.maxNumber >= $scope.renderModel.length
);
}
$scope.sortableOptions.disabled = $scope.renderModel.length === 1;
}
);
$scope.remove = function ($index) {
$scope.renderModel.splice($index, 1);
currentForm.$setDirty();
};
$scope.openLinkPicker = function (link, $index) {
var target = link ? {
name: link.name,
anchor: link.queryString,
// the linkPicker breaks if it get an udi for media
udi: link.isMedia ? null : link.udi,
url: link.url,
target: link.target
} : null;
$scope.linkPickerOverlay = {
view: "linkpicker",
currentTarget: target,
show: true,
submit: function (model) {
if (model.target.url || model.target.anchor) {
// if an anchor exists, check that it is appropriately prefixed
if (model.target.anchor && model.target.anchor[0] !== '?' && model.target.anchor[0] !== '#') {
model.target.anchor = (model.target.anchor.indexOf('=') === -1 ? '#' : '?') + model.target.anchor;
}
if (link) {
if (link.isMedia && link.url === model.target.url) {
// we can assume the existing media item is changed and no new file has been selected
// so we don't need to update the udi and isMedia fields
} else {
link.udi = model.target.udi;
link.isMedia = model.target.isMedia;
}
link.name = model.target.name || model.target.url || model.target.anchor;
link.queryString = model.target.anchor;
link.target = model.target.target;
link.url = model.target.url;
} else {
link = {
isMedia: model.target.isMedia,
name: model.target.name || model.target.url || model.target.anchor,
queryString: model.target.anchor,
target: model.target.target,
udi: model.target.udi,
url: model.target.url
};
$scope.renderModel.push(link);
}
if (link.udi) {
var entityType = link.isMedia ? "media" : "document";
entityResource.getById(link.udi, entityType).then(function (data) {
link.icon = iconHelper.convertFromLegacyIcon(data.icon);
link.published = (data.metaData && data.metaData.IsPublished === false && entityType === "Document") ? false : true;
link.trashed = data.trashed;
if (link.trashed) {
item.url = localizationService.dictionary.general_recycleBin;
}
});
} else {
link.icon = "icon-link";
link.published = true;
}
currentForm.$setDirty();
}
$scope.linkPickerOverlay.show = false;
$scope.linkPickerOverlay = null;
}
};
};
}
angular.module("umbraco").controller("Umbraco.PropertyEditors.MultiUrlPickerController", multiUrlPickerController);
@@ -0,0 +1,79 @@
<div ng-controller="Umbraco.PropertyEditors.MultiUrlPickerController" 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="multiUrlPickerForm">
<div ui-sortable="sortableOptions" ng-model="renderModel">
<umb-node-preview
ng-repeat="link in renderModel"
icon="link.icon"
name="link.name"
published="link.published"
description="link.url + (link.queryString ? link.queryString : '')"
sortable="!sortableOptions.disabled"
allow-remove="true"
allow-edit="true"
on-remove="remove($index)"
on-edit="openLinkPicker(link, $index)">
</umb-node-preview>
</div>
<a ng-show="!model.config.maxNumber || renderModel.length < model.config.maxNumber"
class="umb-node-preview-add"
href
ng-click="openLinkPicker()"
prevent-default>
<localize key="general_add">Add</localize>
</a>
<div class="umb-contentpicker__min-max-help">
<!-- Both min and max items -->
<span ng-if="model.config.minNumber && model.config.maxNumber && model.config.minNumber !== model.config.maxNumber">
<span ng-if="renderModel.length < model.config.maxNumber">Add between {{model.config.minNumber}} and {{model.config.maxNumber}} items</span>
<span ng-if="renderModel.length > model.config.maxNumber">
<localize key="validation_maxCount">You can only have</localize> {{model.config.maxNumber}} <localize key="validation_itemsSelected"> items selected</localize>
</span>
</span>
<!-- Equal min and max -->
<span ng-if="model.config.minNumber && model.config.maxNumber && model.config.minNumber === model.config.maxNumber">
<span ng-if="renderModel.length < model.config.maxNumber">Add {{model.config.minNumber - renderModel.length}} item(s)</span>
<span ng-if="renderModel.length > model.config.maxNumber">
<localize key="validation_maxCount">You can only have</localize> {{model.config.maxNumber}} <localize key="validation_itemsSelected"> items selected</localize>
</span>
</span>
<!-- Only max -->
<span ng-if="!model.config.minNumber && model.config.maxNumber">
<span ng-if="renderModel.length < model.config.maxNumber">Add up to {{model.config.maxNumber}} items</span>
<span ng-if="renderModel.length > model.config.maxNumber">
<localize key="validation_maxCount">You can only have</localize> {{model.config.maxNumber}} <localize key="validation_itemsSelected">items selected</localize>
</span>
</span>
<!-- Only min -->
<span ng-if="model.config.minNumber && !model.config.maxNumber && renderModel.length < model.config.minNumber">
Add at least {{model.config.minNumber}} item(s)
</span>
</div>
<!--These are here because we need ng-form fields to validate against-->
<input type="hidden" name="minCount" ng-model="renderModel" />
<input type="hidden" name="maxCount" ng-model="renderModel" />
<div class="help-inline" val-msg-for="minCount" val-toggle-msg="minCount">
<localize key="validation_minCount">You need to add at least</localize> {{model.config.minNumber}} <localize key="validation_items">items</localize>
</div>
<div class="help-inline" val-msg-for="maxCount" val-toggle-msg="maxCount">
<localize key="validation_maxCount">You can only have</localize> {{model.config.maxNumber}} <localize key="validation_itemsSelected">items selected</localize>
</div>
</ng-form>
<umb-overlay ng-if="linkPickerOverlay.show"
model="linkPickerOverlay"
view="linkPickerOverlay.view"
position="right">
</umb-overlay>
</div>
@@ -1,12 +1,8 @@
<div class="umb-editor umb-radiobuttons" ng-controller="Umbraco.PropertyEditors.RadioButtonsController">
<div class="umb-editor umb-edtitor--list" ng-controller="Umbraco.PropertyEditors.RadioButtonsController">
<ul class="unstyled">
<li ng-repeat="item in model.config.items">
<label class="radio">
<input type="radio" name="radiobuttons-{{model.alias}}"
value="{{item.id}}"
ng-model="model.value" />
{{item.value}}
</label>
<li ng-repeat="item in model.config.items" class="umb-editor__item">
<umb-radiobutton name="{{model.alias}}" value="{{item.id}}" model="model.value" text="{{item.value}}"></umb-radiobutton>
</li>
</ul>
</div>
</div>
@@ -278,7 +278,7 @@ angular.module("umbraco")
$scope.linkPickerOverlay = {
view: "linkpicker",
currentTarget: currentTarget,
anchors: tinyMceService.getAnchorNames(JSON.stringify(editorState.current.properties)),
anchors: editorState.current ? tinyMceService.getAnchorNames(JSON.stringify(editorState.current.properties)) : [],
show: true,
submit: function(model) {
tinyMceService.insertLinkInEditor(editor, model.target, anchorElement);
@@ -12,6 +12,10 @@ function TemplatesDeleteController($scope, templateResource , treeService, navig
//mark it for deletion (used in the UI)
$scope.currentNode.loading = true;
// Reset the error message
$scope.error = null;
templateResource.deleteById($scope.currentNode.id).then(function () {
$scope.currentNode.loading = false;
@@ -21,6 +25,9 @@ function TemplatesDeleteController($scope, templateResource , treeService, navig
//TODO: Need to sync tree, etc...
treeService.removeNode($scope.currentNode);
navigationService.hideMenu();
}, function (err) {
$scope.currentNode.loading = false;
$scope.error = err;
});
};
@@ -1,11 +1,18 @@
<div class="umb-dialog umb-pane" ng-controller="Umbraco.Editors.Templates.DeleteController">
<div class="umb-dialog-body">
<div ng-show="error">
<div class="alert alert-error">
<div><strong>{{error.errorMsg}}</strong></div>
<div>{{error.data.message}}</div>
</div>
</div>
<p class="umb-abstract">
<localize key="defaultdialogs_confirmdelete">Are you sure you want to delete</localize>&nbsp;<strong>{{currentNode.name}}</strong> ?
</p>
<umb-confirm on-confirm="performDelete" on-cancel="cancel">
<umb-confirm on-confirm="performDelete" on-cancel="cancel">
</umb-confirm>
</div>
-3
View File
@@ -1,3 +0,0 @@
/Umbraco/**
/Umbraco_Client/**
+2 -3
View File
@@ -520,7 +520,6 @@
</Content>
<Content Include="Umbraco\Install\Views\Web.config" />
<Content Include="App_Plugins\ModelsBuilder\package.manifest" />
<Content Include=".eslintignore" />
<None Include="Config\404handlers.Release.config">
<DependentUpon>404handlers.config</DependentUpon>
</None>
@@ -1039,9 +1038,9 @@ xcopy "$(ProjectDir)"..\packages\SqlServerCE.4.0.0.1\x86\*.* "$(TargetDir)x86\"
<WebProjectProperties>
<UseIIS>True</UseIIS>
<AutoAssignPort>True</AutoAssignPort>
<DevelopmentServerPort>7130</DevelopmentServerPort>
<DevelopmentServerPort>7140</DevelopmentServerPort>
<DevelopmentServerVPath>/</DevelopmentServerVPath>
<IISUrl>http://localhost:7130</IISUrl>
<IISUrl>http://localhost:7140</IISUrl>
<NTLMAuthentication>False</NTLMAuthentication>
<UseCustomServer>False</UseCustomServer>
<CustomServerUrl>
@@ -1350,4 +1350,4 @@
<key alias="enabledConfirm">轉址追蹤器已開啟。</key>
<key alias="enableError">啟動轉址追蹤器錯誤,更多資訊請參閱您的紀錄檔。</key>
</area>
</language>
</language>
+15 -15
View File
@@ -8,19 +8,19 @@ For details on the format of this configuration file see:
https://our.umbraco.com/documentation/reference/config/healthchecks
-->
<HealthChecks>
<disabledChecks>
<!--<check id="1B5D221B-CE99-4193-97CB-5F3261EC73DF" disabledOn="" disabledBy="0" />-->
</disabledChecks>
<notificationSettings enabled="true" firstRunTime="" periodInHours="24">
<notificationMethods>
<notificationMethod alias="email" enabled="true" verbosity="Summary">
<settings>
<add key="recipientEmail" value="" />
</settings>
</notificationMethod>
</notificationMethods>
<disabledChecks>
<!--<check id="EB66BB3B-1BCD-4314-9531-9DA2C1D6D9A7" disabledOn="" disabledBy="0" />-->
</disabledChecks>
</notificationSettings>
</HealthChecks>
<!--<check id="1B5D221B-CE99-4193-97CB-5F3261EC73DF" disabledOn="" disabledBy="0" />-->
</disabledChecks>
<notificationSettings enabled="true" firstRunTime="" periodInHours="24">
<notificationMethods>
<notificationMethod alias="email" enabled="true" verbosity="Summary">
<settings>
<add key="recipientEmail" value="" />
</settings>
</notificationMethod>
</notificationMethods>
<disabledChecks>
<!--<check id="EB66BB3B-1BCD-4314-9531-9DA2C1D6D9A7" disabledOn="" disabledBy="0" />-->
</disabledChecks>
</notificationSettings>
</HealthChecks>
@@ -6,11 +6,11 @@
https://our.umbraco.com/documentation/using-umbraco/config-files/umbracoSettings/
Many of the optional settings are not explicitly listed here
but can be found in the online documentation.
-->
-->
<backOffice>
<tours enable="true"></tours>
</backOffice>
</backOffice>
<content>
@@ -32,7 +32,7 @@
<notifications>
<!-- the email that should be used as from mail when umbraco sends a notification -->
<!-- you can add a display name to the email like thist: <email>Your display name here &lt;your@email.here&gt;</email> -->
<!-- you can add a display name to the email like this: <email>Your display name here &lt;your@email.here&gt;</email> -->
<email>your@email.here</email>
</notifications>
@@ -61,14 +61,14 @@
<EnablePropertyValueConverters>true</EnablePropertyValueConverters>
<!-- You can specify your own background image for the login screen here. The image will automatically get an overlay to match back office colors - this path is relative to the ~/umbraco path. The default location is: /umbraco/assets/img/installer.jpg -->
<loginBackgroundImage>assets/img/installer.jpg</loginBackgroundImage>
<loginBackgroundImage>assets/img/installer.jpg</loginBackgroundImage>
</content>
<security>
<!-- set to true to auto update login interval (and there by disabling the lock screen -->
<keepUserLoggedIn>false</keepUserLoggedIn>
<!-- by default this is true and if not specified in config will be true. set to false to always show a separate username field in the back office user editor -->
<!-- by default this is true and if not specified in config will be true. set to false to always show a separate username field in the back office user editor -->
<usernameIsEmail>true</usernameIsEmail>
<!-- change in 4.8: Disabled users are now showed dimmed and last in the tree. If you prefer not to display them set this to true -->
<hideDisabledUsersInBackoffice>false</hideDisabledUsersInBackoffice>
+16 -4
View File
@@ -32,8 +32,11 @@
<key alias="rename" version="7.3.0">Omdøb</key>
<key alias="restore" version="7.3.0">Gendan</key>
<key alias="SetPermissionsForThePage">Sæt rettigheder for siden %0%</key>
<key alias="chooseWhereToCopy">Vælg hvor du vil kopiere</key>
<key alias="chooseWhereToMove">Vælg hvortil du vil flytte</key>
<key alias="toInTheTreeStructureBelow">I træstrukturen nedenfor</key>
<key alias="toInTheTreeStructureBelow">til i træstrukturen nedenfor</key>
<key alias="wasMovedTo">blev flyttet til</key>
<key alias="wasCopiedTo">blev kopieret til</key>
<key alias="rights">Rettigheder</key>
<key alias="rollback">Fortryd ændringer</key>
<key alias="sendtopublish">Send til udgivelse</key>
@@ -179,6 +182,11 @@
<key alias="validationErrorPropertyWithMoreThanOneMapping">Overførsel af egenskaber kunne ikke fuldføres, da en eller flere egenskaber er indstillet til at blive overført mere end én gang.</key>
<key alias="validDocTypesNote">Kun andre dokumenttyper, der er gyldige på denne placering, vises.</key>
</area>
<area alias="codefile">
<key alias="createFolderFailedById">Oprettelse af mappen under parent med ID %0% fejlede</key>
<key alias="createFolderFailedByName">Oprettelse af mappen under parent med navnet %0% fejlede</key>
<key alias="deleteItemFailed">Sletning af filen/mappen fejlede: %0%</key>
</area>
<area alias="content">
<key alias="isPublished" version="7.2">Udgivet</key>
<key alias="about">Om siden</key>
@@ -279,6 +287,7 @@
<key alias="chooseNode">Hvor ønsker du at oprette den nye %0%</key>
<key alias="createUnder">Opret under</key>
<key alias="createContentBlueprint">Vælg den dokumenttype, du vil oprette en indholdsskabelon til</key>
<key alias="enterFolderName">Angiv et navn for mappen</key>
<key alias="updateData">Vælg en type og skriv en titel</key>
<key alias="noDocumentTypes" version="7.0"><![CDATA[Der kunne ikke findes nogen tilladte dokument typer. Du skal tillade disse i indstillinger under <strong>"dokument typer"</strong>.]]></key>
<key alias="noMediaTypes" version="7.0"><![CDATA[Der kunne ikke findes nogen tilladte media typer. Du skal tillade disse i indstillinger under <strong>"media typer"</strong>.]]></key>
@@ -830,7 +839,8 @@
<key alias="relateToOriginal">Relater det kopierede element til originalen</key>
</area>
<area alias="notifications">
<key alias="editNotifications">Rediger dine notificeringer for %0%</key>
<key alias="editNotifications"><![CDATA[Vælg dine notificeringer for <strong>%0%</strong>]]></key>
<key alias="notificationsSavedFor">Notificeringer er gemt for</key>
<key alias="mailBody">
<![CDATA[
Hej %0%
@@ -1004,6 +1014,7 @@ Mange hilsner fra Umbraco robotten
<area alias="rollback">
<key alias="headline">Vælg en version at sammenligne med den nuværende version</key>
<key alias="currentVersion">Nuværende version</key>
<key alias="diffHelp"><![CDATA[Her vises forskellene mellem den nuværende version og den valgte version<br /><del>Rød</del> tekst vil ikke blive vist i den valgte version. <ins>Grøn betyder tilføjet</ins>]]></key>
<key alias="documentRolledBack">Dokument tilbagerullet</key>
@@ -1153,6 +1164,7 @@ Mange hilsner fra Umbraco robotten
</area>
<area alias="template">
<key alias="deleteByIdFailed">Sletning af skabelonen med ID %0% fejlede</key>
<key alias="edittemplate">Rediger skabelon</key>
<key alias="insertSections">Sektioner</key>
@@ -1446,9 +1458,9 @@ Mange hilsner fra Umbraco robotten
<key alias="macros">Makroer</key>
<key alias="mediaTypes">Medietyper</key>
<key alias="member">Medlemmer</key>
<key alias="memberGroups">Medlemsgruppe</key>
<key alias="memberGroups">Medlemsgrupper</key>
<key alias="memberRoles">Roller</key>
<key alias="memberTypes">Medlemstype</key>
<key alias="memberTypes">Medlemstyper</key>
<key alias="documentTypes">Dokumenttyper</key>
<key alias="relationTypes">Relationstyper</key>
<key alias="packager">Pakker</key>
+17 -2
View File
@@ -33,8 +33,11 @@
<key alias="rename" version="7.3.0">Rename</key>
<key alias="restore" version="7.3.0">Restore</key>
<key alias="SetPermissionsForThePage">Set permissions for the page %0%</key>
<key alias="chooseWhereToCopy">Choose where to copy</key>
<key alias="chooseWhereToMove">Choose where to move</key>
<key alias="toInTheTreeStructureBelow">In the tree structure below</key>
<key alias="toInTheTreeStructureBelow">to in the tree structure below</key>
<key alias="wasMovedTo">was moved to</key>
<key alias="wasCopiedTo">was copied to</key>
<key alias="rights">Permissions</key>
<key alias="rollback">Rollback</key>
<key alias="sendtopublish">Send To Publish</key>
@@ -185,6 +188,11 @@
<key alias="validationErrorPropertyWithMoreThanOneMapping">Could not complete property mapping as one or more properties have more than one mapping defined.</key>
<key alias="validDocTypesNote">Only alternate types valid for the current location are displayed.</key>
</area>
<area alias="codefile">
<key alias="createFolderFailedById">Failed to create a folder under parent with ID %0%</key>
<key alias="createFolderFailedByName">Failed to create a folder under parent with name %0%</key>
<key alias="deleteItemFailed">Failed to delete item: %0%</key>
</area>
<area alias="content">
<key alias="isPublished" version="7.2">Is Published</key>
<key alias="about">About this page</key>
@@ -287,6 +295,7 @@
<key alias="chooseNode">Where do you want to create the new %0%</key>
<key alias="createUnder">Create an item under</key>
<key alias="createContentBlueprint">Select the document type you want to make a content template for</key>
<key alias="enterFolderName">Enter a folder name</key>
<key alias="updateData">Choose a type and a title</key>
<key alias="noDocumentTypes" version="7.0"><![CDATA[There are no allowed document types available. You must enable these in the settings section under <strong>"document types"</strong>.]]></key>
<key alias="noMediaTypes" version="7.0"><![CDATA[There are no allowed media types available. You must enable these in the settings section under <strong>"media types"</strong>.]]></key>
@@ -1038,7 +1047,8 @@ To manage your website, simply open the Umbraco back office and start adding con
<key alias="relateToOriginal">Relate copied items to original</key>
</area>
<area alias="notifications">
<key alias="editNotifications">Edit your notification for %0%</key>
<key alias="editNotifications"><![CDATA[Select your notification for <strong>%0%</strong>]]></key>
<key alias="notificationsSavedFor">Notification settings saved for</key>
<key alias="mailBody">
<![CDATA[
Hi %0%
@@ -1310,6 +1320,7 @@ To manage your website, simply open the Umbraco back office and start adding con
<key alias="undoEditCrop">Undo edits</key>
</area>
<area alias="rollback">
<key alias="headline">Select a version to compare with the current version</key>
<key alias="currentVersion">Current version</key>
<key alias="diffHelp"><![CDATA[This shows the differences between the current version and the selected version<br /><del>Red</del> text will not be shown in the selected version. , <ins>green means added</ins>]]></key>
<key alias="documentRolledBack">Document has been rolled back</key>
@@ -1478,6 +1489,7 @@ To manage your website, simply open the Umbraco back office and start adding con
</area>
<area alias="template">
<key alias="deleteByIdFailed">Failed to delete template with ID %0%</key>
<key alias="edittemplate">Edit template</key>
<key alias="insertSections">Sections</key>
@@ -2194,6 +2206,9 @@ To manage your website, simply open the Umbraco back office and start adding con
<key alias="notificationEmailsCheckErrorMessage"><![CDATA[Notification email is still set to the default value of <strong>%0%</strong>.]]></key>
<key alias="scheduledHealthCheckEmailBody"><![CDATA[<html><body><p>Results of the scheduled Umbraco Health Checks run on %0% at %1% are as follows:</p>%2%</body></html>]]></key>
<key alias="scheduledHealthCheckEmailSubject">Umbraco Health Check Status: %0%</key>
<key alias="tls12HealthCheckSuccess">Your site can use the TLS 1.2 security protocol when making outbound connections to HTTPS endpoints.</key>
<key alias="tls12HealthCheckWarn">Your site isn't configured to allow the TLS 1.2 security protocol when making outbound connections: some HTTPS endpoints might not be reachable using a less secure protocol.</key>
</area>
<area alias="redirectUrls">
<key alias="disableUrlTracker">Disable URL tracker</key>
@@ -33,8 +33,11 @@
<key alias="rename" version="7.3.0">Rename</key>
<key alias="restore" version="7.3.0">Restore</key>
<key alias="SetPermissionsForThePage">Set permissions for the page %0%</key>
<key alias="chooseWhereToCopy">Choose where to copy</key>
<key alias="chooseWhereToMove">Choose where to move</key>
<key alias="toInTheTreeStructureBelow">In the tree structure below</key>
<key alias="toInTheTreeStructureBelow">to in the tree structure below</key>
<key alias="wasMovedTo">was moved to</key>
<key alias="wasCopiedTo">was copied to</key>
<key alias="rights">Permissions</key>
<key alias="rollback">Rollback</key>
<key alias="sendtopublish">Send To Publish</key>
@@ -186,6 +189,11 @@
<key alias="validationErrorPropertyWithMoreThanOneMapping">Could not complete property mapping as one or more properties have more than one mapping defined.</key>
<key alias="validDocTypesNote">Only alternate types valid for the current location are displayed.</key>
</area>
<area alias="codefile">
<key alias="createFolderFailedById">Failed to create a folder under parent with ID %0%</key>
<key alias="createFolderFailedByName">Failed to create a folder under parent with name %0%</key>
<key alias="deleteItemFailed">Failed to delete item: %0%</key>
</area>
<area alias="content">
<key alias="isPublished" version="7.2">Is Published</key>
<key alias="about">About this page</key>
@@ -289,6 +297,7 @@
<key alias="chooseNode">Where do you want to create the new %0%</key>
<key alias="createUnder">Create an item under</key>
<key alias="createContentBlueprint">Select the document type you want to make a content template for</key>
<key alias="enterFolderName">Enter a folder name</key>
<key alias="updateData">Choose a type and a title</key>
<key alias="noDocumentTypes" version="7.0"><![CDATA[There are no allowed document types available. You must enable these in the settings section under <strong>"document types"</strong>.]]></key>
<key alias="noMediaTypes" version="7.0"><![CDATA[There are no allowed media types available. You must enable these in the settings section under <strong>"media types"</strong>.]]></key>
@@ -1037,7 +1046,8 @@ To manage your website, simply open the Umbraco back office and start adding con
<key alias="relateToOriginal">Relate copied items to original</key>
</area>
<area alias="notifications">
<key alias="editNotifications">Edit your notification for %0%</key>
<key alias="editNotifications"><![CDATA[Select your notification for <strong>%0%</strong>]]></key>
<key alias="notificationsSavedFor">Notification settings saved for</key>
<key alias="mailBody">
<![CDATA[
Hi %0%
@@ -1309,6 +1319,7 @@ To manage your website, simply open the Umbraco back office and start adding con
<key alias="undoEditCrop">Undo edits</key>
</area>
<area alias="rollback">
<key alias="headline">Select a version to compare with the current version</key>
<key alias="currentVersion">Current version</key>
<key alias="diffHelp"><![CDATA[This shows the differences between the current version and the selected version<br /><del>Red</del> text will not be shown in the selected version. , <ins>green means added</ins>]]></key>
<key alias="documentRolledBack">Document has been rolled back</key>
@@ -1476,6 +1487,7 @@ To manage your website, simply open the Umbraco back office and start adding con
<key alias="styles">Styles</key>
</area>
<area alias="template">
<key alias="deleteByIdFailed">Failed to delete template with ID %0%</key>
<key alias="edittemplate">Edit template</key>
<key alias="insertSections">Sections</key>
@@ -2187,6 +2199,9 @@ To manage your website, simply open the Umbraco back office and start adding con
<key alias="notificationEmailsCheckErrorMessage"><![CDATA[Notification email is still set to the default value of <strong>%0%</strong>.]]></key>
<key alias="scheduledHealthCheckEmailBody"><![CDATA[<html><body><p>Results of the scheduled Umbraco Health Checks run on %0% at %1% are as follows:</p>%2%</body></html>]]></key>
<key alias="scheduledHealthCheckEmailSubject">Umbraco Health Check Status: %0%</key>
<key alias="tls12HealthCheckSuccess">Your site can use the TLS 1.2 security protocol when making outbound connections to HTTPS endpoints.</key>
<key alias="tls12HealthCheckWarn">Your site isn't configured to allow the TLS 1.2 security protocol when making outbound connections: some HTTPS endpoints might not be reachable using a less secure protocol.</key>
</area>
<area alias="redirectUrls">
<key alias="disableUrlTracker">Disable URL tracker</key>
@@ -2220,8 +2235,4 @@ To manage your website, simply open the Umbraco back office and start adding con
<key alias="itemCannotBeRestoredHelpText">There is no location where this item can be automatically restored. You can move the item manually using the tree below.</key>
<key alias="wasRestored">was restored under</key>
</area>
<area alias="notify">
<key alias="notifySet">Select your notifications for</key>
<key alias="notificationsSavedFor">Notification settings saved for </key>
</area>
</language>
@@ -1856,6 +1856,9 @@
<key alias="notificationEmailsCheckErrorMessage"><![CDATA[El email de notificación está todavía configurado en tuvalor por defecto: <strong>%0%</strong>.]]></key>
<key alias="scheduledHealthCheckEmailBody"><![CDATA[<html><body><p>Los resultados de los Chequeos de Salud de Umbraco programados para ejecutarse el %0% a las %1% son:</p>%2%</body></html>]]></key>
<key alias="scheduledHealthCheckEmailSubject">Status de los Chequeos de Salud de Umbraco: %0%</key>
<key alias="tlsHealthCheckSuccess">Su sitio web está configurado para usar TLS 1.2 o superior para las conexiones salientes.</key>
<key alias="tlsHealthCheckWarn">Las conexiones salientes de su sitio web están siendo servidas a través de un protocolo antiguo. Deberías considerar actualizarlo para usar TLS 1.2 o superior.</key>
</area>
<area alias="redirectUrls">
<key alias="disableUrlTracker">Desactivar URL tracker</key>

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