Compare commits

...

137 Commits

Author SHA1 Message Date
elitsa 6f716cc343 Update old string format for a language area alias and a language key alias 2018-09-13 14:33:29 +02:00
Sebastiaan Janssen 31ed4e0574 Merge pull request #2973 from prjseal/patch-1
update the release notes url
2018-09-13 12:01:01 +02:00
Paul Seal 9e3cf00cc0 update the release notes url 2018-09-12 13:32:10 +01:00
Shannon 2f74720c38 updates wording 2018-09-10 11:12:46 +10:00
Sebastiaan Janssen 91ebc649d4 Re-apply missing changes from #2446 2018-09-09 16:35:48 +02:00
Sebastiaan Janssen 32591eec36 Merge branch 'shoecake-U4-5572' into dev-v7 2018-09-07 15:20:36 +02:00
Sebastiaan Janssen e05a55c532 Fixes incorrectly named method and removes extraneous spaces 2018-09-07 15:20:29 +02:00
Sebastiaan Janssen f3d96ad45e Merge branch 'U4-5572' of https://github.com/shoecake/Umbraco-CMS into shoecake-U4-5572 2018-09-07 15:15:52 +02:00
Poornima Nayar 010a2e012e Clean up multiple textstring(repeatable textstring) view - (#2934)
* Clean up multiple textstring(repeatable textstring) view - Introduced some styling rules to make the view look cleaner

* Removes unnecessary additional included files from csproj
2018-09-07 14:54:20 +02:00
Sebastiaan Janssen 5986899b5e Fixes #U4-10383 Feature request - Ignore casing when getting member email and username from IPublishedContent 2018-09-06 11:07:04 +02:00
Sebastiaan Janssen 5dd04d9a3e Merge pull request #2902 from umbraco/abjerner-patch-2
The name field is not automatically in focus when creating a new data type folder
2018-09-04 09:38:15 +02:00
Anders Bjerner 6ff2f1eabb The name field is not automatically in focus when creating a new data type folder 2018-09-03 18:06:15 +02:00
Sebastiaan Janssen ac9c6305e7 Update CONTRIBUTING_DETAILED.md 2018-09-03 12:12:27 +02:00
Sebastiaan Janssen b2b9b53af1 Whoops, fixes previous commit for #2896 2018-09-02 10:03:51 +02:00
Sebastiaan Janssen 2dd5010d2c Seems there is no need to hide the .small class, fixes #2896 2018-09-02 09:57:45 +02:00
Sebastiaan Janssen bfd12b3a7b Merge pull request #2888 from mvanhelmont/#2886
Media Picker should not show deleted items #2886
2018-08-31 20:43:47 +02:00
Sebastiaan Janssen 396b499e81 Merge pull request #2885 from adhaliwal34/comment-change
Fix comment regarding the length of the salt bytes array
2018-08-31 20:27:32 +02:00
Sebastiaan Janssen 61ce1bcdca Merge branch 'dev-v7' of https://github.com/umbraco/Umbraco-CMS into dev-v7 2018-08-31 20:21:58 +02:00
Sebastiaan Janssen ec1d2a6433 Merge branch 'mvanhelmont-U4-11589' into dev-v7 2018-08-31 20:21:05 +02:00
Sebastiaan Janssen 9ea9c5d6b7 Don't repeat the code to check for and create a template 2018-08-31 20:20:37 +02:00
Sebastiaan Janssen fee9bce110 Merge branch 'U4-11589' of https://github.com/mvanhelmont/Umbraco-CMS into mvanhelmont-U4-11589 2018-08-31 20:11:50 +02:00
Sebastiaan Janssen 222720aea4 Merge pull request #2884 from AliSheikhTaheri/temp-u4-8310
Temp u4 8310 - Fixed can't rename of a document type alias by changing its casing
2018-08-31 20:06:07 +02:00
Sebastiaan Janssen 9e3213147f Merge pull request #2883 from mvanhelmont/U4-11145
U4-11145 Email validation is too strict on password reset screen
2018-08-31 19:50:54 +02:00
Marcel van Helmont c29357b845 inside ensureWithinStartNode also check if node is trashed otherwise go to startnode. 2018-08-30 21:06:29 +02:00
AJ_Dhaliwal cc680f2cfb Fix comment regarding the length of the salt bytes array 2018-08-30 18:03:44 +08:00
Sebastiaan Janssen 58dab23d04 Fix links 2018-08-30 10:00:29 +02:00
Sebastiaan Janssen 90a47cd042 Move from docs to github folder 2018-08-30 09:58:29 +02:00
Sebastiaan Janssen fb6079d4e2 Add issue templates and updated PR template 2018-08-30 09:57:17 +02:00
Shannon f359648215 fixes U4-11463 MembershipHelper is not working with basic auth on the initial request 2018-08-30 09:57:16 +02:00
Marcel van Helmont 74ca315197 added val-email to corrrectly validate emails supporting new TLD 2018-08-29 15:38:12 +02:00
Ali.Taheri 541e546f7b u4-8310 - Added error message to the xml file. 2018-08-29 14:35:20 +01:00
Ali.Taheri 26a8d680d4 u4-8310 - Fixed rename content type with the same alias but with different casing. 2018-08-29 14:28:33 +01:00
Marcel van Helmont ec1a3f0fe8 make sure alias is camelCase format 2018-08-28 22:44:53 +02:00
Marcel van Helmont 8ce200bd16 added toggles to allow creating templates for collection and collection item 2018-08-28 21:32:18 +02:00
Sebastiaan Janssen 26e2bc6afa Merge pull request #2879 from umbraco/temp-u4-11599
U4-11599 - do not abort inst processing on error
2018-08-27 08:45:04 +02:00
Sebastiaan Janssen 546458bcfd Merge pull request #2322 from umbraco/validate-using-schema
Updates sql to include current schema in queries
2018-08-27 08:16:57 +02:00
Stephan f2090e9fc7 U4-11599 - do not abort inst processing on error 2018-08-27 08:10:39 +02:00
Sebastiaan Janssen 46b0063921 Fixes U4-11598 Scheduling the content does not reload the page at the same time 2018-08-27 06:56:05 +02:00
Sebastiaan Janssen 7fd1617759 Merge branch 'dev-v7' into validate-using-schema 2018-08-26 23:13:08 +02:00
Sebastiaan Janssen 5e7c9f2341 Merge pull request #2876 from RNHornets/temp-u4-9030
U4-9030 Moving a RTE between grid cells causes rendering issues for other RTEs
2018-08-26 22:57:17 +02:00
Sebastiaan Janssen bec8aabede Merge pull request #2442 from madsoulswe/temp-U4-10962
U4-10962 - Disable stickyheader when nested, fix margins when disabled
2018-08-26 22:17:44 +02:00
Sebastiaan Janssen c07780caff Merge pull request #2481 from SaDa1337/dev-v7.9
fix x alignment in colorpicker transparent option in umbraco skin
2018-08-26 22:08:24 +02:00
Sebastiaan Janssen 0c3d3ca545 Merge pull request #2506 from PeteDuncanson/temp-U4-11074
Added web.config to fonts folder to allow for caching out of the box
2018-08-26 21:26:45 +02:00
Sebastiaan Janssen 35a0d4451f Merge pull request #2483 from kccsf/U4-4441
U4-4441 Fix: TinyMCE overlay was showing in front of login overlay
2018-08-26 21:01:58 +02:00
Sebastiaan Janssen 03fdba6a3b Merge pull request #2512 from NathalieLarsson/dev-v7
Quick fix for U4-11085 and added filtering to list view in MNTP
2018-08-26 20:51:53 +02:00
Sebastiaan Janssen 550c383598 Also make sure there's a value for dialogOptions.filterTypes if it doesn't start with "!"
Else you get errors on `dialogOptions.filterTypes.toLowerCase()`
2018-08-26 20:47:26 +02:00
Sebastiaan Janssen 9d3d718e16 Merge branch 'dev-v7' into dev-v7 2018-08-26 20:33:00 +02:00
Ben Palmer b09bf518c6 U4-9237 Validate application parameter when getting application trees (#2315) 2018-08-26 18:12:07 +02:00
Sebastiaan Janssen 8666b222ac Merge pull request #2841 from leekelleher/U4-11556
U4-11556 - Removed metablogConfig.config
2018-08-26 18:04:50 +02:00
Sebastiaan Janssen 9e564d70ef Merge branch 'drpeck-U4-8550' into dev-v7 2018-08-26 17:57:00 +02:00
Sebastiaan Janssen 276810be6c Bump to v7.13.0 2018-08-26 17:56:13 +02:00
Sebastiaan Janssen 49df6e7c9d Merge branch 'U4-8550' of https://github.com/drpeck/Umbraco-CMS into drpeck-U4-8550
# Conflicts:
#	src/Umbraco.Web.UI/config/umbracoSettings.config
#	src/Umbraco.Web/PublishedContentExtensions.cs
2018-08-26 17:45:34 +02:00
Sebastiaan Janssen 16155ea416 Merge branch 'dev-v7' of https://github.com/umbraco/Umbraco-CMS into dev-v7 2018-08-26 17:25:18 +02:00
Sebastiaan Janssen f183e27cae Merge branch 'jamescoxhead-U4-11166' into dev-v7 2018-08-26 17:24:18 +02:00
Sebastiaan Janssen a411c9c300 Make sure inactive users get the correct state attached to them 2018-08-26 17:23:52 +02:00
Sebastiaan Janssen 342ac7b1b2 Merge branch 'U4-11166' of https://github.com/jamescoxhead/Umbraco-CMS into jamescoxhead-U4-11166 2018-08-26 16:52:58 +02:00
Sebastiaan Janssen f5ac5f20a8 Merge pull request #2869 from Bazmech/temp-U4-11594
U4-11594 HasFocalPoint in ImageCropDataSet does not return correct value
2018-08-26 16:44:19 +02:00
Chris Houston 56de9ff4ae Fix for issue: U4 11409 - "Create content" tour is failing when doing the tour with the starter kit installed (#2851) 2018-08-26 14:52:14 +02:00
Arbie Sarkissian e4d8fcf019 U4-11506 - Fix Gregorian DateTime.MinValue is out of range for some calendars (like PersianCalendar) (#2821) 2018-08-24 11:15:53 +02:00
Sebastiaan Janssen e1f7e835ea Fixes U4-11584 RelatedLinks2 throws exception with null value in Link field 2018-08-24 11:08:27 +02:00
Sebastiaan Janssen d83bb6aa49 Whoops, committed the wrong file! Revert "Fixes U4-11584 RelatedLinks2 throws exception with null value in Link field"
This reverts commit 612138f0e1.
2018-08-24 11:07:55 +02:00
Robert Johnston 06e55c8c4e Use offsetParent to get the grid cell for the moved item since parents() always returns 0 results 2018-08-24 09:50:24 +01:00
Sebastiaan Janssen 612138f0e1 Fixes U4-11584 RelatedLinks2 throws exception with null value in Link field 2018-08-24 10:49:39 +02:00
Sebastiaan Janssen bfc627857d Merge pull request #2840 from WebCentrum/temp-U4-11527
U4-11527 Fix concurrency issue
2018-08-24 00:02:30 +02:00
BatJan 7d439566cd U4-11526 - Member Group Picker doesn't remove group after unselecting it during selection. (#2835) 2018-08-23 23:56:32 +02:00
Sebastiaan Janssen d224a93ce1 Merge branch 'BatJan-feature/temp-U4-11577' into dev-v7 2018-08-23 23:44:23 +02:00
Sebastiaan Janssen 3454db6ee8 No need to do an extra userService request, if the contentType is null we can't access the settings section, that's a good enough test
Also fixed the bug where editors would see the node name instead of the content type name
2018-08-23 23:36:50 +02:00
Sebastiaan Janssen b67c06a85a Remove console.log that was left behind 2018-08-23 22:23:41 +02:00
Sebastiaan Janssen 44bd3dec9a Merge branch 'dev-v7' into feature/temp-U4-11577 2018-08-23 22:22:57 +02:00
Thomas Nielsen 68ac84aa1d Sort the Umbraco.UserPicker list alphabetically by name (#2872) 2018-08-23 22:15:28 +02:00
Sebastiaan Janssen c1bf8259ef Merge branch 'rasmusjp-fix/linkpicker-url-empty' into dev-v7 2018-08-23 21:34:06 +02:00
Sebastiaan Janssen 1b1df84863 Populates the anchor when found
Also fixes one of the JS files where .model was seemingly used randomly, but the view doesn't want a .model in there
2018-08-23 21:31:31 +02:00
Sebastiaan Janssen 05fdfc6b34 Merge branch 'fix/linkpicker-url-empty' of https://github.com/rasmusjp/Umbraco-CMS into rasmusjp-fix/linkpicker-url-empty 2018-08-23 20:52:14 +02:00
Sebastiaan Janssen 18b690f11a Bump the version to 7.12.2 2018-08-23 20:45:49 +02:00
Sebastiaan Janssen d3b577fe37 Merge pull request #2867 from BatJan/features/temp-U4-11587
U4-11587 Media link does not update when the file is swapped
2018-08-23 20:37:45 +02:00
Sebastiaan Janssen 720409ef54 Merge pull request #2871 from leekelleher/U4-11595
umb-node-preview directive - corrected the title of the "Edit" button
2018-08-23 19:21:30 +02:00
Sebastiaan Janssen 919a63d0ea Merge pull request #2848 from readingdancer/U4-11569
Small tweaks to the Getting Started tour text.
2018-08-23 18:53:40 +02:00
Mads Rasmussen ef6822e15b Merge pull request #2873 from kjac/media-picker-update
Media picker: Minor style update + add help text.
2018-08-23 09:29:05 +02:00
Jan Skovgaard 015e89b927 Make sure the "open" action is only visible when logged in as an administrator 2018-08-22 11:31:07 +02:00
Jan Skovgaard 05e48376c7 Use the node object to get the name and icon so it's also displayed for non-admin users 2018-08-22 11:30:39 +02:00
Jan Skovgaard a2cc0ec411 Shorten comments 2018-08-22 11:30:07 +02:00
Jan Skovgaard d4fff97814 Move the setModePublishStatus function above the scope.previewOpenUrl...not sure why but this makes the status be visible when logged in as something other than an administrator. When logged in as an admin it worked fine before. Can't quite make sense of this. But now it works. 2018-08-22 11:23:51 +02:00
Lee Kelleher 06e99c3b33 Corrected the title of the "Edit" button
umb-node-preview directive - corrected the title of the "Edit" button
2018-08-22 09:13:43 +01:00
Jan Skovgaard ad3d27be76 Reference the node object instead of the documentType object, which returns null if the user is not logged in as an admin. 2018-08-22 10:00:54 +02:00
Jan Skovgaard 2e2fc6ad84 Make sure to check whether the open anchor for the template should be displayed or not 2018-08-22 09:31:44 +02:00
Jan Skovgaard 9f396e4b15 By default set the "allowOpen" to be false and only set it to true if the current user is an admin. This ensures that the "Open" anchors are never displayed for other than admin users. 2018-08-22 09:13:46 +02:00
Barry Bell f42862c42a Update ImageCropDataSet.cs
If only one of the Left or Right values changed the HasFocalPoint function would return false but this should now return true if only one is altered
2018-08-21 21:07:54 +01:00
Mads Rasmussen f7201a70bd add colored border 2018-08-21 21:20:38 +02:00
Mads Rasmussen ec67ab83af Merge branch 'patch-1' of git://github.com/jannikanker/Umbraco-CMS into jannikanker-patch-1 2018-08-21 21:10:01 +02:00
Rasmus John Pedersen a725ddae5a Only remove ? or # if it's part of the url 2018-08-21 17:10:46 +02:00
Jan Skovgaard 8f2c253138 Refactort the scope.nodeUrl to be updated whenever save is hit in the existing update watcher 2018-08-21 14:52:00 +02:00
Sebastiaan Janssen e6597d47e3 Fixes U4-11574 - return an empty string if the datatype is in "single" mode and nothing is selected 2018-08-20 16:12:23 +02:00
Nathan Woulfe 89f69bd2a8 U4 4732 - fix regressions in 7.12 (#2862) 2018-08-20 16:10:36 +02:00
Sebastiaan Janssen 8087fc4c9a Merge pull request #2858 from umbraco/temp-U4-11579
U4-11579 Take startNodeId into account before picking the current nod…
2018-08-20 12:06:45 +02:00
Radu Orleanu f665f8af89 fixing U4-11570 (#2860) 2018-08-17 14:04:35 +02:00
Kenn Jacobsen de8a24c691 Add "info" style to upload button + add help text when the dropzone is hidden. 2018-08-17 12:22:54 +02:00
Sebastiaan Janssen c4163e94c0 Merge pull request #2856 from dawoe/remove-deleted-scripts-from-solution
Removed files from solution that are not longer present in repo
2018-08-17 08:25:50 +02:00
Sebastiaan Janssen 62855d021f Merge pull request #2857 from umbraco/temp-U4-11581
U4-11581 In rare cases the umbracoLanguage table has a constraint ins…
2018-08-17 08:24:43 +02:00
Shannon 49430ca0a5 fixes logic order of dropping indexes 2018-08-17 16:07:53 +10:00
Shannon 9d75e36eb4 Ensures that checking for constraints/indexes is done within the transaction before dropping anything instead of before the transaction. 2018-08-17 15:20:12 +10:00
Shannon 5068b8ae9f Fixes DB schema validation 2018-08-17 11:16:10 +10:00
Shannon cdf3581721 code simplification 2018-08-17 10:53:45 +10:00
Shannon 0c6cca44d8 Fixes SQL providers for returning the correct results for constraints 2018-08-17 10:53:21 +10:00
Sebastiaan Janssen f18b0aa774 U4-11579 Take startNodeId into account before picking the current node to sync to 2018-08-16 13:53:42 +02:00
Sebastiaan Janssen b9e8dd8b86 Removes unused import statement 2018-08-16 13:47:20 +02:00
Sebastiaan Janssen 45d8d302c9 U4-11581 In rare cases the umbracoLanguage table has a constraint instead of an index, making the migration fail 2018-08-16 12:10:21 +02:00
Dave Woestenborghs e0ce9f1a77 Removed files from solution that are not longer present in repo 2018-08-16 10:35:08 +02:00
Sebastiaan Janssen d7a0886097 Fixes problem where we try to query a table that hasn't been updated with the new column yet, so we can't use the DTO 2018-08-16 10:32:10 +02:00
Sebastiaan Janssen 39e8a9fa67 Bump version to 7.12.1 2018-08-15 15:47:21 +02:00
Warren Buckley 1dbf509020 Merge pull request #2855 from umbraco/temp7-156
fixes: 156: Update nested content css/markup so it doesn't collide with the old package
2018-08-15 14:03:47 +01:00
Mads Rasmussen 8ce93055ef update colors to use variables and match the new color scheme 2018-08-15 13:00:40 +02:00
Mads Rasmussen ee4b2adbd4 prefix all nested content css classes with "umb" 2018-08-15 11:59:06 +02:00
Jannik Anker de73080e14 U4-11572
Add border to selected icon in document type icon picker dialog
2018-08-14 13:37:54 +02:00
Mads Rasmussen 6c0d14e0f4 add type="button" to toggle so it doesn't auto-submits a form 2018-08-14 13:14:49 +02:00
Chris Houston ba682d95dc Small tweaks to the Getting Started tour text. 2018-08-12 01:16:57 -04:00
Sebastiaan Janssen fd888cab4b Fixes U4-9095 - the textService.Localize always returns some string, either the translation or [alias] - so we need to make sure it actually translated something 2018-08-09 14:36:08 +02:00
leekelleher 92273f263b U4-11556 V8 - Removed metablogConfig.config
http://issues.umbraco.org/issue/U4-11556

For v7, I've marked the `SystemFiles.MetablogConfig` strings as deprecated.
2018-08-08 10:23:14 +01:00
Pavel Budik 3efbb47aed U4-11527 Fix concurrency issue 2018-08-08 10:38:53 +02:00
James Coxhead 9a774c8f9e Added inactive state for users who haven't logged in 2018-08-02 22:01:45 +01:00
James Coxhead f81dc16210 Specify which user states we want to include when getting all users 2018-08-02 21:55:04 +01:00
James Coxhead c4a787331f Reverted previous commit to show disabled users in the status filter 2018-08-02 21:54:00 +01:00
James Coxhead 3078be93b6 Remove disabled users option from users list view filter 2018-07-05 21:07:12 +01:00
James Coxhead 0a2fd277a6 U4-11166 Hide disabled users from the users list view 2018-06-28 20:19:02 +01:00
Morten Christensen f5b017ed67 Updates sql to include current schema in queries 2018-06-08 10:44:11 +02:00
Nathalie Festin 4512cf0145 Filtering items 'Allow items of type' in mini list view in MNTP 2018-03-11 20:49:43 +01:00
Nathalie Festin 38e9a3d2ee Bug in exclude - Dialogoption.filter 2018-03-11 20:41:51 +01:00
Peter Duncanson 13f42773d7 Added web.config to fonts folder to allow for caching out of the box 2018-03-06 17:02:16 +00:00
Steve Fawcett 71d3c1112e Fix: TinyMCE overlay was showing in front of login overlay 2018-02-27 17:48:53 +00:00
Maciej Sadowski 5bfac6c5b4 fix x alignment in colorpicker in umbraco skin 2018-02-27 09:23:35 +01:00
Dennis Öhman ebae69d00c U4-10962 - Disable stickyheader when nested, fix margins when disabled 2018-02-11 16:58:46 +01:00
David Peck 1ece576825 Merge branch 'dev-v7' of https://github.com/umbraco/Umbraco-CMS into U4-8550
Conflicts:
	src/Umbraco.Web.UI/config/umbracoSettings.config
2017-05-30 23:13:33 +01:00
David Peck a2611ce35f Changed the name of IsTemplateAllowed to IsAllowedTemplate to reflect the usage elsewhere and changed the overload of IsAllowedTemplate with the alias parameter to use the template id version to be more DRY 2017-05-30 22:39:26 +01:00
David Peck 7a89580db2 Merge branch 'dev-v7' into U4-8550 2016-11-08 21:06:39 +00:00
David Peck a031551fb2 Rationalised changes in whitespace, to reduce the differences in the PR 2016-11-08 17:59:30 +00:00
David Peck 69728fb5c4 Changed Allowed Templates setting to be validate templates which checks url only 2016-11-08 08:27:18 +00:00
David Peck afd91f8adb Added ability to only allow templates what are allowed by the document type 2016-11-03 16:25:45 +00:00
Patrick Scott d99d5a0b36 Issue U4-5572 convert file name to friendly media item name 2016-11-03 14:30:57 +00:00
142 changed files with 1725 additions and 1277 deletions
View File
@@ -129,7 +129,7 @@ We like to use [Gitflow as much as possible](https://jeffkreeftmeijer.com/git-fl
The easiest way to get started is to run `build.bat` which will build both the backoffice (also known as "Belle") and the Umbraco core. You can then easily start debugging from Visual Studio, or if you need to debug Belle you can run `gulp dev` in `src\Umbraco.Web.UI.Client`. See [this page](BUILD.md) for more details.
Alternatively, you can open `src\umbraco.sln` in Visual Studio 2017 ([the community edition is free](https://www.visualstudio.com/thank-you-downloading-visual-studio/?sku=Community&rel=15) for you to use to contribute to Open Source projects). In Visual Studio, find the Task Runner Explorer (in the View menu under Other Windows) and run the build task under the gulpfile.
Alternatively, you can open `src\umbraco.sln` in Visual Studio 2017 (version 15.3 or higher, [the community edition is free](https://www.visualstudio.com/thank-you-downloading-visual-studio/?sku=Community&rel=15) for you to use to contribute to Open Source projects). In Visual Studio, find the Task Runner Explorer (in the View menu under Other Windows) and run the build task under the gulpfile.
![Gulp build in Visual Studio](img/gulpbuild.png)
@@ -156,4 +156,4 @@ git rebase upstream/dev-v7
In this command we're syncing with the `dev-v7` branch, but you can of course choose another one if needed.
(More info on how this works: [http://robots.thoughtbot.com/post/5133345960/keeping-a-git-fork-updated](http://robots.thoughtbot.com/post/5133345960/keeping-a-git-fork-updated))
(More info on how this works: [http://robots.thoughtbot.com/post/5133345960/keeping-a-git-fork-updated](http://robots.thoughtbot.com/post/5133345960/keeping-a-git-fork-updated))
+66
View File
@@ -0,0 +1,66 @@
---
name: 🐛 Bug Report
about: File a bug report, if you've discovered a problem in Umbraco.
---
A brief description of the issue goes here.
<!--
If you haven't yet done so, please read the "contributing guidelines"
thoroughly. Then, proceed by filling out the rest of the details in the issue
template below. The more details you can give us, the easier it will be for us
to determine the cause of a problem.
See: https://github.com/umbraco/Umbraco-CMS/blob/dev-v7/.github/CONTRIBUTING.md
-->
Reproduction
------------
If you're filing a bug, please describe how to reproduce it. Include as much
relevant information as possible, such as:
### Bug summary
<!--
* Write a short summary of the bug
* Try to pinpoint it as much as possible
* Try to state the _actual problem_, and not just what you _think_ the
solution might be.
-->
### Specifics
<!--
* Mention the URL where this bug occurs, if applicable
* What version of Umbraco are you using (down to the very last digit!)
* What browser and version you are using
* Please mention if you've checked it in other browsers as well
* Please include *full error messages* and *screenshots* if possible
-->
### Steps to reproduce
<!--
* Clearly mention the steps to reproduce the bug
-->
### Expected result
<!--
* What did you _expect_ that would happen on your Umbraco site?
* Describe the intended/desired outcome after you did the steps mentioned.
-->
### Actual result
<!--
* What is the actual result of the above steps?
* Describe the behaviour of the bug
* Please, please include **error messages** and screenshots. They might mean
nothing to you, but they are _very_ helpful to us.
-->
@@ -0,0 +1,31 @@
---
name: 📮 Feature Request
about: Open a feature request, if you want to propose a new feature.
---
A brief description of your feature request goes here.
<!--
If you want to discuss the feature you're imagining, please make sure to keep
those discussions on the forum at https://our.umbraco.com/ (choose the
category "Contributing to Umbraco", Umbraco HQ follows all new topics there).
Once you've come to a conclusion in the discussion, feel free to propose the
new feature here.
-->
How can you help?
-------------------------------
<!--
The resources (read: available time and effort) of Umbraco's core team are
limited.
If we can not work on your suggestion, please don't take it personally. Most
likely, it's either:
- We think your idea is valid, but we can't find the time to work on it.
- Your idea might be better suited as a package, if it's not suitable for
the majority of users.
-->
@@ -0,0 +1,9 @@
---
name: ⁉️ Support Question
about: Having trouble with Umbraco? -> https://our.umbraco.com
---
This issue tracker is NOT meant for support questions. If you have a question,
please join us on the forum at https://our.umbraco.com.
Thanks!
@@ -0,0 +1,9 @@
---
name: 📖 Documentation Issue
about: See https://github.com/umbraco/UmbracoDocs/issues for documentation issues
---
The Umbraco documentation has its own dedicated repository. Please open your
documentation-related issue at https://github.com/umbraco/UmbracoDocs/issues
Thanks!
@@ -0,0 +1,31 @@
---
name: 🔐 Security Issue
about: Discovered a Security Issue in Umbraco?
---
⚠️ PLEASE DON'T DISCLOSE SECURITY-RELATED ISSUES PUBLICLY, SEE BELOW.
If you have found a security issue in Umbraco, please send the details to
security@umbraco.com and don't disclose it publicly until we can provide a fix for
it. If you wish, we'll credit you for finding verified issues, when we release
the patched version.
❗ Please read more about how to report security issues on https://umbraco.com/security
A note on "Self XSS"
--------------------
Umbraco is a CMS, that allows users to edit content on a website. As such,
all _authenticated users_ can:
- Edit content, and (depending on the field types) insert HTML and CSS in that
content, with a variety of allowed attributes.
- Depending on the user level: Edit template files, and insert C#, HTML, CSS and
javascript in so on.
- Upload files to the site, which will become publicly available.
We see these functionalities as _features_, and not as security issues. Please
report the mentioned items only if they can be performed by non-authorized
users, or other exploitable vulnerabilities.
Thanks!
+11
View File
@@ -0,0 +1,11 @@
### Prerequisites
- [ ] I have [created an issue](https://github.com/umbraco/Umbraco-CMS/issues) for the proposed changes in this PR, the link is:
- [ ] I have added steps to test this contribution in the description below
### Description
<!-- A description of the changes proposed in the pull-request -->
<!-- Make sure to link to the related issue number so we can easily find it in the issue tracker -->
<!-- Thanks for contributing to Umbraco CMS! -->
+1 -1
View File
@@ -44,6 +44,6 @@ Umbraco is contribution focused and community driven. If you want to contribute
## Found a bug?
Another way you can contribute to Umbraco is by providing issue reports. For information on how to submit an issue report refer to our [online guide for reporting issues](https://github.com/umbraco/Umbraco-CMS/blob/dev-v7/docs/CONTRIBUTING.md).
Another way you can contribute to Umbraco is by providing issue reports. For information on how to submit an issue report refer to our [online guide for reporting issues](https://github.com/umbraco/Umbraco-CMS/blob/dev-v7/.github/CONTRIBUTING.md).
To view existing issues, please visit [http://issues.umbraco.org](http://issues.umbraco.org).

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 12 KiB

Before

Width:  |  Height:  |  Size: 26 KiB

After

Width:  |  Height:  |  Size: 26 KiB

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 18 KiB

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 12 KiB

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 20 KiB

Before

Width:  |  Height:  |  Size: 27 KiB

After

Width:  |  Height:  |  Size: 27 KiB

+2 -2
View File
@@ -21,6 +21,6 @@ The following items will now be automatically included when creating a deploy pa
system: umbraco, umbraco_client, config\splashes and global.asax.
Please read the release notes on our.umbraco.com:
http://our.umbraco.com/contribute/releases
https://our.umbraco.com/download/releases
- Umbraco
- Umbraco
-11
View File
@@ -1,11 +0,0 @@
### Prerequisites
- [ ] I have written a descriptive pull-request title
- [ ] I have linked this PR to an issue on the tracker at http://issues.umbraco.org
### Description
<!-- A description of the changes proposed in the pull-request -->
<!-- Thanks for contributing to Umbraco CMS! -->
+2 -2
View File
@@ -11,5 +11,5 @@ using System.Resources;
[assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyFileVersion("7.12.0")]
[assembly: AssemblyInformationalVersion("7.12.0")]
[assembly: AssemblyFileVersion("7.13.0")]
[assembly: AssemblyInformationalVersion("7.13.0")]
+10 -10
View File
@@ -1,8 +1,8 @@
using System;
using System.Collections.Generic;
using Semver;
using System;
using System.Collections.Concurrent;
using System.Configuration;
using System.Threading;
using Semver;
using Umbraco.Core.Configuration;
using Umbraco.Core.Logging;
using Umbraco.Core.ObjectResolution;
@@ -13,7 +13,7 @@ using Umbraco.Core.Sync;
namespace Umbraco.Core
{
/// <summary>
/// <summary>
/// the Umbraco Application context
/// </summary>
/// <remarks>
@@ -270,7 +270,7 @@ namespace Umbraco.Core
return _umbracoApplicationUrl;
}
}
/// <summary>
/// Resets the url.
/// </summary>
@@ -280,10 +280,10 @@ namespace Umbraco.Core
}
// ReSharper disable once InconsistentNaming
internal string _umbracoApplicationUrl;
internal List<string> _umbracoApplicationDomains = new List<string>();
internal string _umbracoApplicationUrl;
internal ConcurrentDictionary<string, string> _umbracoApplicationDomains = new ConcurrentDictionary<string, string>();
internal string _umbracoApplicationDeploymentId;
private Lazy<bool> _configured;
@@ -399,7 +399,7 @@ namespace Umbraco.Core
}
return version;
}
}
private void AssertIsNotReady()
{
@@ -8,6 +8,8 @@
bool DisableAlternativeTemplates { get; }
bool ValidateAlternativeTemplates { get; }
bool DisableFindContentByIdPath { get; }
bool DisableRedirectUrlTracking { get; }
@@ -1,4 +1,5 @@
using System.Configuration;
using System;
using System.Configuration;
namespace Umbraco.Core.Configuration.UmbracoSettings
{
@@ -21,6 +22,13 @@ namespace Umbraco.Core.Configuration.UmbracoSettings
{
get { return (bool) base["disableAlternativeTemplates"]; }
}
[ConfigurationProperty("validateAlternativeTemplates", DefaultValue = "false")]
public bool ValidateAlternativeTemplates
{
get { return (bool)base["validateAlternativeTemplates"]; }
}
[ConfigurationProperty("disableFindContentByIdPath", DefaultValue = "false")]
public bool DisableFindContentByIdPath
{
@@ -6,7 +6,7 @@ namespace Umbraco.Core.Configuration
{
public class UmbracoVersion
{
private static readonly Version Version = new Version("7.12.0");
private static readonly Version Version = new Version("7.13.0");
/// <summary>
/// Gets the current version of Umbraco.
+1
View File
@@ -37,6 +37,7 @@ namespace Umbraco.Core.IO
}
}
[Obsolete("This file is no longer used and should not be accessed!")]
public static string MetablogConfig
{
get
+22
View File
@@ -102,6 +102,28 @@ namespace Umbraco.Core.Models
}
}
/// <summary>
/// Determines if AllowedTemplates contains templateId
/// </summary>
/// <param name="templateId">The template id to check</param>
/// <returns>True if AllowedTemplates contains the templateId else False</returns>
public bool IsAllowedTemplate(int templateId)
{
var allowedTemplates = AllowedTemplates ?? new ITemplate[0];
return allowedTemplates.Any(t => t.Id == templateId);
}
/// <summary>
/// Determines if AllowedTemplates contains templateId
/// </summary>
/// <param name="templateAlias">The template alias to check</param>
/// <returns>True if AllowedTemplates contains the templateAlias else False</returns>
public bool IsAllowedTemplate(string templateAlias)
{
var allowedTemplates = AllowedTemplates ?? new ITemplate[0];
return allowedTemplates.Any(t => t.Alias.Equals(templateAlias, StringComparison.InvariantCultureIgnoreCase));
}
/// <summary>
/// Sets the default template for the ContentType
/// </summary>
+14
View File
@@ -17,6 +17,20 @@ namespace Umbraco.Core.Models
/// </summary>
IEnumerable<ITemplate> AllowedTemplates { get; set; }
/// <summary>
/// Determines if AllowedTemplates contains templateId
/// </summary>
/// <param name="templateId">The template id to check</param>
/// <returns>True if AllowedTemplates contains the templateId else False</returns>
bool IsAllowedTemplate(int templateId);
/// <summary>
/// Determines if AllowedTemplates contains templateId
/// </summary>
/// <param name="templateAlias">The template alias to check</param>
/// <returns>True if AllowedTemplates contains the templateAlias else False</returns>
bool IsAllowedTemplate(string templateAlias);
/// <summary>
/// Sets the default template for the ContentType
/// </summary>
+6 -2
View File
@@ -259,7 +259,7 @@ namespace Umbraco.Core.Models.Membership
{
get
{
if (LastLoginDate == default(DateTime) && IsApproved == false && InvitedDate != null)
if (LastLoginDate == default && IsApproved == false && InvitedDate != null)
return UserState.Invited;
if (IsLockedOut)
@@ -267,7 +267,11 @@ namespace Umbraco.Core.Models.Membership
if (IsApproved == false)
return UserState.Disabled;
return UserState.Active;
// User is not disabled or locked and has never logged in before
if (LastLoginDate == default && IsApproved && IsLockedOut == false)
return UserState.Inactive;
return UserState.Active;
}
}
@@ -9,6 +9,7 @@
Active = 0,
Disabled = 1,
LockedOut = 2,
Invited = 3
Invited = 3,
Inactive = 4
}
}
}
@@ -6,17 +6,17 @@ namespace Umbraco.Core.Persistence.DatabaseModelDefinitions
{
public ConstraintDefinition(ConstraintType type)
{
constraintType = type;
_constraintType = type;
}
private ConstraintType constraintType;
public bool IsPrimaryKeyConstraint { get { return ConstraintType.PrimaryKey == constraintType; } }
public bool IsUniqueConstraint { get { return ConstraintType.Unique == constraintType; } }
public bool IsNonUniqueConstraint { get { return ConstraintType.NonUnique == constraintType; } }
private readonly ConstraintType _constraintType;
public bool IsPrimaryKeyConstraint => ConstraintType.PrimaryKey == _constraintType;
public bool IsUniqueConstraint => ConstraintType.Unique == _constraintType;
public bool IsNonUniqueConstraint => ConstraintType.NonUnique == _constraintType;
public string SchemaName { get; set; }
public string ConstraintName { get; set; }
public string TableName { get; set; }
public ICollection<string> Columns = new HashSet<string>();
}
}
}
@@ -1,3 +1,5 @@
using System;
namespace Umbraco.Core.Persistence.DatabaseModelDefinitions
{
/// <summary>
@@ -5,9 +7,17 @@ namespace Umbraco.Core.Persistence.DatabaseModelDefinitions
/// </summary>
internal class DbIndexDefinition
{
public virtual string IndexName { get; set; }
public virtual string TableName { get; set; }
public virtual string ColumnName { get; set; }
public virtual bool IsUnique { get; set; }
public DbIndexDefinition(Tuple<string, string, string, bool> data)
{
TableName = data.Item1;
IndexName = data.Item2;
ColumnName = data.Item3;
IsUnique = data.Item4;
}
public string IndexName { get; }
public string TableName { get; }
public string ColumnName { get; }
public bool IsUnique { get; }
}
}
}
@@ -159,13 +159,7 @@ namespace Umbraco.Core.Persistence.Migrations.Initial
//get the db index defs
result.DbIndexDefinitions = _sqlSyntaxProvider.GetDefinedIndexes(_database)
.Select(x => new DbIndexDefinition()
{
TableName = x.Item1,
IndexName = x.Item2,
ColumnName = x.Item3,
IsUnique = x.Item4
}).ToArray();
.Select(x => new DbIndexDefinition(x)).ToArray();
foreach (var item in OrderedTables.OrderBy(x => x.Key))
{
@@ -184,6 +178,14 @@ namespace Umbraco.Core.Persistence.Migrations.Initial
return result;
}
/// <summary>
/// This validates the Primary/Foreign keys in the database
/// </summary>
/// <param name="result"></param>
/// <remarks>
/// This does not validate any database constraints that are not PKs or FKs because Umbraco does not create a database with non PK/FK contraints.
/// Any unique "constraints" in the database are done with unique indexes.
/// </remarks>
private void ValidateDbConstraints(DatabaseSchemaResult result)
{
//MySql doesn't conform to the "normal" naming of constraints, so there is currently no point in doing these checks.
@@ -196,8 +198,7 @@ namespace Umbraco.Core.Persistence.Migrations.Initial
var constraintsInDatabase = _sqlSyntaxProvider.GetConstraintsPerColumn(_database).DistinctBy(x => x.Item3).ToList();
var foreignKeysInDatabase = constraintsInDatabase.Where(x => x.Item3.InvariantStartsWith("FK_")).Select(x => x.Item3).ToList();
var primaryKeysInDatabase = constraintsInDatabase.Where(x => x.Item3.InvariantStartsWith("PK_")).Select(x => x.Item3).ToList();
var indexesInDatabase = constraintsInDatabase.Where(x => x.Item3.InvariantStartsWith("IX_")).Select(x => x.Item3).ToList();
var indexesInSchema = result.TableDefinitions.SelectMany(x => x.Indexes.Select(y => y.Name)).ToList();
var unknownConstraintsInDatabase =
constraintsInDatabase.Where(
x =>
@@ -212,7 +213,7 @@ namespace Umbraco.Core.Persistence.Migrations.Initial
// In theory you could have: FK_ or fk_ ...or really any standard that your development department (or developer) chooses to use.
foreach (var unknown in unknownConstraintsInDatabase)
{
if (foreignKeysInSchema.InvariantContains(unknown) || primaryKeysInSchema.InvariantContains(unknown) || indexesInSchema.InvariantContains(unknown))
if (foreignKeysInSchema.InvariantContains(unknown) || primaryKeysInSchema.InvariantContains(unknown))
{
result.ValidConstraints.Add(unknown);
}
@@ -254,23 +255,6 @@ namespace Umbraco.Core.Persistence.Migrations.Initial
result.Errors.Add(new Tuple<string, string>("Constraint", primaryKey));
}
//Constaints:
//NOTE: SD: The colIndex checks above should really take care of this but I need to keep this here because it was here before
// and some schema validation checks might rely on this data remaining here!
//Add valid and invalid index differences to the result object
var validIndexDifferences = indexesInDatabase.Intersect(indexesInSchema, StringComparer.InvariantCultureIgnoreCase);
foreach (var index in validIndexDifferences)
{
result.ValidConstraints.Add(index);
}
var invalidIndexDifferences =
indexesInDatabase.Except(indexesInSchema, StringComparer.InvariantCultureIgnoreCase)
.Union(indexesInSchema.Except(indexesInDatabase, StringComparer.InvariantCultureIgnoreCase));
foreach (var index in invalidIndexDifferences)
{
result.Errors.Add(new Tuple<string, string>("Constraint", index));
}
}
private void ValidateDbColumns(DatabaseSchemaResult result)
@@ -28,13 +28,7 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSeven
public override void Up()
{
var dbIndexes = _skipIndexCheck ? new DbIndexDefinition[]{} : SqlSyntax.GetDefinedIndexes(Context.Database)
.Select(x => new DbIndexDefinition()
{
TableName = x.Item1,
IndexName = x.Item2,
ColumnName = x.Item3,
IsUnique = x.Item4
}).ToArray();
.Select(x => new DbIndexDefinition(x)).ToArray();
//make sure it doesn't already exist
if (dbIndexes.Any(x => x.IndexName.InvariantEquals("IX_cmsMacroProperty_Alias")) == false)
@@ -54,4 +48,4 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSeven
Delete.Index("IX_cmsMacroProperty_Alias").OnTable("cmsMacroProperty");
}
}
}
}
@@ -30,13 +30,7 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSeven
public override void Up()
{
var dbIndexes = _forTesting ? new DbIndexDefinition[] { } : SqlSyntax.GetDefinedIndexes(Context.Database)
.Select(x => new DbIndexDefinition()
{
TableName = x.Item1,
IndexName = x.Item2,
ColumnName = x.Item3,
IsUnique = x.Item4
}).ToArray();
.Select(x => new DbIndexDefinition(x)).ToArray();
//make sure it doesn't already exist
if (dbIndexes.Any(x => x.IndexName.InvariantEquals("IX_cmsMacro_Alias")) == false)
@@ -75,4 +69,4 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSeven
Delete.Index("IX_cmsMacro_Alias").OnTable("cmsMacro");
}
}
}
}
@@ -18,13 +18,7 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSeven
public override void Up()
{
var dbIndexes = SqlSyntax.GetDefinedIndexes(Context.Database)
.Select(x => new DbIndexDefinition()
{
TableName = x.Item1,
IndexName = x.Item2,
ColumnName = x.Item3,
IsUnique = x.Item4
}).ToArray();
.Select(x => new DbIndexDefinition(x)).ToArray();
//add a foreign key to the parent id column too!
@@ -54,4 +48,4 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSeven
throw new DataLossException("Cannot downgrade from a version 7 database to a prior version, the database schema has already been modified");
}
}
}
}
@@ -26,13 +26,7 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSeven
// it is absolutely required to exist in order to have it as a foreign key reference, so we'll need to check it's existence
// this came to light from this issue: http://issues.umbraco.org/issue/U4-4133
var dbIndexes = SqlSyntax.GetDefinedIndexes(Context.Database)
.Select(x => new DbIndexDefinition()
{
TableName = x.Item1,
IndexName = x.Item2,
ColumnName = x.Item3,
IsUnique = x.Item4
}).ToArray();
.Select(x => new DbIndexDefinition(x)).ToArray();
if (dbIndexes.Any(x => x.IndexName.InvariantEquals("IX_cmsContent")) == false)
{
Create.Index("IX_cmsContent").OnTable("cmsContent").OnColumn("nodeId").Ascending().WithOptions().Unique();
@@ -95,4 +89,4 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSeven
//don't do anything, these keys should have always existed!
}
}
}
}
@@ -15,7 +15,7 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenEightZe
{
Execute.Code(database =>
{
var dbIndexes = SqlSyntax.GetDefinedIndexesDefinitions(Context.Database);
var dbIndexes = SqlSyntax.GetDefinedIndexesDefinitions(database);
//make sure it doesn't already exist
if (dbIndexes.Any(x => x.IndexName.InvariantEquals("IX_cmsPropertyTypeAlias")) == false)
@@ -62,13 +62,7 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenThreeZe
}
var dbIndexes = SqlSyntax.GetDefinedIndexes(Context.Database)
.Select(x => new DbIndexDefinition
{
TableName = x.Item1,
IndexName = x.Item2,
ColumnName = x.Item3,
IsUnique = x.Item4
}).ToArray();
.Select(x => new DbIndexDefinition(x)).ToArray();
//make sure it doesn't already exist
if (dbIndexes.Any(x => x.IndexName.InvariantEquals("IX_cmsDictionary_id")) == false)
@@ -104,4 +98,4 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenThreeZe
throw new NotImplementedException();
}
}
}
}
@@ -120,13 +120,7 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenThreeZe
var dbIndexes = SqlSyntax.GetDefinedIndexes(Context.Database)
.Select(x => new DbIndexDefinition()
{
TableName = x.Item1,
IndexName = x.Item2,
ColumnName = x.Item3,
IsUnique = x.Item4
}).ToArray();
.Select(x => new DbIndexDefinition(x)).ToArray();
//in some databases there's an index (IX_Master) on the master column which needs to be dropped first
var foundIndex = dbIndexes.FirstOrDefault(x => x.TableName.InvariantEquals("cmsTemplate") && x.ColumnName.InvariantEquals("master"));
@@ -167,4 +161,4 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenThreeZe
return path;
}
}
}
}
@@ -15,13 +15,7 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenThreeZe
public override void Up()
{
var indexes = SqlSyntax.GetDefinedIndexes(Context.Database)
.Select(x => new DbIndexDefinition()
{
TableName = x.Item1,
IndexName = x.Item2,
ColumnName = x.Item3,
IsUnique = x.Item4
}).ToArray();
.Select(x => new DbIndexDefinition(x)).ToArray();
// drop the index if it exists
if (indexes.Any(x => x.IndexName.InvariantEquals("IX_umbracoNodeUniqueID")))
@@ -38,4 +32,4 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenThreeZe
public override void Down()
{ }
}
}
}
@@ -1,7 +1,4 @@
using System;
using Umbraco.Core.Logging;
using Umbraco.Core.Models.Rdbms;
using Umbraco.Core.Persistence.DatabaseAnnotations;
using Umbraco.Core.Logging;
using Umbraco.Core.Persistence.SqlSyntax;
namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenTwelveZero
@@ -16,20 +13,22 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenTwelveZ
public override void Up()
{
var exists = Context.Database.FirstOrDefault<RelationTypeDto>("WHERE alias=@alias", new { alias = Constants.Conventions.RelationTypes.RelateParentMediaFolderOnDeleteAlias });
if (exists == null)
var relationTypeCount = Context.Database.ExecuteScalar<int>("SELECT COUNT(*) FROM umbracoRelationType WHERE alias=@alias",
new { alias = Constants.Conventions.RelationTypes.RelateParentMediaFolderOnDeleteAlias });
if (relationTypeCount > 0)
return;
var uniqueId = (Constants.Conventions.RelationTypes.RelateParentMediaFolderOnDeleteAlias + "____" + Constants.Conventions.RelationTypes.RelateParentMediaFolderOnDeleteName).ToGuid();
Insert.IntoTable("umbracoRelationType").Row(new
{
var uniqueId = (Constants.Conventions.RelationTypes.RelateParentMediaFolderOnDeleteAlias + "____" + Constants.Conventions.RelationTypes.RelateParentMediaFolderOnDeleteName).ToGuid();
Insert.IntoTable("umbracoRelationType").Row(new
{
typeUniqueId = uniqueId,
alias = Constants.Conventions.RelationTypes.RelateParentMediaFolderOnDeleteAlias,
name = Constants.Conventions.RelationTypes.RelateParentMediaFolderOnDeleteName,
childObjectType = Constants.ObjectTypes.MediaType,
parentObjectType = Constants.ObjectTypes.MediaType,
dual = false
});
}
typeUniqueId = uniqueId,
alias = Constants.Conventions.RelationTypes.RelateParentMediaFolderOnDeleteAlias,
name = Constants.Conventions.RelationTypes.RelateParentMediaFolderOnDeleteName,
childObjectType = Constants.ObjectTypes.MediaType,
parentObjectType = Constants.ObjectTypes.MediaType,
dual = false
});
}
public override void Down()
@@ -15,21 +15,35 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenTwelveZ
public override void Up()
{
var dbIndexes = SqlSyntax.GetDefinedIndexes(Context.Database)
.Select(x => new DbIndexDefinition()
{
TableName = x.Item1,
IndexName = x.Item2,
ColumnName = x.Item3,
IsUnique = x.Item4
}).ToArray();
//Ensure the index exists before dropping it
if (dbIndexes.Any(x => x.IndexName.InvariantEquals("IX_umbracoLanguage_languageISOCode")))
Execute.Code(database =>
{
Delete.Index("IX_umbracoLanguage_languageISOCode").OnTable("umbracoLanguage");
}
var localContext = new LocalMigrationContext(Context.CurrentDatabaseProvider, database, SqlSyntax, Logger);
// Some people seem to have a constraint in their DB instead of an index, we'd need to drop that one
// See: https://our.umbraco.com/forum/using-umbraco-and-getting-started/93282-upgrade-from-711-to-712-fails
var constraints = SqlSyntax.GetConstraintsPerTable(database).Distinct().ToArray();
if (constraints.Any(x => x.Item2.InvariantEquals("IX_umbracoLanguage_languageISOCode")))
{
localContext.Delete.UniqueConstraint("IX_umbracoLanguage_languageISOCode").FromTable("umbracoLanguage");
return localContext.GetSql();
}
return null;
});
Execute.Code(database =>
{
var localContext = new LocalMigrationContext(Context.CurrentDatabaseProvider, database, SqlSyntax, Logger);
//Now check for indexes of that name and drop that if it exists
var dbIndexes = SqlSyntax.GetDefinedIndexes(database)
.Select(x => new DbIndexDefinition(x)).ToArray();
if (dbIndexes.Any(x => x.IndexName.InvariantEquals("IX_umbracoLanguage_languageISOCode")))
{
localContext.Delete.Index("IX_umbracoLanguage_languageISOCode").OnTable("umbracoLanguage");
return localContext.GetSql();
}
return null;
});
Alter.Table("umbracoLanguage")
.AlterColumn("languageISOCode")
.AsString(14)
@@ -38,6 +52,8 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenTwelveZ
Create.Index("IX_umbracoLanguage_languageISOCode")
.OnTable("umbracoLanguage")
.OnColumn("languageISOCode")
.Ascending()
.WithOptions()
.Unique();
}
@@ -48,14 +48,8 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenTwoZero
//Some very old schemas don't have an index on the cmsContentType.nodeId column, I'm not actually sure when it was added but
// it is absolutely required to exist in order to add other foreign keys and much better for perf, so we'll need to check it's existence
// this came to light from this issue: http://issues.umbraco.org/issue/U4-4133
var dbIndexes = SqlSyntaxContext.SqlSyntaxProvider.GetDefinedIndexes(Context.Database)
.Select(x => new DbIndexDefinition()
{
TableName = x.Item1,
IndexName = x.Item2,
ColumnName = x.Item3,
IsUnique = x.Item4
}).ToArray();
var dbIndexes = SqlSyntax.GetDefinedIndexes(Context.Database)
.Select(x => new DbIndexDefinition(x)).ToArray();
if (dbIndexes.Any(x => x.IndexName.InvariantEquals("IX_cmsContentType")) == false)
{
Create.Index("IX_cmsContentType").OnTable("cmsContentType").OnColumn("nodeId").Ascending().WithOptions().Unique();
@@ -82,4 +76,4 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenTwoZero
throw new DataLossException("Cannot downgrade from a version 7.2 database to a prior version, the database schema has already been modified");
}
}
}
}
@@ -20,13 +20,7 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSixTwoZero
{
var dbIndexes = SqlSyntax.GetDefinedIndexes(Context.Database)
.Select(x => new DbIndexDefinition()
{
TableName = x.Item1,
IndexName = x.Item2,
ColumnName = x.Item3,
IsUnique = x.Item4
}).ToArray();
.Select(x => new DbIndexDefinition(x)).ToArray();
//do not create any indexes if they already exist in the database
@@ -118,4 +112,4 @@ DROP TABLE ""umbracoUserLogins_temp""");
}
}
}
}
@@ -186,6 +186,8 @@ UNION
SELECT '4CountOfLockedOut' AS colName, COUNT(id) AS num FROM umbracoUser WHERE userNoConsole = 1
UNION
SELECT '5CountOfInvited' AS colName, COUNT(id) AS num FROM umbracoUser WHERE lastLoginDate IS NULL AND userDisabled = 1 AND invitedDate IS NOT NULL
UNION
SELECT '6CountOfDisabled' AS colName, COUNT(id) AS num FROM umbracoUser WHERE userDisabled = 0 AND userNoConsole = 0 AND lastLoginDate IS NULL
ORDER BY colName";
var result = Database.Fetch<dynamic>(sql);
@@ -196,7 +198,8 @@ ORDER BY colName";
{UserState.Active, (int)result[1].num},
{UserState.Disabled, (int)result[2].num},
{UserState.LockedOut, (int)result[3].num},
{UserState.Invited, (int)result[4].num}
{UserState.Invited, (int)result[4].num},
{UserState.Inactive, (int) result[5].num}
};
}
@@ -765,6 +768,12 @@ ORDER BY colName";
sb.Append("(userDisabled = 0 AND userNoConsole = 0 AND lastLoginDate IS NOT NULL)");
appended = true;
}
if (userState.Contains(UserState.Inactive))
{
if (appended) sb.Append(" OR ");
sb.Append("(userDisabled = 0 AND userNoConsole = 0 AND lastLoginDate IS NULL)");
appended = true;
}
if (userState.Contains(UserState.Disabled))
{
if (appended) sb.Append(" OR ");
@@ -915,4 +924,4 @@ ORDER BY colName";
}
}
}
}
@@ -53,6 +53,8 @@ namespace Umbraco.Core.Persistence.SqlSyntax
string TruncateTable { get; }
string CreateConstraint { get; }
string DeleteConstraint { get; }
[Obsolete("This is never used, use the Format(ForeignKeyDefinition) instead")]
string CreateForeignKeyConstraint { get; }
string DeleteDefaultConstraint { get; }
string FormatDateTime(DateTime date, bool includeTime = true);
@@ -78,9 +80,32 @@ namespace Umbraco.Core.Persistence.SqlSyntax
IEnumerable<string> GetTablesInSchema(Database db);
IEnumerable<ColumnInfo> GetColumnsInSchema(Database db);
/// <summary>
/// Returns all constraints defined in the database (Primary keys, foreign keys, unique constraints...) (does not include indexes)
/// </summary>
/// <param name="db"></param>
/// <returns>
/// A Tuple containing: TableName, ConstraintName
/// </returns>
IEnumerable<Tuple<string, string>> GetConstraintsPerTable(Database db);
/// <summary>
/// Returns all constraints defined in the database (Primary keys, foreign keys, unique constraints...) (does not include indexes)
/// </summary>
/// <param name="db"></param>
/// <returns>
/// A Tuple containing: TableName, ColumnName, ConstraintName
/// </returns>
IEnumerable<Tuple<string, string, string>> GetConstraintsPerColumn(Database db);
/// <summary>
/// Returns all defined Indexes in the database excluding primary keys
/// </summary>
/// <param name="db"></param>
/// <returns>
/// A Tuple containing: TableName, IndexName, ColumnName, IsUnique
/// </returns>
IEnumerable<Tuple<string, string, string, bool>> GetDefinedIndexes(Database db);
}
}
}
@@ -78,6 +78,7 @@ namespace Umbraco.Core.Persistence.SqlSyntax
return list;
}
/// <inheritdoc />
public override IEnumerable<Tuple<string, string>> GetConstraintsPerTable(Database db)
{
List<Tuple<string, string>> list;
@@ -100,6 +101,7 @@ namespace Umbraco.Core.Persistence.SqlSyntax
return list;
}
/// <inheritdoc />
public override IEnumerable<Tuple<string, string, string>> GetConstraintsPerColumn(Database db)
{
List<Tuple<string, string, string>> list;
@@ -126,6 +128,7 @@ namespace Umbraco.Core.Persistence.SqlSyntax
return list;
}
/// <inheritdoc />
public override IEnumerable<Tuple<string, string, string, bool>> GetDefinedIndexes(Database db)
{
List<Tuple<string, string, string, bool>> list;
@@ -401,4 +404,4 @@ ORDER BY TABLE_NAME, INDEX_NAME",
return PetaPocoExtensions.EscapeAtSymbols(MySql.Data.MySqlClient.MySqlHelper.EscapeString(val));
}
}
}
}
@@ -10,7 +10,7 @@ namespace Umbraco.Core.Persistence.SqlSyntax
/// <summary>
/// Represents an SqlSyntaxProvider for Sql Ce
/// </summary>
[SqlSyntaxProviderAttribute(Constants.DatabaseProviders.SqlCe)]
[SqlSyntaxProvider(Constants.DatabaseProviders.SqlCe)]
public class SqlCeSyntaxProvider : MicrosoftSqlSyntaxProviderBase<SqlCeSyntaxProvider>
{
public SqlCeSyntaxProvider()
@@ -123,40 +123,27 @@ namespace Umbraco.Core.Persistence.SqlSyntax
item.IS_NULLABLE, item.DATA_TYPE)).ToList();
}
/// <inheritdoc />
public override IEnumerable<Tuple<string, string>> GetConstraintsPerTable(Database db)
{
var items = db.Fetch<dynamic>("SELECT TABLE_NAME, CONSTRAINT_NAME FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS");
var indexItems = db.Fetch<dynamic>("SELECT TABLE_NAME, INDEX_NAME FROM INFORMATION_SCHEMA.INDEXES");
return
items.Select(item => new Tuple<string, string>(item.TABLE_NAME, item.CONSTRAINT_NAME))
.Union(
indexItems.Select(
indexItem => new Tuple<string, string>(indexItem.TABLE_NAME, indexItem.INDEX_NAME)))
.ToList();
return items.Select(item => new Tuple<string, string>(item.TABLE_NAME, item.CONSTRAINT_NAME)).ToList();
}
/// <inheritdoc />
public override IEnumerable<Tuple<string, string, string>> GetConstraintsPerColumn(Database db)
{
var items =
db.Fetch<dynamic>(
"SELECT CONSTRAINT_NAME, TABLE_NAME, COLUMN_NAME FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE");
var indexItems = db.Fetch<dynamic>("SELECT INDEX_NAME, TABLE_NAME, COLUMN_NAME FROM INFORMATION_SCHEMA.INDEXES");
return
items.Select(
item => new Tuple<string, string, string>(item.TABLE_NAME, item.COLUMN_NAME, item.CONSTRAINT_NAME))
.Union(
indexItems.Select(
indexItem =>
new Tuple<string, string, string>(indexItem.TABLE_NAME, indexItem.COLUMN_NAME,
indexItem.INDEX_NAME))).ToList();
var items = db.Fetch<dynamic>("SELECT TABLE_NAME, COLUMN_NAME, CONSTRAINT_NAME FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE");
return items.Select(item => new Tuple<string, string, string>(item.TABLE_NAME, item.COLUMN_NAME, item.CONSTRAINT_NAME)).ToList();
}
/// <inheritdoc />
public override IEnumerable<Tuple<string, string, string, bool>> GetDefinedIndexes(Database db)
{
var items =
db.Fetch<dynamic>(
@"SELECT TABLE_NAME, INDEX_NAME, COLUMN_NAME, [UNIQUE] FROM INFORMATION_SCHEMA.INDEXES
WHERE INDEX_NAME NOT LIKE 'PK_%'
WHERE PRIMARY_KEY=0
ORDER BY TABLE_NAME, INDEX_NAME");
return
items.Select(
@@ -215,4 +202,4 @@ ORDER BY TABLE_NAME, INDEX_NAME");
public override string DropIndex { get { return "DROP INDEX {1}.{0}"; } }
}
}
}
@@ -1,186 +1,188 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Umbraco.Core.Persistence.DatabaseModelDefinitions;
namespace Umbraco.Core.Persistence.SqlSyntax
{
/// <summary>
/// Represents an SqlSyntaxProvider for Sql Server.
/// </summary>
[SqlSyntaxProvider(Constants.DatabaseProviders.SqlServer)]
public class SqlServerSyntaxProvider : MicrosoftSqlSyntaxProviderBase<SqlServerSyntaxProvider>
{
/// <summary>
/// Gets/sets the version of the current SQL server instance
/// </summary>
internal SqlServerVersionName GetVersionName(Database database)
{
if (_versionName.HasValue)
return _versionName.Value;
try
{
var version = database.ExecuteScalar<string>("SELECT SERVERPROPERTY('productversion')");
var firstPart = version.Split('.')[0];
switch (firstPart)
{
case "13":
_versionName = SqlServerVersionName.V2016;
break;
case "12":
_versionName = SqlServerVersionName.V2014;
break;
case "11":
_versionName = SqlServerVersionName.V2012;
break;
case "10":
_versionName = SqlServerVersionName.V2008;
break;
case "9":
_versionName = SqlServerVersionName.V2005;
break;
case "8":
_versionName = SqlServerVersionName.V2000;
break;
case "7":
_versionName = SqlServerVersionName.V7;
break;
default:
_versionName = SqlServerVersionName.Other;
break;
}
}
catch (Exception)
{
_versionName = SqlServerVersionName.Invalid;
}
return _versionName.Value;
}
private SqlServerVersionName? _versionName;
/// <summary>
/// SQL Server stores default values assigned to columns as constraints, it also stores them with named values, this is the only
/// server type that does this, therefore this method doesn't exist on any other syntax provider
/// </summary>
/// <returns></returns>
public IEnumerable<Tuple<string, string, string, string>> GetDefaultConstraintsPerColumn(Database db)
{
var items = db.Fetch<dynamic>("SELECT TableName = t.Name,ColumnName = c.Name,dc.Name,dc.[Definition] FROM sys.tables t INNER JOIN sys.default_constraints dc ON t.object_id = dc.parent_object_id INNER JOIN sys.columns c ON dc.parent_object_id = c.object_id AND c.column_id = dc.parent_column_id");
return items.Select(x => new Tuple<string, string, string, string>(x.TableName, x.ColumnName, x.Name, x.Definition));
}
public override IEnumerable<string> GetTablesInSchema(Database db)
{
var items = db.Fetch<dynamic>("SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES");
return items.Select(x => x.TABLE_NAME).Cast<string>().ToList();
}
public override IEnumerable<ColumnInfo> GetColumnsInSchema(Database db)
{
var items = db.Fetch<dynamic>("SELECT TABLE_NAME, COLUMN_NAME, ORDINAL_POSITION, COLUMN_DEFAULT, IS_NULLABLE, DATA_TYPE FROM INFORMATION_SCHEMA.COLUMNS");
return
items.Select(
item =>
new ColumnInfo(item.TABLE_NAME, item.COLUMN_NAME, item.ORDINAL_POSITION, item.COLUMN_DEFAULT,
item.IS_NULLABLE, item.DATA_TYPE)).ToList();
}
public override IEnumerable<Tuple<string, string>> GetConstraintsPerTable(Database db)
{
var items =
db.Fetch<dynamic>(
"SELECT TABLE_NAME, CONSTRAINT_NAME FROM INFORMATION_SCHEMA.CONSTRAINT_TABLE_USAGE");
return items.Select(item => new Tuple<string, string>(item.TABLE_NAME, item.CONSTRAINT_NAME)).ToList();
}
public override IEnumerable<Tuple<string, string, string>> GetConstraintsPerColumn(Database db)
{
var items =
db.Fetch<dynamic>(
"SELECT TABLE_NAME, COLUMN_NAME, CONSTRAINT_NAME FROM INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE");
return items.Select(item => new Tuple<string, string, string>(item.TABLE_NAME, item.COLUMN_NAME, item.CONSTRAINT_NAME)).ToList();
}
public override IEnumerable<Tuple<string, string, string, bool>> GetDefinedIndexes(Database db)
{
var items =
db.Fetch<dynamic>(
@"select T.name as TABLE_NAME, I.name as INDEX_NAME, AC.Name as COLUMN_NAME,
CASE WHEN I.is_unique_constraint = 1 OR I.is_unique = 1 THEN 1 ELSE 0 END AS [UNIQUE]
from sys.tables as T inner join sys.indexes as I on T.[object_id] = I.[object_id]
inner join sys.index_columns as IC on IC.[object_id] = I.[object_id] and IC.[index_id] = I.[index_id]
inner join sys.all_columns as AC on IC.[object_id] = AC.[object_id] and IC.[column_id] = AC.[column_id]
WHERE I.name NOT LIKE 'PK_%'
order by T.name, I.name");
return items.Select(item => new Tuple<string, string, string, bool>(item.TABLE_NAME, item.INDEX_NAME, item.COLUMN_NAME,
item.UNIQUE == 1)).ToList();
}
public override bool DoesTableExist(Database db, string tableName)
{
var result =
db.ExecuteScalar<long>("SELECT COUNT(*) FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = @TableName",
new { TableName = tableName });
return result > 0;
}
public override string FormatColumnRename(string tableName, string oldName, string newName)
{
return string.Format(RenameColumn, tableName, oldName, newName);
}
public override string FormatTableRename(string oldName, string newName)
{
return string.Format(RenameTable, oldName, newName);
}
protected override string FormatIdentity(ColumnDefinition column)
{
return column.IsIdentity ? GetIdentityString(column) : string.Empty;
}
public override Sql SelectTop(Sql sql, int top)
{
return new Sql(sql.SQL.Insert(sql.SQL.IndexOf(' '), " TOP " + top), sql.Arguments);
}
private static string GetIdentityString(ColumnDefinition column)
{
return "IDENTITY(1,1)";
}
protected override string FormatSystemMethods(SystemMethods systemMethod)
{
switch (systemMethod)
{
case SystemMethods.NewGuid:
return "NEWID()";
case SystemMethods.CurrentDateTime:
return "GETDATE()";
//case SystemMethods.NewSequentialId:
// return "NEWSEQUENTIALID()";
//case SystemMethods.CurrentUTCDateTime:
// return "GETUTCDATE()";
}
return null;
}
public override string DeleteDefaultConstraint
{
get { return "ALTER TABLE [{0}] DROP CONSTRAINT [DF_{0}_{1}]"; }
}
public override string DropIndex { get { return "DROP INDEX {0} ON {1}"; } }
public override string RenameColumn { get { return "sp_rename '{0}.{1}', '{2}', 'COLUMN'"; } }
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using Umbraco.Core.Persistence.DatabaseModelDefinitions;
namespace Umbraco.Core.Persistence.SqlSyntax
{
/// <summary>
/// Represents an SqlSyntaxProvider for Sql Server.
/// </summary>
[SqlSyntaxProvider(Constants.DatabaseProviders.SqlServer)]
public class SqlServerSyntaxProvider : MicrosoftSqlSyntaxProviderBase<SqlServerSyntaxProvider>
{
/// <summary>
/// Gets/sets the version of the current SQL server instance
/// </summary>
internal SqlServerVersionName GetVersionName(Database database)
{
if (_versionName.HasValue)
return _versionName.Value;
try
{
var version = database.ExecuteScalar<string>("SELECT SERVERPROPERTY('productversion')");
var firstPart = version.Split('.')[0];
switch (firstPart)
{
case "13":
_versionName = SqlServerVersionName.V2016;
break;
case "12":
_versionName = SqlServerVersionName.V2014;
break;
case "11":
_versionName = SqlServerVersionName.V2012;
break;
case "10":
_versionName = SqlServerVersionName.V2008;
break;
case "9":
_versionName = SqlServerVersionName.V2005;
break;
case "8":
_versionName = SqlServerVersionName.V2000;
break;
case "7":
_versionName = SqlServerVersionName.V7;
break;
default:
_versionName = SqlServerVersionName.Other;
break;
}
}
catch (Exception)
{
_versionName = SqlServerVersionName.Invalid;
}
return _versionName.Value;
}
private SqlServerVersionName? _versionName;
/// <summary>
/// SQL Server stores default values assigned to columns as constraints, it also stores them with named values, this is the only
/// server type that does this, therefore this method doesn't exist on any other syntax provider
/// </summary>
/// <returns></returns>
public IEnumerable<Tuple<string, string, string, string>> GetDefaultConstraintsPerColumn(Database db)
{
var items = db.Fetch<dynamic>("SELECT TableName = t.Name, ColumnName = c.Name, dc.Name, dc.[Definition] FROM sys.tables t INNER JOIN sys.default_constraints dc ON t.object_id = dc.parent_object_id INNER JOIN sys.columns c ON dc.parent_object_id = c.object_id AND c.column_id = dc.parent_column_id INNER JOIN sys.schemas as s on t.[schema_id] = s.[schema_id] WHERE s.name = (SELECT SCHEMA_NAME())");
return items.Select(x => new Tuple<string, string, string, string>(x.TableName, x.ColumnName, x.Name, x.Definition));
}
public override IEnumerable<string> GetTablesInSchema(Database db)
{
var items = db.Fetch<dynamic>("SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = (SELECT SCHEMA_NAME())");
return items.Select(x => x.TABLE_NAME).Cast<string>().ToList();
}
public override IEnumerable<ColumnInfo> GetColumnsInSchema(Database db)
{
var items = db.Fetch<dynamic>("SELECT TABLE_NAME, COLUMN_NAME, ORDINAL_POSITION, COLUMN_DEFAULT, IS_NULLABLE, DATA_TYPE FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA = (SELECT SCHEMA_NAME())");
return
items.Select(
item =>
new ColumnInfo(item.TABLE_NAME, item.COLUMN_NAME, item.ORDINAL_POSITION, item.COLUMN_DEFAULT,
item.IS_NULLABLE, item.DATA_TYPE)).ToList();
}
/// <inheritdoc />
public override IEnumerable<Tuple<string, string>> GetConstraintsPerTable(Database db)
{
var items =
db.Fetch<dynamic>(
"SELECT TABLE_NAME, CONSTRAINT_NAME FROM INFORMATION_SCHEMA.CONSTRAINT_TABLE_USAGE WHERE TABLE_SCHEMA = (SELECT SCHEMA_NAME())");
return items.Select(item => new Tuple<string, string>(item.TABLE_NAME, item.CONSTRAINT_NAME)).ToList();
}
/// <inheritdoc />
public override IEnumerable<Tuple<string, string, string>> GetConstraintsPerColumn(Database db)
{
var items =
db.Fetch<dynamic>(
"SELECT TABLE_NAME, COLUMN_NAME, CONSTRAINT_NAME FROM INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE WHERE TABLE_SCHEMA = (SELECT SCHEMA_NAME())");
return items.Select(item => new Tuple<string, string, string>(item.TABLE_NAME, item.COLUMN_NAME, item.CONSTRAINT_NAME)).ToList();
}
/// <inheritdoc />
public override IEnumerable<Tuple<string, string, string, bool>> GetDefinedIndexes(Database db)
{
var items =
db.Fetch<dynamic>(
@"select T.name as TABLE_NAME, I.name as INDEX_NAME, AC.Name as COLUMN_NAME,
CASE WHEN I.is_unique_constraint = 1 OR I.is_unique = 1 THEN 1 ELSE 0 END AS [UNIQUE]
from sys.tables as T inner join sys.indexes as I on T.[object_id] = I.[object_id]
inner join sys.index_columns as IC on IC.[object_id] = I.[object_id] and IC.[index_id] = I.[index_id]
inner join sys.all_columns as AC on IC.[object_id] = AC.[object_id] and IC.[column_id] = AC.[column_id]
inner join sys.schemas as S on T.[schema_id] = S.[schema_id]
WHERE S.name = (SELECT SCHEMA_NAME()) AND I.is_primary_key = 0
order by T.name, I.name");
return items.Select(item => new Tuple<string, string, string, bool>(item.TABLE_NAME, item.INDEX_NAME, item.COLUMN_NAME,
item.UNIQUE == 1)).ToList();
}
public override bool DoesTableExist(Database db, string tableName)
{
var result =
db.ExecuteScalar<long>("SELECT COUNT(*) FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = @TableName AND TABLE_SCHEMA = (SELECT SCHEMA_NAME())",
new { TableName = tableName });
return result > 0;
}
public override string FormatColumnRename(string tableName, string oldName, string newName)
{
return string.Format(RenameColumn, tableName, oldName, newName);
}
public override string FormatTableRename(string oldName, string newName)
{
return string.Format(RenameTable, oldName, newName);
}
protected override string FormatIdentity(ColumnDefinition column)
{
return column.IsIdentity ? GetIdentityString(column) : string.Empty;
}
public override Sql SelectTop(Sql sql, int top)
{
return new Sql(sql.SQL.Insert(sql.SQL.IndexOf(' '), " TOP " + top), sql.Arguments);
}
private static string GetIdentityString(ColumnDefinition column)
{
return "IDENTITY(1,1)";
}
protected override string FormatSystemMethods(SystemMethods systemMethod)
{
switch (systemMethod)
{
case SystemMethods.NewGuid:
return "NEWID()";
case SystemMethods.CurrentDateTime:
return "GETDATE()";
//case SystemMethods.NewSequentialId:
// return "NEWSEQUENTIALID()";
//case SystemMethods.CurrentUTCDateTime:
// return "GETUTCDATE()";
}
return null;
}
public override string DeleteDefaultConstraint
{
get { return "ALTER TABLE [{0}] DROP CONSTRAINT [DF_{0}_{1}]"; }
}
public override string DropIndex { get { return "DROP INDEX {0} ON {1}"; } }
public override string RenameColumn { get { return "sp_rename '{0}.{1}', '{2}', 'COLUMN'"; } }
}
}
@@ -537,10 +537,11 @@ namespace Umbraco.Core.Persistence.SqlSyntax
public virtual string CreateConstraint { get { return "ALTER TABLE {0} ADD CONSTRAINT {1} {2} ({3})"; } }
public virtual string DeleteConstraint { get { return "ALTER TABLE {0} DROP CONSTRAINT {1}"; } }
public virtual string CreateForeignKeyConstraint { get { return "ALTER TABLE {0} ADD CONSTRAINT {1} FOREIGN KEY ({2}) REFERENCES {3} ({4}){5}{6}"; } }
public virtual string ConvertIntegerToOrderableString { get { return "REPLACE(STR({0}, 8), SPACE(1), '0')"; } }
public virtual string ConvertDateToOrderableString { get { return "CONVERT(nvarchar, {0}, 102)"; } }
public virtual string ConvertDecimalToOrderableString { get { return "REPLACE(STR({0}, 20, 9), SPACE(1), '0')"; } }
}
}
}
@@ -9,13 +9,7 @@ namespace Umbraco.Core.Persistence.SqlSyntax
public static IEnumerable<DbIndexDefinition> GetDefinedIndexesDefinitions(this ISqlSyntaxProvider sql, Database db)
{
return sql.GetDefinedIndexes(db)
.Select(x => new DbIndexDefinition()
{
TableName = x.Item1,
IndexName = x.Item2,
ColumnName = x.Item3,
IsUnique = x.Item4
}).ToArray();
.Select(x => new DbIndexDefinition(x)).ToArray();
}
/// <summary>
@@ -57,4 +51,4 @@ namespace Umbraco.Core.Persistence.SqlSyntax
In,
NotIn
}
}
}
@@ -42,18 +42,19 @@ namespace Umbraco.Core.PropertyEditors.ValueConverters
return null;
}
var isMultipleDataType = IsMultipleDataType(propertyType.DataTypeId, propertyType.PropertyEditorAlias);
var selectedValues = (string[]) source;
if (selectedValues.Any())
{
if (IsMultipleDataType(propertyType.DataTypeId, propertyType.PropertyEditorAlias))
{
if (isMultipleDataType)
return selectedValues;
}
return selectedValues.First();
}
return source;
return isMultipleDataType ? source : string.Empty;
}
public Type GetPropertyValueType(PublishedPropertyType propertyType)
@@ -720,7 +720,7 @@ namespace Umbraco.Core.Security
}
else
{
//if the salt bytes is too long for the required key length for the algorithm, extend it
//if the salt bytes is too short for the required key length for the algorithm, extend it
var numArray2 = new byte[keyedHashAlgorithm.Key.Length];
var dstOffset = 0;
while (dstOffset < numArray2.Length)
@@ -963,4 +963,4 @@ namespace Umbraco.Core.Security
}
}
}
}
@@ -77,7 +77,7 @@ namespace Umbraco.Core.Services
regs = xr.Repository.GetAll().ToArray();
// default role is single server, but if registrations contain more
// than one active server, then role is master or slave
// than one active server, then role is master or replica
_currentServerRole = regs.Count(x => x.IsActive) > 1
? (server.IsMaster ? ServerRole.Master : ServerRole.Slave)
: ServerRole.Single;
@@ -175,4 +175,4 @@ namespace Umbraco.Core.Services
return _currentServerRole;
}
}
}
}
+1 -1
View File
@@ -699,7 +699,7 @@ namespace Umbraco.Core.Services
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repository = RepositoryFactory.CreateUserRepository(uow);
return repository.GetPagedResultsByQuery(null, pageIndex, pageSize, out totalRecords, member => member.Username);
return repository.GetPagedResultsByQuery(null, pageIndex, pageSize, out totalRecords, member => member.Name);
}
}
+24
View File
@@ -1574,5 +1574,29 @@ namespace Umbraco.Core
guid[left] = guid[right];
guid[right] = temp;
}
/// <summary>
/// Converts a file name to a friendly name for a content item
/// </summary>
/// <param name="fileName"></param>
/// <returns></returns>
public static string ToFriendlyName(this string fileName)
{
// strip the file extension
fileName = fileName.StripFileExtension();
// underscores and dashes to spaces
fileName = fileName.ReplaceMany(new[] { '_', '-' }, ' ');
// any other conversions ?
// Pascalcase (to be done last)
fileName = System.Threading.Thread.CurrentThread.CurrentCulture.TextInfo.ToTitleCase(fileName);
// Replace multiple consecutive spaces with a single space
fileName = string.Join(" ", fileName.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries));
return fileName;
}
}
}
@@ -51,10 +51,9 @@ namespace Umbraco.Core.Sync
if (request != null)
{
var applicationUrl = GetApplicationUrlFromRequest(request);
newApplicationUrl = !appContext._umbracoApplicationDomains.Contains(applicationUrl);
newApplicationUrl = appContext._umbracoApplicationDomains.TryAdd(applicationUrl, applicationUrl);
if (newApplicationUrl)
{
appContext._umbracoApplicationDomains.Add(applicationUrl);
LogHelper.Info(typeof(ApplicationUrlHelper), string.Format("New ApplicationUrl detected: {0}", applicationUrl));
}
}
+2 -2
View File
@@ -16,7 +16,7 @@ namespace Umbraco.Core.Sync
Single = 1,
/// <summary>
/// In a multi-servers environment, the server is a slave server.
/// In a multi-servers environment, the server is a replica server.
/// </summary>
Slave = 2,
@@ -25,4 +25,4 @@ namespace Umbraco.Core.Sync
/// </summary>
Master = 3
}
}
}
@@ -129,7 +129,7 @@ namespace Umbraco.Tests
public void SetApplicationUrlFromDcSettingsSsl2()
{
// set from distributed call settings
// other servers are slave servers
// other servers are replica servers
var settings = Mock.Of<IUmbracoSettingsSection>(section =>
section.DistributedCall == Mock.Of<IDistributedCallSection>(callSection => callSection.Enabled == true && callSection.Servers == new IServer[]
@@ -224,7 +224,7 @@ namespace Umbraco.Tests
[Test]
public void ServerRoleUnknown2()
{
// distributed call enabled, cannot find server, assume it's an undeclared slave
// distributed call enabled, cannot find server, assume it's an undeclared replica
var settings = Mock.Of<IUmbracoSettingsSection>(section =>
section.DistributedCall == Mock.Of<IDistributedCallSection>(callSection => callSection.Enabled == true && callSection.Servers == new IServer[]
@@ -301,4 +301,4 @@ namespace Umbraco.Tests
Assert.AreEqual("httpx://whatever.com/umbraco", appCtx._umbracoApplicationUrl);
}
}
}
}
@@ -23,6 +23,12 @@ namespace Umbraco.Tests.Configurations.UmbracoSettings
Assert.IsTrue(SettingsSection.WebRouting.DisableAlternativeTemplates == false);
}
[Test]
public void ValidateAlternativeTemplates()
{
Assert.IsTrue(SettingsSection.WebRouting.ValidateAlternativeTemplates == false);
}
[Test]
public void DisableFindContentByIdPath()
{
File diff suppressed because one or more lines are too long
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<system.webServer>
<staticContent>
<clientCache cacheControlMode="UseMaxAge" cacheControlMaxAge="7.00:00:00" />
</staticContent>
</system.webServer>
</configuration>
@@ -10,10 +10,12 @@
scope.publishStatus = {};
scope.disableTemplates = Umbraco.Sys.ServerVariables.features.disabledFeatures.disableTemplates;
function onInit() {
scope.allowOpen = true;
function onInit() {
// If logged in user has access to the settings section
// show the open anchors - if the user doesn't have
// access, documentType is null, see ContentModelMapper
scope.allowOpen = scope.node.documentType !== null;
scope.datePickerConfig = {
pickDate: true,
@@ -41,11 +43,13 @@
// make sure dates are formatted to the user's locale
formatDatesToLocal();
// Declare a fallback URL for the <umb-node-preview/> directive
scope.previewOpenUrl = '#/settings/documenttypes/edit/' + scope.documentType.id;
// Make sure to set the node status
setNodePublishStatus(scope.node);
// Declare a fallback URL for the <umb-node-preview/> directive
if (scope.documentType !== null) {
scope.previewOpenUrl = '#/settings/documenttypes/edit/' + scope.documentType.id;
}
}
scope.auditTrailPageChange = function (pageNumber) {
@@ -53,7 +57,7 @@
loadAuditTrail();
};
scope.openDocumentType = function (documentType) {
scope.openDocumentType = function (documentType) {
var url = "/settings/documenttypes/edit/" + documentType.id;
$location.url(url);
};
@@ -99,7 +103,7 @@
item.timestampFormatted = dateHelper.getLocalDate(item.timestamp, currentUser.locale, 'LLL');
});
});
scope.auditTrail = data.items;
scope.auditTrailOptions.pageNumber = data.pageNumber;
scope.auditTrailOptions.pageSize = data.pageSize;
@@ -107,7 +111,7 @@
scope.auditTrailOptions.totalPages = data.totalPages;
setAuditTrailLogTypeColor(scope.auditTrail);
scope.loadingAuditTrail = false;
});
@@ -115,6 +119,7 @@
function setAuditTrailLogTypeColor(auditTrail) {
angular.forEach(auditTrail, function (item) {
switch (item.logType) {
case "Publish":
item.logTypeColor = "success";
@@ -130,7 +135,6 @@
}
function setNodePublishStatus(node) {
// deleted node
if(node.trashed === true) {
scope.publishStatus.label = localizationService.localize("general_deleted");
@@ -224,7 +228,7 @@
eventsService.emit("editors.content.changeUnpublishDate", args);
}
function ucfirst(string) {
return string.charAt(0).toUpperCase() + string.slice(1);
}
@@ -233,13 +237,13 @@
// get current backoffice user and format dates
userService.getCurrentUser().then(function (currentUser) {
scope.node.createDateFormatted = dateHelper.getLocalDate(scope.node.createDate, currentUser.locale, 'LLL');
scope.node.releaseDateYear = scope.node.releaseDate ? ucfirst(dateHelper.getLocalDate(scope.node.releaseDate, currentUser.locale, 'YYYY')) : null;
scope.node.releaseDateMonth = scope.node.releaseDate ? ucfirst(dateHelper.getLocalDate(scope.node.releaseDate, currentUser.locale, 'MMMM')) : null;
scope.node.releaseDateDayNumber = scope.node.releaseDate ? ucfirst(dateHelper.getLocalDate(scope.node.releaseDate, currentUser.locale, 'DD')) : null;
scope.node.releaseDateDay = scope.node.releaseDate ? ucfirst(dateHelper.getLocalDate(scope.node.releaseDate, currentUser.locale, 'dddd')) : null;
scope.node.releaseDateTime = scope.node.releaseDate ? ucfirst(dateHelper.getLocalDate(scope.node.releaseDate, currentUser.locale, 'HH:mm')) : null;
scope.node.removeDateYear = scope.node.removeDate ? ucfirst(dateHelper.getLocalDate(scope.node.removeDate, currentUser.locale, 'YYYY')) : null;
scope.node.removeDateMonth = scope.node.removeDate ? ucfirst(dateHelper.getLocalDate(scope.node.removeDate, currentUser.locale, 'MMMM')) : null;
scope.node.removeDateDayNumber = scope.node.removeDate ? ucfirst(dateHelper.getLocalDate(scope.node.removeDate, currentUser.locale, 'DD')) : null;
@@ -264,8 +268,8 @@
scope.$watch('node.updateDate', function(newValue, oldValue){
if(!newValue) { return; }
if(newValue === oldValue) { return; }
if(newValue === oldValue) { return; }
if(isInfoTab) {
loadAuditTrail();
formatDatesToLocal();
@@ -8,11 +8,16 @@
var evts = [];
function onInit() {
scope.allowOpenMediaType = true;
// If logged in user has access to the settings section
// show the open anchors - if the user doesn't have
// access, contentType is null, see MediaModelMapper
scope.allowOpen = scope.node.contentType !== null;
// get document type details
scope.mediaType = scope.node.contentType;
// get node url
scope.nodeUrl = scope.node.mediaLink;
// set the media link initially
setMediaLink();
// make sure dates are formatted to the user's locale
formatDatesToLocal();
}
@@ -25,16 +30,25 @@
});
}
function setMediaLink(){
scope.nodeUrl = scope.node.mediaLink;
}
scope.openMediaType = function (mediaType) {
// remove first "#" from url if it is prefixed else the path won't work
var url = "/settings/mediaTypes/edit/" + mediaType.id;
$location.path(url);
};
// watch for content updates - reload content when node is saved, published etc.
scope.$watch('node.updateDate', function(newValue, oldValue){
if(!newValue) { return; }
if(newValue === oldValue) { return; }
// Update the media link
setMediaLink();
// Update the create and update dates
formatDatesToLocal();
});
@@ -46,7 +60,6 @@
});
onInit();
}
var directive = {
@@ -64,4 +77,4 @@
angular.module('umbraco.directives').directive('umbMediaNodeInfo', MediaNodeInfoDirective);
})();
})();
@@ -8,7 +8,7 @@
scope.search = "";
scope.miniListViews = [];
scope.breadcrumb = [];
var miniListViewsHistory = [];
var goingForward = true;
var skipAnimation = true;
@@ -60,9 +60,13 @@
entityResource.getPagedChildren(miniListView.node.id, scope.entityType, miniListView.pagination)
.then(function (data) {
// update children
miniListView.children = data.items;
_.each(miniListView.children, function(c) {
// child allowed by default
c.allowed = true;
// convert legacy icon for node
if(c.icon) {
c.icon = iconHelper.convertFromLegacyIcon(c.icon);
@@ -74,6 +78,17 @@
c.published = c.metaData.IsPublished;
}
}
// filter items if there is a filter and it's not advanced
// ** ignores advanced filter at the moment
if (scope.entityTypeFilter && !scope.entityTypeFilter.filterAdvanced) {
var a = scope.entityTypeFilter.filter.toLowerCase().replace(/\s/g, '').split(',');
var found = a.indexOf(c.metaData.ContentTypeAlias.toLowerCase()) >= 0;
if (!scope.entityTypeFilter.filterExclude && !found || scope.entityTypeFilter.filterExclude && found) {
c.allowed = false;
}
}
});
// update pagination
miniListView.pagination.totalItems = data.totalItems;
@@ -89,7 +104,7 @@
};
scope.selectNode = function(node) {
if(scope.onSelect) {
if (scope.onSelect && node.allowed) {
scope.onSelect({'node': node});
}
};
@@ -202,7 +217,8 @@
entityType: "@",
startNodeId: "=",
onSelect: "&",
onClose: "&"
onClose: "&",
entityTypeFilter: "="
},
link: link
};
@@ -50,6 +50,11 @@ Use this directive make an element sticky and follow the page when scrolling.
function activate() {
if (bar.parents(".umb-property").length > 1) {
bar.addClass("nested");
return;
}
if (attr.scrollableContainer) {
scrollableContainer = $(attr.scrollableContainer);
} else {
@@ -298,10 +298,10 @@ function contentTypeResource($q, $http, umbRequestHelper, umbDataFormatter) {
},
createCollection: function (parentId, collectionName, collectionItemName, collectionIcon, collectionItemIcon) {
createCollection: function (parentId, collectionName, collectionCreateTemplate, collectionItemName, collectionItemCreateTemplate, collectionIcon, collectionItemIcon) {
return umbRequestHelper.resourcePromise(
$http.post(umbRequestHelper.getApiUrl("contentTypeApiBaseUrl", "PostCreateCollection", { parentId: parentId, collectionName: collectionName, collectionItemName: collectionItemName, collectionIcon: collectionIcon, collectionItemIcon: collectionItemIcon})),
$http.post(umbRequestHelper.getApiUrl("contentTypeApiBaseUrl", "PostCreateCollection", { parentId: parentId, collectionName: collectionName, collectionCreateTemplate: collectionCreateTemplate, collectionItemName: collectionItemName, collectionItemCreateTemplate: collectionItemCreateTemplate, collectionIcon: collectionIcon, collectionItemIcon: collectionItemIcon})),
'Failed to create collection under ' + parentId);
},
@@ -260,7 +260,7 @@ function contentEditingHelper(fileManager, $q, $location, $routeParams, notifica
// if save button is alread the default don't change it just update the label
if (buttons.defaultButton && buttons.defaultButton.letter === "A") {
buttons.defaultButton.labelKey = "buttons_saveAndSchedule";
return;
return buttons;
}
if(buttons.defaultButton && buttons.subButtons && buttons.subButtons.length > 0) {
@@ -761,6 +761,8 @@ function tinyMceService($log, imageHelper, $http, $timeout, macroResource, macro
* @param {string} input the string to parse
*/
getAnchorNames: function (input) {
if (!input) return [];
var anchorPattern = /<a id=\\"(.*?)\\">/gi;
var matches = input.match(anchorPattern);
var anchors = [];
@@ -771,7 +773,9 @@ function tinyMceService($log, imageHelper, $http, $timeout, macroResource, macro
});
}
return anchors;
return anchors.filter(function(val, i, self) {
return self.indexOf(val) === i;
});
},
insertLinkInEditor: function (editor, target, anchorElm) {
@@ -8,7 +8,8 @@
{ "value": 0, "name": "Active", "key": "Active", "color": "success" },
{ "value": 1, "name": "Disabled", "key": "Disabled", "color": "danger" },
{ "value": 2, "name": "Locked out", "key": "LockedOut", "color": "danger" },
{ "value": 3, "name": "Invited", "key": "Invited", "color": "warning" }
{ "value": 3, "name": "Invited", "key": "Invited", "color": "warning" },
{ "value": 4, "name": "Inactive", "key": "Inactive", "color": "warning" }
];
angular.forEach(userStates, function (userState) {
@@ -126,6 +126,7 @@
@import "components/umb-querybuilder.less";
@import "components/umb-pagination.less";
@import "components/umb-mini-list-view.less";
@import "components/umb-multiple-textbox.less";
@import "components/umb-badge.less";
@import "components/umb-nested-content.less";
@import "components/umb-checkmark.less";
@@ -1,12 +1,18 @@
.umb-editor-sub-header {
padding: 15px 0;
margin-bottom: 30px;
background: @white;
display: flex;
justify-content: space-between;
margin-top: -30px;
position: relative;
top: 0;
padding: 15px 0;
margin-bottom: 30px;
background: @white;
display: flex;
justify-content: space-between;
margin-top: -30px;
position: relative;
top: 0;
&.nested {
margin-top: 0;
margin-bottom: 0;
background: @gray-10;
}
}
.umb-editor-sub-header.-umb-sticky-bar {
@@ -27,12 +27,18 @@
}
.umb-iconpicker-item a:hover,
.umb-iconpicker-item a:focus,
.umb-iconpicker-item.-selected {
.umb-iconpicker-item a:focus {
background: @gray-10;
outline: none;
}
.umb-iconpicker-item.-selected {
background: @gray-10;
border: solid 1px @turquoise-d1;
border-radius: @baseBorderRadius;
box-sizing: border-box;
}
.umb-iconpicker-item a:active {
background: @gray-10;
}
@@ -54,11 +60,6 @@
border-radius: 3px;
}
// Hide Circle when not active
i.small{
display: none;
}
// Circle behind the checkmark
i.small.active{
font-size: 14px;
@@ -0,0 +1,34 @@
.umb-multiple-textbox .textbox-wrapper {
align-items: center;
margin-bottom: 15px;
}
.umb-multiple-textbox .textbox-wrapper .umb-editor {
margin-bottom: 0;
}
.umb-multiple-textbox .textbox-wrapper i {
margin-right: 5px;
}
.umb-multiple-textbox .textbox-wrapper i.handle {
margin-left: 5px;
}
.umb-multiple-textbox .textbox-wrapper a.remove {
margin-left: 5px;
text-decoration: none;
}
.umb-multiple-textbox .add-link {
&:extend(.umb-node-preview-add);
}
.umb-editor-wrapper .umb-multiple-textbox .add-link {
&:extend(.umb-editor-wrapper .umb-node-preview);
}
.umb-modal .umb-multiple-textbox .textbox-wrapper .umb-editor {
flex: 1 1 auto;
width: auto;
}
@@ -1,16 +1,13 @@
.nested-content
{
.umb-nested-content {
text-align: center;
}
.nested-content--not-supported
{
.umb-nested-content--not-supported {
opacity: 0.3;
pointer-events: none;
}
.nested-content-overlay
{
.umb-nested-content-overlay {
position: absolute;
top: 0;
left: 0;
@@ -19,47 +16,39 @@
z-index: 1000;
}
.nested-content__item
{
.umb-nested-content__item {
position: relative;
text-align: left;
border-top: solid 1px transparent;
background: white;
background: @white;
}
.nested-content__item--active:not(.nested-content__item--single)
{
background: #f8f8f8;
.umb-nested-content__item--active:not(.umb-nested-content__item--single) {
background: @gray-10;
}
.nested-content__item.ui-sortable-placeholder
{
background: #f8f8f8;
border: 1px dashed #d9d9d9;
.umb-nested-content__item.ui-sortable-placeholder {
background: @gray-10;
border: 1px dashed @gray-8;
visibility: visible !important;
height: 55px;
margin-top: -1px;
}
.nested-content__item--single > .nested-content__content
{
.umb-nested-content__item--single > .umb-nested-content__content {
border: 0;
}
.nested-content__item--single > .nested-content__content > .umb-pane
{
.umb-nested-content__item--single > .umb-nested-content__content > .umb-pane {
margin: 0;
}
.nested-content__header-bar
{
.umb-nested-content__header-bar {
padding: 15px 20px;
border-bottom: 1px dashed #e0e0e0;
border-bottom: 1px dashed @gray-8;
text-align: right;
cursor: pointer;
background-color: white;
background-color: @white;
-moz-user-select: none;
-khtml-user-select: none;
@@ -67,24 +56,21 @@
-o-user-select: none;
}
.nested-content__heading {
.umb-nested-content__heading {
line-height: 20px;
position: relative;
&.-with-icon
{
&.-with-icon {
padding-left: 20px;
}
i
{
color: #999; /* same icon color as the icons in the item type picker */
i {
color: @gray-2;
position: absolute;
left: 0;
}
.nested-content__item-name
{
.umb-nested-content__item-name {
max-height: 20px;
text-align: left;
white-space: nowrap;
@@ -94,22 +80,16 @@
}
}
.nested-content__icons
{
.umb-nested-content__icons {
opacity: 0;
transition: opacity .15s ease-in-out;
-moz-transition: opacity .15s ease-in-out;
-webkit-transition: opacity .15s ease-in-out;
position: absolute;
right: 0px;
top: 2px;
background-color: white;
background-color: @white;
padding: 5px;
&:before
{
&:before {
content: ' ';
position: absolute;
display: block;
@@ -117,126 +97,129 @@
left: -30px;
top: 0;
bottom: 0;
background: -webkit-linear-gradient(90deg, rgba(255,255,255,0), white);
background: -moz-linear-gradient(90deg, rgba(255,255,255,0), white);
background: linear-gradient(90deg, rgba(255,255,255,0), white);
}
}
.nested-content__header-bar:hover .nested-content__icons,
.nested-content__item--active > .nested-content__header-bar .nested-content__icons
{
.umb-nested-content__header-bar:hover .umb-nested-content__icons,
.umb-nested-content__item--active > .umb-nested-content__header-bar .umb-nested-content__icons {
opacity: 1;
}
.nested-content__icon,
.nested-content__icon.nested-content__icon--disabled:hover
{
.umb-nested-content__icon,
.umb-nested-content__icon.umb-nested-content__icon--disabled:hover {
display: inline-block;
padding: 4px 6px;
margin: 2px;
cursor: pointer;
background: #fff;
border: 1px solid #b6b6b6;
background: @white;
border: 1px solid @gray-7;
border-radius: 200px;
text-decoration: none !important;
}
.nested-content__icon:hover,
.nested-content__icon--active
.umb-nested-content__icon:hover,
.umb-nested-content__icon--active
{
color: white;
background: #2e8aea;
border-color: #2e8aea;
color: @white;
background: @turquoise-d1;
border-color: @turquoise-d1;
text-decoration: none;
}
.nested-content__icon .icon,
.nested-content__icon.nested-content__icon--disabled:hover .icon
{
.umb-nested-content__icon .icon,
.umb-nested-content__icon.umb-nested-content__icon--disabled:hover .icon {
display: block;
font-size: 16px !important;
color: #5f5f5f;
color: @gray-3;
}
.nested-content__icon:hover .icon,
.nested-content__icon--active .icon
{
color: white;
.umb-nested-content__icon:hover .icon,
.umb-nested-content__icon--active .icon {
color: @white;
}
.nested-content__icon--disabled
{
.umb-nested-content__icon--disabled {
opacity: 0.3;
}
.nested-content__footer-bar
{
.umb-nested-content__footer-bar {
text-align: center;
padding-top: 20px;
}
.nested-content__content
{
border-bottom: 1px dashed #e0e0e0;
.umb-nested-content__content {
border-bottom: 1px dashed @gray-8;
}
.nested-content__content .umb-control-group {
.umb-nested-content__content .umb-control-group {
padding-bottom: 0;
}
.nested-content__item.ui-sortable-helper .nested-content__content
{
.umb-nested-content__item.ui-sortable-helper .umb-nested-content__content {
display: none !important;
}
.nested-content__help-text
{
.umb-nested-content__help-text {
display: inline-block;
padding: 10px 20px 10px 20px;
clear: both;
font-size: 14px;
color: #555;
background: #f8f8f8;
color: @gray-3;
background: @gray-10;
border-radius: 15px;
}
.nested-content__doctypepicker table input, .nested-content__doctypepicker table select {
.umb-nested-content__doctypepicker table input,
.umb-nested-content__doctypepicker table select {
width: 100%;
padding-right: 0;
}
.nested-content__doctypepicker table td.icon-navigation, .nested-content__doctypepicker i.nested-content__help-icon {
.umb-nested-content__doctypepicker table td.icon-navigation,
.umb-nested-content__doctypepicker i.umb-nested-content__help-icon {
vertical-align: middle;
color: #CCC;
color: @gray-7;
}
.nested-content__doctypepicker table td.icon-navigation:hover, .nested-content__doctypepicker i.nested-content__help-icon:hover {
color: #343434;
.umb-nested-content__doctypepicker table td.icon-navigation:hover,
.umb-nested-content__doctypepicker i.umb-nested-content__help-icon:hover {
color: @gray-2;
}
.nested-content__doctypepicker i.nested-content__help-icon {
.umb-nested-content__doctypepicker i.umb-nested-content__help-icon {
margin-left: 10px;
}
.form-horizontal .nested-content--narrow .controls-row
.form-horizontal .umb-nested-content--narrow .controls-row
{
margin-left: 40% !important;
}
.form-horizontal .nested-content--narrow .controls-row .umb-textstring,
.form-horizontal .nested-content--narrow .controls-row .umb-textarea
.form-horizontal .umb-nested-content--narrow .controls-row .umb-textstring,
.form-horizontal .umb-nested-content--narrow .controls-row .umb-textarea
{
width: 95%;
}
.form-horizontal .nested-content--narrow .controls-row .umb-dropdown {
.form-horizontal .umb-nested-content--narrow .controls-row .umb-dropdown {
width: 99%;
}
.usky-grid.nested-content__node-type-picker .cell-tools-menu {
.usky-grid.umb-nested-content__node-type-picker .cell-tools-menu {
position: relative;
transform: translate(-50%, -25%);
}
// this resolves the layout issue introduced in nested content in 7.12 with the addition of the input for link anchors
// the attribute selector ensures the change only applies to the linkpicker overlay
.form-horizontal .umb-nested-content--narrow [ng-controller*="Umbraco.Overlays.LinkPickerController"] .controls-row {
margin-left:0!important;
.umb-textarea, .umb-textstring {
width:100%;
}
}
@@ -157,6 +157,10 @@
/* TEMP */
.umb-minilistview {
.umb-table-row.not-allowed { opacity: 0.6; cursor: not-allowed; }
}
.umb-listview .table-striped tbody td {
position: relative
}
@@ -5,7 +5,7 @@
width: 100%;
height: 100%;
position: absolute;
z-index: 10000;
z-index: 65537;
top: 0;
left: 0;
margin: 0 !important;
@@ -40,11 +40,18 @@ angular.module("umbraco").controller("Umbraco.Dialogs.LinkPickerController",
// if a link exists, get the properties to build the anchor name list
contentResource.getById(id).then(function (resp) {
$scope.anchorValues = tinyMceService.getAnchorNames(JSON.stringify(resp.properties));
$scope.model.target.url = resp.urls[0];
$scope.target.url = resp.urls[0];
});
} else if ($scope.target.url.length) {
// a url but no id/udi indicates an external link - trim the url to remove the anchor/qs
$scope.target.url = $scope.model.url.substring(0, $scope.model.url.search(/(#|\?)/));
// 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 ?
var indexOfAnchor = $scope.target.url.search(/(#|\?)/);
if (indexOfAnchor > -1) {
// populate the anchor
$scope.target.anchor = $scope.target.url.substring(indexOfAnchor);
// then rewrite the model and populate the link
$scope.target.url = $scope.target.url.substring(0, indexOfAnchor);
}
}
}
@@ -81,7 +88,7 @@ angular.module("umbraco").controller("Umbraco.Dialogs.LinkPickerController",
} else {
contentResource.getById(args.node.id).then(function (resp) {
$scope.anchorValues = tinyMceService.getAnchorNames(JSON.stringify(resp.properties));
$scope.model.target.url = resp.urls[0];
$scope.target.url = resp.urls[0];
});
}
@@ -7,7 +7,7 @@
placeholder="@general_url"
class="umb-editor umb-textstring"
ng-model="target.url"
ng-disabled="target.id" />
ng-disabled="target.id || target.udi" />
</umb-control-group>
<umb-control-group label="@defaultdialogs_anchorLinkPicker" class="umb-property--push">
@@ -181,7 +181,7 @@
<form method="POST" name="requestPasswordResetForm" ng-submit="requestPasswordResetSubmit(email)">
<div class="control-group" ng-class="{error: requestPasswordResetForm.email.$invalid}">
<label><localize key="general_email">Email</localize></label>
<input type="email" ng-model="email" name="email" class="-full-width-input" localize="placeholder" placeholder="@placeholders_email" />
<input type="email" val-email ng-model="email" name="email" class="-full-width-input" localize="placeholder" placeholder="@placeholders_email" />
</div>
<div class="control-group" ng-show="requestPasswordResetForm.$invalid">
@@ -3,8 +3,6 @@ angular.module("umbraco").controller("Umbraco.Overlays.LinkPickerController",
function ($scope, eventsService, dialogService, entityResource, contentResource, mediaHelper, userService, localizationService, tinyMceService) {
var dialogOptions = $scope.model;
var anchorPattern = /<a id=\\"(.*?)\\">/gi;
var searchText = "Search...";
localizationService.localize("general_search").then(function (value) {
searchText = value + "...";
@@ -52,8 +50,15 @@ angular.module("umbraco").controller("Umbraco.Overlays.LinkPickerController",
$scope.model.target.url = resp.urls[0];
});
} 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
$scope.model.target.url = $scope.model.target.url.substring(0, $scope.model.target.url.search(/(#|\?)/));
// 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 ?
var indexOfAnchor = $scope.model.target.url.search(/(#|\?)/);
if (indexOfAnchor > -1) {
// populate the anchor
$scope.model.target.anchor = $scope.model.target.url.substring(indexOfAnchor);
// then rewrite the model and populate the link
$scope.model.target.url = $scope.model.target.url.substring(0, indexOfAnchor);
}
}
} else if (dialogOptions.anchors) {
$scope.anchorValues = dialogOptions.anchors;
@@ -6,7 +6,7 @@
placeholder="@general_url"
class="umb-editor umb-textstring"
ng-model="model.target.url"
ng-disabled="model.target.id" />
ng-disabled="model.target.id || model.target.udi" />
</umb-control-group>
<umb-control-group label="@defaultdialogs_anchorLinkPicker" class="umb-property--push">
@@ -250,7 +250,8 @@ angular.module("umbraco")
// make sure that last opened node is on the same path as start node
var nodePath = node.path.split(",");
if (nodePath.indexOf($scope.startNodeId.toString()) !== -1) {
// also make sure the node is not trashed
if (nodePath.indexOf($scope.startNodeId.toString()) !== -1 && node.trashed === false) {
$scope.gotoFolder({ id: $scope.lastOpenedNode, name: "Media", icon: "icon-folder" });
return true;
} else {
@@ -28,6 +28,7 @@
label-key="general_upload"
action="upload()"
disabled="lockedFolder"
button-style="info"
ng-if="acceptedMediatypes.length > 0">
</umb-button>
</div>
@@ -24,7 +24,16 @@ angular.module("umbraco").controller("Umbraco.Overlays.MemberGroupPickerControll
}
function selectMemberGroups(id) {
$scope.model.selectedMemberGroups.push(id);
var index = $scope.model.selectedMemberGroups.indexOf(id);
if(index === -1){
// If the id does not exists in the array then add it
$scope.model.selectedMemberGroups.push(id);
}
else{
// Otherwise we will remove it from the array instead
$scope.model.selectedMemberGroups.splice(index, 1);
}
}
/** Method used for selecting a node */
@@ -22,7 +22,7 @@
<umb-empty-state ng-if="!hasItems && emptyStateMessage" position="center">
{{ emptyStateMessage }}
</umb-empty-state>
</umb-empty-state>
<div ng-if="treeReady" ng-hide="searchInfo.showSearch" ng-animate="'tree-fade-out'">
<umb-tree
@@ -48,7 +48,8 @@
entity-type="{{entityType}}"
start-node-id="model.startNodeId"
on-select="selectListViewNode(node)"
on-close="closeMiniListView()">
on-close="closeMiniListView()"
entity-type-filter="filter">
</umb-mini-list-view>
</div>
</div>
@@ -1,4 +1,4 @@
<button ng-click="click()" class="umb-toggle dib" ng-class="{'umb-toggle--checked': checked}">
<button ng-click="click()" type="button" class="umb-toggle dib" ng-class="{'umb-toggle--checked': checked}">
<span ng-if="!labelPosition && showLabels === 'true' || labelPosition === 'left' && showLabels === 'true'">
<span ng-if="!checked" class="umb-toggle__label umb-toggle__label--left">{{ displayLabelOff }}</span>
@@ -178,15 +178,16 @@
<umb-control-group data-element="node-info-document-type" label="@content_documentType">
<umb-node-preview
style="max-width: 100%; margin-bottom: 0;"
icon="documentType.icon"
name="documentType.name"
icon="node.icon"
name="node.contentTypeName"
allow-open="allowOpen"
on-open="openDocumentType(documentType)"
open-url="previewOpenUrl">
open-url="previewOpenUrl">
</umb-node-preview>
</umb-control-group>
<umb-control-group ng-if="disableTemplates == false" data-element="node-info-template" label="@template_template">
<div class="flex items-center">
<select class="input-block-level"
ng-model="node.template"
@@ -194,7 +195,7 @@
ng-change="updateTemplate(node.template)">
<option value=""><localize key="general_choose">Choose</localize>...</option>
</select>
<a href="" class="umb-node-preview__action" style="margin-left:15px;" ng-click="openTemplate()" ng-if="node.template !== null">
<a href="" class="umb-node-preview__action" style="margin-left:15px;" ng-click="openTemplate()" ng-if="node.template !== null && allowOpen">
<localize key="general_open">Open</localize>
</a>
</div>
@@ -9,7 +9,7 @@
size="small">
<localize key="content_noMediaLink"></localize>
</umb-empty-state>
<ul ng-if="nodeUrl" class="nav nav-stacked" style="margin-bottom: 0;">
<li>
<a href="{{nodeUrl}}" target="_blank">
@@ -28,7 +28,7 @@
<umb-box data-element="node-info-general">
<umb-box-header title-key="general_general"></umb-box-header>
<umb-box-content class="block-form">
<umb-control-group data-element="node-info-create-date" label="@content_createDate">
{{node.createDateFormatted}} by {{ node.owner.name }}
</umb-control-group>
@@ -36,13 +36,13 @@
<umb-control-group data-element="node-info-update-date" label="@content_updateDate">
{{node.updateDateFormatted}}
</umb-control-group>
<umb-control-group data-element="node-info-media-type" label="@content_mediatype">
<umb-node-preview
style="max-width: 100%; margin-bottom: 0px;"
icon="mediaType.icon"
name="mediaType.name"
allow-open="allowOpenMediaType"
icon="node.icon"
name="node.contentTypeName"
allow-open="allowOpen"
on-open="openMediaType(mediaType)">
</umb-node-preview>
</umb-control-group>
@@ -52,8 +52,8 @@
<small>{{ node.key }}</small>
</umb-control-group>
</umb-box-content>
</umb-box-content>
</umb-box>
</div>
</div>
</div>
@@ -1,4 +1,4 @@
<div>
<div class="umb-minilistview">
<div ng-repeat="miniListView in miniListViews" ng-animate="getMiniListViewAnimation()">
@@ -61,7 +61,7 @@
<div class="umb-table-row"
ng-repeat="child in miniListView.children"
ng-click="selectNode(child)"
ng-class="{'-selected':child.selected}">
ng-class="{'-selected':child.selected, 'not-allowed':!child.allowed}">
<div class="umb-table-cell umb-table-cell--auto-width" ng-class="{'umb-table-cell--faded':child.published === false}">
<div class="flex items-center">
<ins class="icon-navigation-right umb-table__row-expand" ng-click="openNode($event, child)" ng-class="{'umb-table__row-expand--hidden': child.hasChildren !== true}">&nbsp;</ins>
@@ -13,7 +13,7 @@
</div>
</div>
<div class="umb-node-preview__actions">
<a class="umb-node-preview__action" title="Open" href="{{editUrl}}" ng-if="allowEdit" ng-click="onEdit()"><localize key="general_edit">Edit</localize></a>
<a class="umb-node-preview__action" title="Edit" href="{{editUrl}}" ng-if="allowEdit" ng-click="onEdit()"><localize key="general_edit">Edit</localize></a>
<a class="umb-node-preview__action" title="Open" href="{{openUrl}}" ng-if="allowOpen" ng-click="onOpen()"><localize key="general_open">Open</localize></a>
<a class="umb-node-preview__action umb-node-preview__action--red" title="Remove" href="{{removeUrl}}" ng-if="allowRemove" ng-click="onRemove()"><localize key="general_remove">Remove</localize></i></a>
</div>
@@ -37,6 +37,12 @@
</div>
</div>
<div ng-show="hideDropzone" ngf-drag-over-class="hide" class="text-center">
<small>
<localize key="media_dragFilesHereToUpload">You can drag files here to upload</localize>
</small>
</div>
<!-- List of uploading/uploaded files -->
<ul class="file-list" ng-show="done.length > 0 || queue.length > 0 || rejected.length > 0 || filesHolder.length > 0">
@@ -29,7 +29,7 @@
val-form-manager>
<umb-control-group label="Enter a folder name" hide-label="false">
<input type="text" name="folderName" ng-model="model.folderName" class="umb-textstring textstring input-block-level" required />
<input type="text" name="folderName" ng-model="model.folderName" class="umb-textstring textstring input-block-level" required autofocus />
</umb-control-group>
<button type="submit" class="btn btn-primary"><localize key="general_create">Create</localize></button>
@@ -27,6 +27,8 @@ function DocumentTypesCreateController($scope, $location, navigationService, con
$scope.showCreateDocTypeCollection = function () {
$scope.model.creatingDoctypeCollection = true;
$scope.model.collectionCreateTemplate = true;
$scope.model.collectionItemCreateTemplate = true;
};
$scope.createContainer = function () {
@@ -83,7 +85,7 @@ function DocumentTypesCreateController($scope, $location, navigationService, con
}
}
contentTypeResource.createCollection(node.id, $scope.model.collectionName, $scope.model.collectionItemName, collectionIcon, collectionItemIcon).then(function (collectionData) {
contentTypeResource.createCollection(node.id, $scope.model.collectionName, $scope.model.collectionCreateTemplate, $scope.model.collectionItemName, $scope.model.collectionItemCreateTemplate, collectionIcon, collectionItemIcon).then(function (collectionData) {
navigationService.hideMenu();
$location.search('create', null);
@@ -80,10 +80,14 @@
<umb-control-group label="Name of the Parent Document Type" hide-label="false">
<input type="text" name="collectionName" ng-model="model.collectionName" class="umb-textstring textstring input-block-level" umb-auto-focus required />
<umb-toggle on-click="model.collectionCreateTemplate = !model.collectionCreateTemplate" checked="model.collectionCreateTemplate"></umb-toggle>
<label>Create template for the Parent Document Type</label>
</umb-control-group>
<umb-control-group label="Name of the Item Document Type" hide-label="false">
<input type="text" name="collectionItemName" ng-model="model.collectionItemName" class="umb-textstring textstring input-block-level" required />
<umb-toggle on-click="model.collectionItemCreateTemplate = !model.collectionItemCreateTemplate" checked="model.collectionItemCreateTemplate"></umb-toggle>
<label>Create template for the Item Document Type</label>
</umb-control-group>
<button type="submit" class="btn btn-primary"><localize key="general_create">Create</localize></button>
@@ -8,6 +8,7 @@
</div>
<div class="sub-view-column-right">
<umb-toggle
data-element="permissions-allow-as-root"
checked="model.allowAsRoot"
on-click="vm.toggle()"
hotkey="alt+shift+r"
@@ -218,7 +218,7 @@ angular.module("umbraco")
// Fade in control when sorting stops
ui.item.context.style.opacity = "1";
ui.item.parents(".umb-cell-content").find(".mceNoEditor").each(function () {
ui.item.offsetParent().find(".mceNoEditor").each(function () {
if ($.inArray($(this).attr("id"), notIncludedRte) < 0) {
// add all dragged's neighbouring RTEs in the new cell
notIncludedRte.splice(0, 0, $(this).attr("id"));

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