Compare commits

...

101 Commits

Author SHA1 Message Date
Sebastiaan Janssen 95d5263405 Bumps version to 7.11.2 and updates CDF 2018-09-20 08:35:28 +02:00
Anders Bjerner ad99d164c9 U4-11477 Here we go again
https://github.com/umbraco/Umbraco-CMS/pull/2720#issuecomment-400106496
2018-06-25 23:58:25 +02:00
Anders Bjerner ae3205c429 Fixes U4-11426 for files as well
The original fix from #2679 only fixes the bug for images, as it checks whether the `umbracoWidth` and `umbracoHeight` properties are present. With this PR, the bug is now fixed for both images and regular files.
2018-06-25 12:08:42 +02:00
Joshua Pease 10c71a7381 Set a initial $scope.model.value for true/false 2018-06-25 08:24:22 +02:00
Sebastiaan Janssen 9875c37cf2 Bumps version to 7.11.1 2018-06-21 10:48:25 +02:00
Sebastiaan Janssen 67e36a0d60 U4-11456 Package installation - Load usercontrol: file cannot be found: /umbraco/developer/Packages/installer.aspx 2018-06-21 10:38:04 +02:00
Sebastiaan Janssen bcca0528c0 U4-11462 Error when using Simple Injector - 'The Tree controller is missing the Umbraco.Web.Trees.TreeAttribute attribute' 2018-06-21 08:19:53 +02:00
Shannon Deminick 4f04692afa Merge pull request #2707 from umbraco/temp-U4-11341
U4-11341 Content node tree collapse on random nodes level 3 or lower …
2018-06-20 18:25:22 +10:00
Sebastiaan Janssen 9909b10edb Removes more unnecessary code from the tree syncing if we don't need to consider the start nodes 2018-06-20 09:26:09 +02:00
Sebastiaan Janssen 4e6c4d6f7f U4-11341 Content node tree collapse on random nodes level 3 or lower after upgrade to 7.10.4 2018-06-19 16:08:11 +02:00
Sebastiaan Janssen 6cbc3367b1 Merge branch 'dev-v7' of https://github.com/umbraco/Umbraco-CMS into dev-v7 2018-06-18 12:05:28 +02:00
Sebastiaan Janssen c961ffcef2 Merge pull request #2704 from andyneil/dev-v7
U4-11321 - Removed redundant autocomplete attribute
2018-06-18 10:00:59 +02:00
Sebastiaan Janssen f034fbccf9 Merge pull request #2701 from abryukhov/temp-U4-11430
U4-11430 - adds new UI localization keys (ru-RU) for v7.11
2018-06-18 09:58:03 +02:00
Andy Neil 65d9b3b99d U4-11321 - Remove unused "autocomplete" attribute 2018-06-17 16:03:02 +01:00
Alexander Bryukhov 77f0b4e093 U4-11430 - couple of typos 2018-06-16 16:25:16 +07:00
Alexander Bryukhov 59e291f961 U4-11430 - slightly better health check keys translation 2018-06-16 16:23:11 +07:00
Alexander Bryukhov 50e4825066 U4-11430 - adds new UI localization keys (ru-RU) for v7.11 2018-06-16 15:59:57 +07:00
Sebastiaan Janssen 4235963fce Fix configuration errors 2018-06-14 15:32:38 +02:00
Sebastiaan Janssen 7d2bbb64b1 Fix configuration errors 2018-06-14 15:22:22 +02:00
Sebastiaan Janssen 07ccdfb7af Removes hacky way to get the section name and replaces it with the normal way to get it 2018-06-14 12:01:29 +02:00
Sebastiaan Janssen 2022ca6d64 Merge pull request #2694 from dampee/feature/U4-11438
U4-11438 Add issuu.com oembed functionality
2018-06-14 10:29:19 +02:00
Shannon Deminick 7372fa1705 Merge pull request #2627 from efabioli/patch-1
U4-11329 - GetExternalAuthenticationOptions gets called when AuthType is Null in Umbraco.Web/editors/BackOfficeController.cs
2018-06-14 14:31:27 +10:00
Damiaan 9ec1d20d51 U4-11438 Add issuu.com oembed functionality + fixed typo's in EmbeddedMedia.config file 2018-06-13 22:20:11 +02:00
Ed Parry 0e4bcc96e7 U4-9367 Refined context menu for content in the recycle bin (#2687) 2018-06-13 21:38:03 +02:00
Sebastiaan Janssen 82c7bc45a7 Merge pull request #2640 from lars-erik/U4-7874
U4-7874 - Add events to content editor
2018-06-13 21:30:10 +02:00
Sebastiaan Janssen 10484a2240 Fix unit tests after moving the Dictionary tree 2018-06-13 21:16:44 +02:00
Enkel Media 8d41d106d0 Fixes #U4-11406 by setting the thread culture before rendering macro (#2666) 2018-06-13 21:06:58 +02:00
Sebastiaan Janssen 8e18778bc2 Merge pull request #2675 from bjarnef/dev-v7-U4-11301
Add id and guid on datatype pages
2018-06-13 21:04:19 +02:00
Sebastiaan Janssen 8068641120 Merge pull request #2679 from stephen47/temp-U4-11426
U4-11426 - Fixed bug with media picker not populating URL in RTE link editor when search is used.
2018-06-13 20:58:18 +02:00
Sebastiaan Janssen 388f9e3a1e Merge pull request #2685 from abryukhov/temp-U4-11430
U4-11430 - Backoffice UI localization update (ru-RU)
2018-06-13 20:48:55 +02:00
Adam Prendergast 51b77669cb U4-11437: Added 'Document Type Alias' title to appear on mouse hover … (#2692) 2018-06-13 20:46:45 +02:00
Garrit Petersen f04335ef7d cursor remians default when no alias is given to the umb-control-grou… (#2497) 2018-06-13 20:42:21 +02:00
Sebastiaan Janssen aca0249c0f NuGet install now creates the correct tree controller 2018-06-13 20:29:55 +02:00
Sebastiaan Janssen d66e951b68 Updating code style, removes obsolete files, now we can move the tree to the Translation section 2018-06-13 20:20:21 +02:00
Dave Woestenborghs 9c33f1b1c9 U4-5683 Migrate Dictionary tree & editor to angular (#2159) 2018-06-13 20:19:18 +02:00
Daniël Knippers 3520f2d1e4 Fix NullReferenceException when HttpContext is null
This method will throw a NullReferenceException in contexts without an HttpContext, like is the case in background threads. As HttpContext is only used to set an isDebug flag, it seems more sensible to not throw in cases without an HttpContext, but simply set isDebug to false instead. If this is not acceptable behavior, could we perhaps look at something other than HttpContext.Current.IsDebuggingEnabled to decide whether isDebug should be set?
2018-06-13 13:25:10 +02:00
Claus 2715d49630 Merge pull request #2498 from hemraker/temp-U4-10899
Fixes U4-10899: Template circular dependency
2018-06-12 13:04:23 +02:00
Alexander Bryukhov 78fe1015aa U4-11430 - Backoffice UI localization update (ru-RU) 2018-06-11 17:16:49 +07:00
Stephen Holder d43d432d2f U4-11426 - Fixed bug with media picker not populating URL in RTE link editor when search is used. 2018-06-08 20:35:20 +01:00
Bjarne Fyrstenborg 06ee6e3845 Add id and guid on datatype pages 2018-06-06 23:23:15 +02:00
Marc Goodson 0eceb3c7fc U4-11369 - Add list of content types where a composition content type is used to compositions dialog (#2668) 2018-06-06 22:35:10 +02:00
Chris Houston 5013c5f526 Fixes issue: U4-11416 - Better formatting for the video tiles in the developer section. (#2673) 2018-06-06 20:17:56 +02:00
Sebastiaan Janssen d07bd58deb Merge pull request #2672 from WojciechKmiecik/temp-U4-10936
fix for U4-10936 "Failed to read the 'rules' property from 'CSSStyleSheet'" when certain chrome extensions are enabled
2018-06-06 10:01:01 +02:00
Sebastiaan Janssen d8ba0d352e Merge pull request #2633 from maarten-kieft/dev-v7
Make base AnchestorOrSelf public
2018-06-06 09:58:55 +02:00
Wojciech Kmiecik faf9800235 fix U4-10936 when ceratin chrome extensions are enabled 2018-06-05 17:17:14 +02:00
Sebastiaan Janssen e789cb8875 Merge pull request #2671 from Mundairson/dev-v7-U4-8199
Refactor the extension method IsNullOrWhiteSpace() to use the native version
2018-06-05 14:30:18 +02:00
Sebastiaan Janssen f208fc65d0 Merge pull request #2639 from lars-erik/U4-11356
U4-11356 Events emitted from the grid on init, row added and item added
2018-06-05 14:18:14 +02:00
Mundairson e7c1d3dd2e Removed old version. 2018-06-05 12:25:37 +01:00
Mundairson 379ac8a3cb Refactored the extension method to call the native method. 2018-06-05 12:25:06 +01:00
Sebastiaan Janssen 8202dbcc5b Merge pull request #2644 from ssougnez/temp-U4-10956
Created an innerState variable in the isolated scope of "umb-button" …
2018-06-05 12:57:44 +02:00
Sebastiaan Janssen 8172789537 Merge pull request #2669 from dawoe/temp-U4-11412
U4-11412 only show buttons in umb-confirm when callback is defined
2018-06-05 12:39:17 +02:00
Sebastiaan Janssen 08dd74322a Merge pull request #2667 from BatJan/dev-v7
Use the umb-toggle directive for the "True/False" property editor
2018-06-05 12:37:08 +02:00
Mundairson 8953021784 Corrected the VersionCheckPeriod property's XML comment. 2018-06-05 10:58:45 +01:00
Sebastiaan Janssen da4e519e4b Merge pull request #2658 from PeteDuncanson/temp-U4-11395
U4-11395 - Add Gulp ImageMin to compress images in build process
2018-06-04 14:16:48 +02:00
Sebastiaan Janssen 42a6872685 Move image to the new location 2018-06-04 13:51:12 +02:00
Sebastiaan Janssen a8cf6e8426 Merge pull request #2651 from umbraco/temp-ic-2
Restructures contribution guidelines into multiple files to make them…
2018-06-04 13:43:06 +02:00
Dave Woestenborghs fe2ff696c5 U4-11412 documented umbConfirm directive 2018-06-04 09:06:25 +02:00
Sebastiaan Janssen 240c205765 Merge pull request #2649 from AndyFelton/temp-U4-11039
Conditional Upload button on Media Picker
2018-06-04 08:58:35 +02:00
Dave Woestenborghs 03019e9676 U4-11412 only show cancel and confirm button when a handler is attached 2018-06-04 08:52:48 +02:00
Dave Woestenborghs 697cc7a420 U4-11412 hide cancel button in umb-confirm when handler is not defined 2018-06-04 08:45:09 +02:00
Sebastiaan Janssen 8961f930e3 Merge pull request #2646 from AndersBrohus/U4-11367
U4-11367 - Show trashbin icon again
2018-06-04 08:03:30 +02:00
Sebastiaan Janssen 2d3ef8d311 Merge pull request #2642 from Mundairson/dev-v7-getting-started-text-fixes
Corrected spelling and grammar in the Getting Started tool tips for v7.
2018-06-04 07:58:36 +02:00
Shannon Deminick 02afb1e774 Merge pull request #2665 from umbraco/temp-U4-11338
fixes U4-11338 Language dropdown fails when invalid cultures are present
2018-06-04 14:07:01 +10:00
Jan Skovgaard 6188629da6 Convert the default boring checkbox to the shiny new and beautiful toggle based on the umb-toggle directive 2018-06-01 22:03:10 +02:00
Sebastiaan Janssen 2c04a02d62 Merge pull request #2662 from readingdancer/U4-11400
Updated references to mention May for CodeGarden in the installer
2018-06-01 15:09:07 +02:00
Claus ccc8868f68 fixes U4-11338 Language dropdown fails when invalid cultures are present 2018-06-01 13:06:13 +02:00
Chris Houston cde7f0fa18 Updated references to CodeGarden in the installer and the umbraco.config test file to mention May instead of June :) 2018-05-31 14:50:01 -04:00
Sebastiaan Janssen 867ccaf2b1 Small corrections 2018-05-31 15:26:12 +02:00
Peter Duncanson 3743fc1c29 Added Gulp Images to compress images as part of the front end build process 2018-05-31 13:37:24 +01:00
Sebastiaan Janssen d10aec9e68 Merge branch 'dev-v7' into temp-ic-2
# Conflicts:
#	docs/CONTRIBUTING_DETAILED.md
#	docs/README.md
2018-05-30 11:18:15 +02:00
Mundairson fefe5660ef Added merged files from dev-v7 2018-05-30 10:07:05 +01:00
Sebastiaan Janssen 5d978a62fd Small corrections 2018-05-30 10:19:21 +02:00
Shannon Deminick 49062d3ede Merge pull request #2625 from poornimanayar/U4-11159
Fixed typos in tours
2018-05-30 08:10:25 +02:00
Sebastiaan Janssen 7853245fe4 Small corrections 2018-05-29 17:33:06 +02:00
Sebastiaan Janssen fa88efbf5e Small corrections 2018-05-29 17:24:14 +02:00
Sebastiaan Janssen 6f6252b616 Restructures contribution guidelines into multiple files to make them easier to digest for new
contributors
ref: https://github.com/umbraco/issues-community/issues/2
2018-05-29 17:18:25 +02:00
Andy Felton 7947970817 Conditional Upload button on Media Picker
Made upload button only appear when media can be uploaded to the current folder. Also ensured acceptedMediatypes is always valid even in the root directory
2018-05-28 15:39:15 +01:00
Anders Brohus 76717eb720 Show trashbin icon again
After looking i found out that the problem was that the "position:relative;" was removed on the umb-group-builder__group class.
2018-05-25 19:53:06 +02:00
Seb cd0c9a39f3 Created an innerState variable in the isolated scope of "umb-button" directive in order to ensure not to create a "state" property in the directive isolated scope. 2018-05-23 18:01:17 +02:00
Sebastiaan Janssen 96ce2882a2 Merge pull request #2643 from abjerner/patch-38
Health Checks: the warning icon should be orange instead of yellow
2018-05-22 11:00:11 +02:00
Anders Bjerner 068ad19492 Health Checks: the warning icon should be orange instead of yellow
Both the yellow and orange colors used to be a bit darker, but when more colors were introduced in 7.10.x, the two colors were made a bit lighter. So now the yellow warning icon is hard to see on a white background, but the orange color now looks just right ;)
2018-05-22 10:44:43 +02:00
Mundairson 6fb4f8fc8b Corrected some spelling and grammar. 2018-05-22 01:10:41 +01:00
Lars-Erik Aabech e7fce9120e Added several events to content editor 2018-05-21 18:04:50 +02:00
Lars-Erik Aabech 76c924fbaa Events emitted from the grid on init, row added and item added w/DOM element and scope. 2018-05-21 17:06:12 +02:00
Sebastiaan Janssen 93b470f15c Merge pull request #2638 from rozzilla/patch-2
Update README img
2018-05-21 10:25:31 +02:00
Roberto Bianchi 1cef87ee34 Update README img 2018-05-21 10:20:44 +02:00
Maarten Kieft 8e7630cd9c Make Base AnchestorOrSelf function public
By making this function public, developers can use it to iterate over the tree on different property / function than the ones which are created. It makes umbraco easier to extend. Now we have to copy existing code in order to do this.
2018-05-17 12:09:15 +02:00
Shannon Deminick 8985d514ec cross link to v8 branch 2018-05-16 13:36:57 +02:00
Shannon Deminick 3c82315782 cross link to the v8 branch 2018-05-16 12:56:00 +02:00
Sebastiaan Janssen 58751577c6 Merge pull request #2622 from DanDiplo/temp-U4-11313
u4 11313 - ContainsAny() method in StringExtensions doesn't honour the StringComparison parameter
2018-05-15 13:07:21 +02:00
Sebastiaan Janssen debe0d811c Merge pull request #2628 from ragivi/patch-1
Update preview page
2018-05-15 13:00:57 +02:00
Sebastiaan Janssen 8d09243473 Merge pull request #2626 from DanDiplo/temp-U4-10706
U4-10706 - Fixes TypedMedia not working with UDI strings
2018-05-15 12:44:46 +02:00
ragivi 2b4cf7d185 Update preview page
In order to avoid indexing.
2018-05-14 14:48:01 +02:00
efabioli 9040b1a3cb NullReferenceException
Retrieving ExternalSignInAutoLinkOptions only if authType is not null.  
Issue found in version 7.9 too; not checked other versions.
2018-05-11 16:27:43 +02:00
Dan Booth 9a8f71dd81 Fixed issue where TypedMedia didn't work with UDI strings 2018-05-11 14:53:03 +01:00
Poornima Nayar d05819e125 Fixed typos in tours 2018-05-11 12:23:51 +01:00
Dan Booth 9c65ed92f1 Added string ContainsAny tests for the ContainsAny(haystack, needles, comparison) extension method 2018-05-10 14:29:00 +01:00
Dan Booth 3f35eca999 Fixed ContainsAny method so that it uses the passed in Comparison method (which enabled case-insensitive comparisons to work) 2018-05-10 14:28:16 +01:00
andyneil 4a86244924 Merge pull request #1 from umbraco/dev-v7
Latest master
2018-05-08 18:28:54 +01:00
Sebastiaan Janssen 324cd7e98f Adds a quick start to setup a gulp environment - when you have NPM in the path the pre-requisites get taken care of 2018-05-04 10:33:35 +02:00
Rune Hem Strand 20216df8cf Add check to avoid cicular template reference 2018-03-02 17:49:02 +01:00
126 changed files with 2904 additions and 965 deletions
-80
View File
@@ -1,80 +0,0 @@
# Code of Conduct
## 1. Purpose
A primary goal of Umbraco CMS is to be inclusive to the largest number of contributors, with the most varied and diverse backgrounds possible. As such, we are committed to providing a friendly, safe and welcoming environment for all, regardless of gender, sexual orientation, ability, ethnicity, socioeconomic status, and religion (or lack thereof).
This code of conduct outlines our expectations for all those who participate in our community, as well as the consequences for unacceptable behavior.
We invite all those who participate in Umbraco CMS to help us create safe and positive experiences for everyone.
## 2. Open Source Citizenship
A supplemental goal of this Code of Conduct is to increase open source citizenship by encouraging participants to recognize and strengthen the relationships between our actions and their effects on our community.
Communities mirror the societies in which they exist and positive action is essential to counteract the many forms of inequality and abuses of power that exist in society.
If you see someone who is making an extra effort to ensure our community is welcoming, friendly, and encourages all participants to contribute to the fullest extent, we want to know.
## 3. Expected Behavior
The following behaviors are expected and requested of all community members:
* Participate in an authentic and active way. In doing so, you contribute to the health and longevity of this community.
* Exercise consideration and respect in your speech and actions.
* Attempt collaboration before conflict.
* Refrain from demeaning, discriminatory, or harassing behavior and speech.
* Be mindful of your surroundings and of your fellow participants. Alert community leaders if you notice a dangerous situation, someone in distress, or violations of this Code of Conduct, even if they seem inconsequential.
* Remember that community event venues may be shared with members of the public; please be respectful to all patrons of these locations.
## 4. Unacceptable Behavior
The following behaviors are considered harassment and are unacceptable within our community:
* Violence, threats of violence or violent language directed against another person.
* Sexist, racist, homophobic, transphobic, ableist or otherwise discriminatory jokes and language.
* Posting or displaying sexually explicit or violent material.
* Posting or threatening to post other peoples personally identifying information ("doxing").
* Personal insults, particularly those related to gender, sexual orientation, race, religion, or disability.
* Inappropriate photography or recording.
* Inappropriate physical contact. You should have someones consent before touching them.
* Unwelcome sexual attention. This includes, sexualized comments or jokes; inappropriate touching, groping, and unwelcomed sexual advances.
* Deliberate intimidation, stalking or following (online or in person).
* Advocating for, or encouraging, any of the above behavior.
* Sustained disruption of community events, including talks and presentations.
## 5. Consequences of Unacceptable Behavior
Unacceptable behavior from any community member, including sponsors and those with decision-making authority, will not be tolerated.
Anyone asked to stop unacceptable behavior is expected to comply immediately.
If a community member engages in unacceptable behavior, the community organizers may take any action they deem appropriate, up to and including a temporary ban or permanent expulsion from the community without warning (and without refund in the case of a paid event).
## 6. Reporting Guidelines
If you are subject to or witness unacceptable behavior, or have any other concerns, please notify a community organizer as soon as possible. Please contact Sebastiaan Janssen - [sj@umbraco.dk](mailto:sj@umbraco.dk).
Additionally, community organizers are available to help community members engage with local law enforcement or to otherwise help those experiencing unacceptable behavior feel safe. In the context of in-person events, organizers will also provide escorts as desired by the person experiencing distress.
## 7. Addressing Grievances
If you feel you have been falsely or unfairly accused of violating this Code of Conduct, you should notify Umbraco with a concise description of your grievance. Your grievance will be handled in accordance with our existing governing policies.
## 8. Scope
We expect all community participants (contributors, paid or otherwise; sponsors; and other guests) to abide by this Code of Conduct in all community venuesonline and in-personas well as in all one-on-one communications pertaining to community business.
This code of conduct and its related procedures also applies to unacceptable behavior occurring outside the scope of community activities when such behavior has the potential to adversely affect the safety and well-being of community members.
## 9. Contact info
Sebastiaan Janssen - [sj@umbraco.dk](mailto:sj@umbraco.dk)
## 10. License and attribution
This Code of Conduct is distributed under a [Creative Commons Attribution-ShareAlike license](http://creativecommons.org/licenses/by-sa/3.0/).
Portions of text derived from the [Django Code of Conduct](https://www.djangoproject.com/conduct/) and the [Geek Feminism Anti-Harassment Policy](http://geekfeminism.wikia.com/wiki/Conference_anti-harassment/Policy).
Retrieved on November 22, 2016 from [http://citizencodeofconduct.org/](http://citizencodeofconduct.org/)
+1 -1
View File
@@ -28,7 +28,7 @@
<dependency id="HtmlAgilityPack" version="[1.4.9.5, 2.0.0)" />
<dependency id="Lucene.Net" version="[2.9.4.1, 3.0.0.0)" />
<dependency id="MySql.Data" version="[6.9.9, 7.0.0)" />
<dependency id="ClientDependency" version="[1.9.6, 2.0.0)" />
<dependency id="ClientDependency" version="[1.9.7, 2.0.0)" />
<dependency id="ClientDependency-Mvc5" version="[1.8.0.0, 2.0.0)" />
<dependency id="AutoMapper" version="[3.3.1, 4.0.0)" />
<dependency id="Newtonsoft.Json" version="[10.0.2, 11.0.0)" />
+1 -1
View File
@@ -46,7 +46,7 @@
<add application="settings" alias="scripts" title="Scripts" type="Umbraco.Web.Trees.ScriptTreeController, umbraco" iconClosed="icon-folder" iconOpen="icon-folder" sortOrder="4"
xdt:Locator="Match(application,alias)"
xdt:Transform="SetAttributes()" />
<add application="settings" alias="dictionary" title="Dictionary" type="umbraco.loadDictionary, umbraco" iconClosed="icon-folder" iconOpen="icon-folder" sortOrder="6"
<add application="settings" alias="dictionary" title="Dictionary" type="Umbraco.Web.Trees.DictionaryTreeController, umbraco" iconClosed="icon-folder" iconOpen="icon-folder" sortOrder="6"
xdt:Locator="Match(application,alias)"
xdt:Transform="SetAttributes()" />
<add alias="dictionary" application="settings"
View File
+32
View File
@@ -0,0 +1,32 @@
# Code Of Conduct
Our informal code of conduct concentrates on the values we, as Umbraco HQ, have set for ourselves and for our community. We expect you to be a friend.
Instead of listing out all the exact "do's" and "don't's" we want to challenge you to think about our values and apply them:
If there's a need to talk to Umbraco HQ about anything, please make sure to send a mail to [Sebastiaan Janssen - sj@umbraco.dk](mailto:sj@umbraco.dk).
## Be a Friend
We welcome and thank you for registering at Our Umbraco. Find below the values that govern Umbraco and which you accept by using Our Umbraco.
## Trust
Assume positive intent and try to understand before being understood.
## Respect
Treat others as you would like to be treated.
This also goes for treating the HQ with respect. For example: dont promote products on [our.umbraco.org](https://our.umbraco.org) that directly compete with our commercial offerings which enables us to work for a sustainable Umbraco.
## Open
Be honest and straightforward. Tell it as it is. Share thoughts and knowledge and engage in collaboration.
## Hungry
Don't rest on your laurels and never accept the status quo. Contribute and give back to fellow Umbracians.
## Friendly
Dont judge upon mistakes made but rather upon the speed and quality with which mistakes are corrected. Friendly posts and contributions generate smiles and builds long lasting relationships.
+99
View File
@@ -0,0 +1,99 @@
_Looking for Umbraco version 8? [Click here](https://github.com/umbraco/Umbraco-CMS/blob/temp8/CONTRIBUTING.md) to go to the v8 branch_
# Contributing to Umbraco CMS
👍🎉 First off, thanks for taking the time to contribute! 🎉👍
The following is a set of guidelines for contributing to Umbraco CMS.
These are mostly guidelines, not rules. Use your best judgment, and feel free to propose changes to this document in a pull request.
Remember, we're a friendly bunch and are happy with whatever contribution you might provide. Below are guidelines for success that we've gathered over the years. If you choose to ignore them then we still love you 💖.
## Contributing code changes
This document gives you a quick overview on how to get started, we will link to in-depth documentation throughout if you need some more background info.
## Guidelines for contributions we welcome
Not all changes are wanted so on occassion we might close a PR without merging it. We will give you feedback why we can't accept your changes and we'll be nice about it, thanking you for spending your valueable time.
We have [documented what we consider small and large changes](CONTRIBUTION_GUIDELINES.md), make sure to talk to us before making large changes.
Remember, if an issue is in the `Up for grabs` list or you've asked for some feedback before you sent us a PR, your PR will not be closed as unwanted.
## How do I begin?
Great question! The short version goes like this:
* **Fork** - create a fork of [`Umbraco-CMS` on GitHub](https://github.com/umbraco/Umbraco-CMS)
![Fork the repository](img/forkrepository.png)
* **Clone** - when GitHub has created your fork, you can clone it in your favorite Git tool
![Clone the fork](img/clonefork.png)
* **Build** - build your fork of Umbraco locally as described in [building Umbraco from source code](BUILD.md)
* **Change** - make your changes, experiment, have fun, explore and learn, and don't be afraid. We welcome all contributions and will [happily give feedback](#questions)
* **Commit** - done? Yay! 🎉 It is recommended to create a new branch now and name it after the issue you're fixing, we usually follow the format: `temp-U4-12345`. This means it's a temporary branch for the particular issue you're working on, in this case `U4-12345`
* **Push** - great, now you can push the changes up to your fork on GitHub
* **Create pull request** - exciting! You're ready to show us your changes (or not quite ready, you just need some feedback to progress). GitHub has picked up on the new branch you've pushed and will offer to create a Pull Request. Click that green button and away you go.
![Create a pull request](img/createpullrequest.png)
### Further reading
At this point you might want to [read on about contributing in depth](CONTRIBUTING_DETAILED.md).
### Reviews
You've sent us your first contribution, congratulations! Now what?
The [pull request team](#the-pr-team) can now start reviewing your proposed changes and give you feedback on them. If it's not perfect, we'll either fix up what we need or we can request you to make some additional changes.
We have [a process in place which you can read all about](REVIEW_PROCESS.md). The very abbreviated version is:
- Your PR will get a reply within 48 hours
- An in-depth reply will be added within at most 2 weeks
- The PR will be either merged or rejected within at most 4 weeks
- Sometimes it is difficult to meet these timelines and we'll talk to you
## Styleguides
To be honest, we don't like rules very much. We trust you have the best of intentions and we encourage you to create working code. If it doesn't look perfect then we'll happily help clean it up.
That said, the Umbraco development team likes to follow the hints that ReSharper gives us (no problem if you don't have this installed) and we've added a `.editorconfig` file so that Visual Studio knows what to do with whitespace, line endings, etc.
## The PR team
The pull request team consists of a member of Umbraco HQ, [Sebastiaan](https://github.com/nul800sebastiaan), who gets assistance from the following community members
- [Anders Bjerner](https://github.com/abjerner)
- [Dave Woestenborghs](https://github.com/dawoe)
- [Emma Burstow](https://github.com/emmaburstow)
- [Kyle Weems](https://github.com/cssquirrel)
- [Poornima Nayar](https://github.com/poornimanayar)
These wonderful volunteers will provide you with a first reply to your PR, review and test out your changes and might ask more questions. After that they'll let Umbraco HQ know if everything seems okay.
## Questions?
You can get in touch with [the PR team](#the-pr-team) in multiple ways, we love open conversations and we are a friendly bunch. No question you have is stupid. Any questions you have usually helps out multiple people with the same question. Ask away:
- If there's an existing issue on the issue tracker then that's a good place to leave questions and discuss how to start or move forward
- Unsure where to start? Did something not work as expected? Try leaving a note in the ["Contributing to Umbraco"](https://our.umbraco.org/forum/contributing-to-umbraco-cms/) forum, the team monitors that one closely
- We're also [active in the Gitter chatroom](https://gitter.im/umbraco/Umbraco-CMS)
## Code of Conduct
This project and everyone participating in it is governed by the [our Code of Conduct](CODE_OF_CONDUCT.md). By participating, you are expected to uphold this code. Please report unacceptable behavior to [Sebastiaan Janssen - sj@umbraco.dk](mailto:sj@umbraco.dk).
## Contributing to Umbraco, in depth
There are other ways to contribute, and there's a few more things that you might be wondering about. We will answer the [most common questions and ways to contribute in our detailed documentation](CONTRIBUTING_DETAILED.md).
## Credits
This contribution guide borrows heavily from the excellent work on [the Atom contribution guide](https://github.com/atom/atom/blob/master/CONTRIBUTING.md). A big [#h5yr](http://h5yr.com/) to them!
@@ -1,17 +1,11 @@
# Contributing to Umbraco CMS
# Contributing in detail
👍🎉 First off, thanks for taking the time to contribute! 🎉👍
There's more than one way to contribute to Umbraco, there's some more suggestions below.
The following is a set of guidelines for contributing to Umbraco CMS.
These are mostly guidelines, not rules. Use your best judgment, and feel free to propose changes to this document in a pull request.
Remember, we're a friendly bunch and are happy with whatever contribution you might provide. Below are guidelines for success that we've gathered over the years. If you choose to ignore them then we still love you 💖.
When contributing code to Umbraco there's plenty of things you'll want to know, skip down to [What should I know before I get started](#what-should-i-know-before-i-get-started) for the answers to your burning questions.
#### Table Of Contents
[Code of Conduct](#code-of-conduct)
[How Can I Contribute?](#how-can-i-contribute)
* [Reporting Bugs](#reporting-bugs)
* [Suggesting Enhancements](#suggesting-enhancements)
@@ -26,16 +20,6 @@ Remember, we're a friendly bunch and are happy with whatever contribution you mi
* [Building Umbraco from source code](#building-umbraco-from-source-code)
* [Keeping your Umbraco fork in sync with the main repository](#keeping-your-umbraco-fork-in-sync-with-the-main-repository)
[How do I even begin?](#how-do-i-even-begin)
[Problems?](#problems)
[Credits](#credits)
## Code of Conduct
This project and everyone participating in it is governed by the [our Code of Conduct](CODE_OF_CONDUCT.md). By participating, you are expected to uphold this code. Please report unacceptable behavior to [Sebastiaan Janssen - sj@umbraco.dk](mailto:sj@umbraco.dk).
## How Can I Contribute?
### Reporting Bugs
@@ -52,7 +36,7 @@ Before creating bug reports, please check [this list](#before-submitting-a-bug-r
* **Use the Google**. Whatever you're experiencing, Google it plus "Umbraco" - usually you can get some pretty good hints from the search results, including open issues and further troubleshooting hints.
* If you do find and existing issue has **and the issue is still open**, add a comment to the existing issue if you have additional information. If you have the same problem and no new info to add, just "star" the issue.
Explain the problem and include additional details to help maintainers reproduce the problem. The following is a long description which we've boiled down into a few very simple question in the issue tracker when you create a new issue. We're listing the following hints to indicate that the most successful reports usually have a lot of this ground covered:
Explain the problem and include additional details to help maintainers reproduce the problem. The following is a long description which we've boiled down into a few very simple questions in the issue tracker when you create a new issue. We're listing the following hints to indicate that the most successful reports usually have a lot of this ground covered:
* **Use a clear and descriptive title** for the issue to identify the problem.
* **Describe the exact steps which reproduce the problem** in as many details as possible. For example, start by explaining which steps you took in the backoffice to get to a certain undesireable result, e.g. you created a document type, inherting 3 levels deep, added a certain datatype, tried to save it and you got an error.
@@ -74,7 +58,7 @@ Include details about your configuration and environment:
### Suggesting Enhancements
This section guides you through submitting an enhancement suggestion for Atom, including completely new features and minor improvements to existing functionality. Following these guidelines helps maintainers and the community understand your suggestion 📝 and find related suggestions 🔎.
This section guides you through submitting an enhancement suggestion for Umbraco, including completely new features and minor improvements to existing functionality. Following these guidelines helps maintainers and the community understand your suggestion 📝 and find related suggestions 🔎.
Most of the suggestions in the [reporting bugs](#reporting-bugs) section also count for suggesting enhancements.
@@ -100,6 +84,10 @@ The most successful pull requests usually look a like this:
Again, these are guidelines, not strict requirements.
## Making changes after the PR was opened
If you make the corrections we ask for in the same branch and push them to your fork again, the pull request automatically updates with the additional commit(s) so we can review it again. If all is well, we'll merge the code and your commits are forever part of Umbraco!
## Styleguides
To be honest, we don't like rules very much. We trust you have the best of intentions and we encourage you to create working code. If it doesn't look perfect then we'll happily help clean it up.
@@ -135,7 +123,7 @@ To find the general areas of something you're looking to fix or improve, have a
We like to use [Gitflow as much as possible](https://jeffkreeftmeijer.com/git-flow/), don't worry if you are not familiar with it. The most important thing you need to know is that when you fork the Umbraco repository, the default branch is set to something, usually `dev-v7`. Whatever the default is, that's where we'd like you to target your contributions.
![What branch do you want me to target?](tools/contributing/defaultbranch.png)
![What branch do you want me to target?](img/defaultbranch.png)
### Building Umbraco from source code
@@ -143,7 +131,7 @@ The easiest way to get started is to run `build.bat` which will build both the b
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.
![Gulp build in Visual Studio](tools/contributing/gulpbuild.png)
![Gulp build in Visual Studio](img/gulpbuild.png)
After this build completes, you should be able to hit `F5` in Visual Studio to build and run the project. A IISExpress webserver will start and the Umbraco installer will pop up in your browser, follow the directions there to get a working Umbraco install up and running.
@@ -168,40 +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))
## How do I even begin?
Great question! The short version goes like this:
* **Fork** - create a fork of [`Umbraco-CMS` on GitHub](https://github.com/umbraco/Umbraco-CMS)
![Fork the repository](tools/contributing/forkrepository.png)
* **Clone** - when GitHub has created your fork, you can clone it in your favorite Git tool
![Clone the fork](tools/contributing/clonefork.png)
* **Build** - build your fork of Umbraco locally as described in [building Umbraco from source code](#building-umbraco-from-source-code)
* **Change** - make your changes, experiment, have fun, explore and learn, and don't be afraid. We welcome all contributions and will happily give feedback
* **Commit** - done? Yay! 🎉 It is recommended to create a new branch now and name it after the issue you're fixing, we usually follow the format: `temp-U4-12345`. This means it's a temporary branch for the particular issue you're working on, in this case `U4-12345`
* **Push** - great, now you can push the changes up to your fork on GitHub
* **Create pull request** - exciting! You're ready to show us your changes (or not quite ready, you just need some feedback to progress). GitHub has picked up on the new branch you've pushed and will offer to create a Pull Request. Click that green button and away you go.
![Create a pull request](tools/contributing/createpullrequest.png)
The Umbraco development team can now start reviewing your proposed changes and give you feedback on them. If it's not perfect, we'll either fix up what we need or we can request you to make some additional changes.
If you make the corrections we ask for in the same branch and push them to your fork again, the pull request automatically updates with the additional commit(s) so we can review it again. If all is well, we'll merge the code and your commits are forever part of Umbraco!
Not all changes are wanted so on occassion we might close a PR without merging it. We will give you feedback why we can't accept your changes at this and we'll be nice about it, thanking you for spending your valueable time.
Remember, if an issue is in the `Up for grabs` list or you've asked for some feedback before you send us a PR, your PR will not be closed as unwanted.
## Problems?
Did something not work as expected? Try leaving a note in the ["Contributing to Umbraco"](https://our.umbraco.org/forum/contributing-to-umbraco-cms/) forum, the team monitors that one closely!
## Credits
This contribution guide borrows heavily from the excellent work on [the Atom contribution guide](https://github.com/atom/atom/blob/master/CONTRIBUTING.md). A big [#h5yr](http://h5yr.com/) to them!
(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))
+33
View File
@@ -0,0 +1,33 @@
# Contributing to Umbraco CMS
When youre considering creating a pull request for Umbraco CMS, we will categorize them in two different sizes, small and large.
The process for both sizes is very similar, as [explained in the contribution document](CONTRIBUTING.md#how-do-i-begin).
## Small PRs
Bug fixes and small improvements - can be recognized by seeing a small number of changes and possibly a small number of new files.
Were usually able to handle small PRs pretty quickly. A community volunteer will do the initial review and flag it for Umbraco HQ as “community tested”. If everything looks good, it will be merged pretty quickly [as per the described process](REVIEW_PROCESS.md).
### Up for grabs
Umbraco HQ will regularly mark newly created issues on the issue tracker with the `Up for grabs` tag. This means that the proposed changes are wanted in Umbraco but the HQ does not have the time to make them at this time. These issues are usually small enough to fit in the "Small PRs" category and we encourage anyone to pick them up and help out.
If you do start working on something, make sure leave a small comment on the issue saying something like: "I'm working on this". That way other people stumbling upon the issue know they don't need to pick it up, someone already has.
## Large PRs
New features and large refactorings - can be recognized by seeing a large number of changes, plenty of new files, updates to package manager files (NuGets packages.config, NPMs packages.json, etc.).
We would love to follow the same process for larger PRs but this is not always possible due to time limitations and priorities that need to be aligned. We dont want to put up any barriers, but this document should set the correct expectations.
Please make sure to describe your idea in an issue, it helps to put in mockup screenshots or videos.
If the change makes sense for HQ to include in Umbraco CMS we will leave you some feedback on how wed like to see it being implemented.
If a larger pull request is encouraged by Umbraco HQ, the process will be similar to what is described in the [small PRs process](#small-prs) above, well get feedback to you within 14 days. Finalizing and merging the PR might take longer though as it will likely need to be picked up by the development team to make sure everything is in order. Well keep you posted on the progress.
### Pull request or package?
If it doesnt fit in CMS right now, we will likely encourage you to make it into a package instead. A package is a great way to check out popularity of a feature, learn how people use it, validate good usability and to fix bugs.
Eventually, a package could "graduate" to be included in the CMS.
+49 -47
View File
@@ -1,47 +1,49 @@
[![Build status](https://ci.appveyor.com/api/projects/status/6by6harxtxt0ocdx/branch/dev-v7?svg=true)](https://ci.appveyor.com/project/Umbraco/umbraco-cms-b2cri/branch/dev-v7)
Umbraco CMS
===========
The friendliest, most flexible and fastest growing ASP.NET CMS used by more than 443,000 websites worldwide: [https://umbraco.com](https://umbraco.com)
[![ScreenShot](vimeo.png)](https://vimeo.com/172382998/)
## Umbraco CMS
Umbraco is a free open source Content Management System built on the ASP.NET platform. Our mission is to help you deliver delightful digital experiences by making Umbraco friendly, simpler and social.
## Watch an introduction video
[![ScreenShot](http://umbraco.com/images/whatisumbraco.png)](https://umbraco.tv/videos/umbraco-v7/content-editor/basics/introduction/cms-explanation/)
## Umbraco - The Friendly CMS
For the first time on the Microsoft platform, there is a free user and developer friendly CMS that makes it quick and easy to create websites - or a breeze to build complex web applications. Umbraco has award-winning integration capabilities and supports ASP.NET MVC or Web Forms, including User and Custom Controls, out of the box.
Umbraco is not only loved by developers, but is a content editors dream. Enjoy intuitive editing tools, media management, responsive views and approval workflows to send your content live.
Used by more than 443,000 active websites including Carlsberg, Segway, Amazon and Heinz and **The Official ASP.NET and IIS.NET website from Microsoft** ([https://asp.net](https://asp.net) / [https://iis.net](https://iis.net)), you can be sure that the technology is proven, stable and scales. Backed by the team at Umbraco HQ, and supported by a dedicated community of over 220,000 craftspeople globally, you can trust that Umbraco is a safe choice and is here to stay.
To view more examples, please visit [https://umbraco.com/why-umbraco/#caseStudies](https://umbraco.com/why-umbraco/#caseStudies)
## Why Open Source?
As an Open Source platform, Umbraco is more than just a CMS. We are transparent with our roadmap for future versions, our incremental sprint planning notes are publicly accessible and community contributions and packages are available for all to use.
## Trying out Umbraco CMS
[Umbraco Cloud](https://umbraco.com) is the easiest and fastest way to use Umbraco yet with full support for all your custom .NET code and intergrations. You're up and running in less than a minute and your life will be made easier with automated upgrades and a built-in deployment engine. We offer a free 14 day trial, no credit card needed.
If you want to DIY you can [download Umbraco](https://our.umbraco.org/download) either as a ZIP file or via NuGet. It's the same version of Umbraco CMS that powers Umbraco Cloud, but you'll need to find a place to host yourself and handling deployments and upgrades is all down to you.
## Community
Our friendly community is available 24/7 at the community hub we call ["Our Umbraco"](https://our.umbraco.org). Our Umbraco feature forums for questions and answers, documentation, downloadable plugins for Umbraco and a rich collection of community resources.
## Contribute to Umbraco
Umbraco is contribution focused and community driven. If you want to contribute back to Umbraco please check out our [guide to contributing](CONTRIBUTING.md).
## 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://our.umbraco.org/contribute/report-an-issue-or-request-a-feature).
To view existing issues, please visit [http://issues.umbraco.org](http://issues.umbraco.org).
[![Build status](https://ci.appveyor.com/api/projects/status/6by6harxtxt0ocdx/branch/dev-v7?svg=true)](https://ci.appveyor.com/project/Umbraco/umbraco-cms-b2cri/branch/dev-v7)
_Looking for Umbraco version 8? [Click here](https://github.com/umbraco/Umbraco-CMS/tree/temp8) to go to the v8 branch_
Umbraco CMS
===========
The friendliest, most flexible and fastest growing ASP.NET CMS used by more than 443,000 websites worldwide: [https://umbraco.com](https://umbraco.com)
[![ScreenShot](img/vimeo.png)](https://vimeo.com/172382998/)
## Umbraco CMS
Umbraco is a free open source Content Management System built on the ASP.NET platform. Our mission is to help you deliver delightful digital experiences by making Umbraco friendly, simpler and social.
## Watch an introduction video
[![ScreenShot](https://shop.umbraco.com/images/whatisumbraco.png)](https://umbraco.tv/videos/umbraco-v7/content-editor/basics/introduction/cms-explanation/)
## Umbraco - The Friendly CMS
For the first time on the Microsoft platform, there is a free user and developer friendly CMS that makes it quick and easy to create websites - or a breeze to build complex web applications. Umbraco has award-winning integration capabilities and supports ASP.NET MVC or Web Forms, including User and Custom Controls, out of the box.
Umbraco is not only loved by developers, but is a content editors dream. Enjoy intuitive editing tools, media management, responsive views and approval workflows to send your content live.
Used by more than 443,000 active websites including Carlsberg, Segway, Amazon and Heinz and **The Official ASP.NET and IIS.NET website from Microsoft** ([https://asp.net](https://asp.net) / [https://iis.net](https://iis.net)), you can be sure that the technology is proven, stable and scales. Backed by the team at Umbraco HQ, and supported by a dedicated community of over 220,000 craftspeople globally, you can trust that Umbraco is a safe choice and is here to stay.
To view more examples, please visit [https://umbraco.com/why-umbraco/#caseStudies](https://umbraco.com/why-umbraco/#caseStudies)
## Why Open Source?
As an Open Source platform, Umbraco is more than just a CMS. We are transparent with our roadmap for future versions, our incremental sprint planning notes are publicly accessible and community contributions and packages are available for all to use.
## Trying out Umbraco CMS
[Umbraco Cloud](https://umbraco.com) is the easiest and fastest way to use Umbraco yet with full support for all your custom .NET code and intergrations. You're up and running in less than a minute and your life will be made easier with automated upgrades and a built-in deployment engine. We offer a free 14 day trial, no credit card needed.
If you want to DIY you can [download Umbraco](https://our.umbraco.org/download) either as a ZIP file or via NuGet. It's the same version of Umbraco CMS that powers Umbraco Cloud, but you'll need to find a place to host yourself and handling deployments and upgrades is all down to you.
## Community
Our friendly community is available 24/7 at the community hub we call ["Our Umbraco"](https://our.umbraco.org). Our Umbraco feature forums for questions and answers, documentation, downloadable plugins for Umbraco and a rich collection of community resources.
## Contribute to Umbraco
Umbraco is contribution focused and community driven. If you want to contribute back to Umbraco please check out our [guide to contributing](CONTRIBUTING.md).
## 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://our.umbraco.org/contribute/report-an-issue-or-request-a-feature).
To view existing issues, please visit [http://issues.umbraco.org](http://issues.umbraco.org).
+25
View File
@@ -0,0 +1,25 @@
# Review process
You're an awesome person and have sent us your contribution in the form of a pull request! It's now time to relax for a bit and wait for our response.
In order to set some expectations, here's what happens next.
## Review process
You will get an initial reply within 48 hours (workdays) to acknowledge that weve seen your PR and well pick it up as soon as we can.
You will get feedback within at most 14 days after opening the PR. Youll most likely get feedback sooner though. Then there are a few possible outcomes:
- Your proposed change is awesome! We merge it in and it will be included in the next minor release of Umbraco
- If the change is a high priority bug fix, we will cherry-pick it into the next patch release as well so that we can release it as soon as possible
- Your proposed change is awesome but needs a bit more work, well give you feedback on the changes wed like to see
- Your proposed change is awesome but.. not something were looking to include at this point. Well close your PR and the related issue (well be nice about it!)
## Are you still available?
We understand you have other things to do and can't just drop everything to help us out.
So if were asking for your help to improve the PR well wait for two weeks to give you a fair chance to make changes. Well ask for an update if we dont hear back from you after that time.
If we dont hear back from you for 4 weeks, well close the PR so that it doesnt just hang around forever. Youre very welcome to re-open it once you have some more time to spend on it.
There will be times that we really like your proposed changes and well finish the final improvements wed like to see ourselves. You still get the credits and your commits will live on in the git repository.

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

View File

Before

Width:  |  Height:  |  Size: 27 KiB

After

Width:  |  Height:  |  Size: 27 KiB

+2 -2
View File
@@ -11,5 +11,5 @@ using System.Resources;
[assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyFileVersion("7.11.0")]
[assembly: AssemblyInformationalVersion("7.11.0")]
[assembly: AssemblyFileVersion("7.11.2")]
[assembly: AssemblyInformationalVersion("7.11.2")]
@@ -35,7 +35,7 @@ namespace Umbraco.Core.Configuration
private static Version _version;
private static readonly object Locker = new object();
//make this volatile so that we can ensure thread safety with a double check lock
private static volatile string _reservedUrlsCache;
private static volatile string _reservedUrlsCache;
private static string _reservedPathsCache;
private static HashSet<string> _reservedList = new HashSet<string>();
private static string _reservedPaths;
@@ -190,7 +190,7 @@ namespace Umbraco.Core.Configuration
/// This will return the MVC area that we will route all custom routes through like surface controllers, etc...
/// We will use the 'Path' (default ~/umbraco) to create it but since it cannot contain '/' and people may specify a path of ~/asdf/asdf/admin
/// we will convert the '/' to '-' and use that as the path. its a bit lame but will work.
///
///
/// We also make sure that the virtual directory (SystemDirectories.Root) is stripped off first, otherwise we'd end up with something
/// like "MyVirtualDirectory-Umbraco" instead of just "Umbraco".
/// </remarks>
@@ -205,7 +205,7 @@ namespace Umbraco.Core.Configuration
var path = Path;
if (path.StartsWith(SystemDirectories.Root)) // beware of TrimStart, see U4-2518
path = path.Substring(SystemDirectories.Root.Length);
return path.TrimStart('~').TrimStart('/').Replace('/', '-').Trim().ToLower();
return path.TrimStart('~').TrimStart('/').Replace('/', '-').Trim().ToLower();
}
}
@@ -312,7 +312,7 @@ namespace Umbraco.Core.Configuration
SetMembershipProvidersLegacyEncoding(UmbracoConfig.For.UmbracoSettings().Providers.DefaultBackOfficeUserProvider, value);
}
}
/// <summary>
/// Saves a setting into the configuration file.
/// </summary>
@@ -503,7 +503,7 @@ namespace Umbraco.Core.Configuration
}
/// <summary>
/// Returns a string value to determine if umbraco should skip version-checking.
/// Returns the number of days that should take place between version checks.
/// </summary>
/// <value>The version check period in days (0 = never).</value>
public static int VersionCheckPeriod
@@ -6,7 +6,7 @@ namespace Umbraco.Core.Configuration
{
public class UmbracoVersion
{
private static readonly Version Version = new Version("7.11.0");
private static readonly Version Version = new Version("7.11.2");
/// <summary>
/// Gets the current version of Umbraco.
+2 -2
View File
@@ -92,7 +92,7 @@
/// alias for the dictionary tree.
/// </summary>
public const string Dictionary = "dictionary";
public const string Stylesheets = "stylesheets";
/// <summary>
@@ -135,4 +135,4 @@
}
}
}
@@ -40,12 +40,13 @@ namespace Umbraco.Core.PropertyEditors.ValueConverters
//TODO: Change all singleton access to use ctor injection in v8!!!
//TODO: That would mean that property value converters would need to be request lifespan, hrm....
bool isDebug = HttpContext.Current != null && HttpContext.Current.IsDebuggingEnabled;
var gridConfig = UmbracoConfig.For.GridConfig(
ApplicationContext.Current.ProfilingLogger.Logger,
ApplicationContext.Current.ApplicationCache.RuntimeCache,
new DirectoryInfo(IOHelper.MapPath(SystemDirectories.AppPlugins)),
new DirectoryInfo(IOHelper.MapPath(SystemDirectories.Config)),
HttpContext.Current.IsDebuggingEnabled);
isDebug);
var sections = GetArray(obj, "sections");
foreach (var section in sections.Cast<JObject>())
@@ -112,4 +113,4 @@ namespace Umbraco.Core.PropertyEditors.ValueConverters
}
}
}
}
@@ -109,6 +109,23 @@ namespace Umbraco.Core.Services
return new ContentTypeAvailableCompositionsResults(ancestors, result);
}
/// <summary>
/// Returns the list of content types the composition is used in
/// </summary>
/// <param name="allContentTypes"></param>
/// <param name="ctService"></param>
/// <param name="source"></param>
/// <returns></returns>
internal static IEnumerable<IContentTypeComposition> GetWhereCompositionIsUsedInContentTypes(this IContentTypeService ctService,
IContentTypeComposition source,
IContentTypeComposition[] allContentTypes)
{
var sourceId = source != null ? source.Id : 0;
// find which content types are using this composition
return allContentTypes.Where(x => x.ContentTypeComposition.Any(y => y.Id == sourceId)).ToArray();
}
private static IContentTypeComposition[] GetAncestors(IContentTypeComposition ctype, IContentTypeComposition[] allContentTypes)
{
@@ -162,4 +179,4 @@ namespace Umbraco.Core.Services
}
}
}
}
+28 -19
View File
@@ -8,14 +8,12 @@ using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Text.RegularExpressions;
using System.Web;
using System.Xml;
using Newtonsoft.Json;
using Umbraco.Core.Configuration;
using System.Web.Security;
using Umbraco.Core.Strings;
using Newtonsoft.Json;
using Umbraco.Core.CodeAnnotations;
using Umbraco.Core.Configuration;
using Umbraco.Core.IO;
using Umbraco.Core.Strings;
namespace Umbraco.Core
{
@@ -121,8 +119,8 @@ namespace Umbraco.Core
//if the resolution was success, return it, otherwise just return the path, we've detected
// it's a path but maybe it's relative and resolution has failed, etc... in which case we're just
// returning what was given to us.
return resolvedUrlResult.Success
? resolvedUrlResult
return resolvedUrlResult.Success
? resolvedUrlResult
: Attempt.Succeed(input);
}
}
@@ -144,7 +142,7 @@ namespace Umbraco.Core
}
internal static readonly Regex Whitespace = new Regex(@"\s+", RegexOptions.Compiled);
internal static readonly string[] JsonEmpties = new [] { "[]", "{}" };
internal static readonly string[] JsonEmpties = new[] { "[]", "{}" };
internal static bool DetectIsEmptyJson(this string input)
{
return JsonEmpties.Contains(Whitespace.Replace(input, string.Empty));
@@ -472,13 +470,13 @@ namespace Umbraco.Core
return ch.ToString(CultureInfo.InvariantCulture) == ch.ToString(CultureInfo.InvariantCulture).ToUpperInvariant();
}
/// <summary>Is null or white space.</summary>
/// <param name="str">The str.</param>
/// <returns>The is null or white space.</returns>
public static bool IsNullOrWhiteSpace(this string str)
{
return (str == null) || (str.Trim().Length == 0);
}
/// <summary>Indicates whether a specified string is null, empty, or
/// consists only of white-space characters.</summary>
/// <param name="value">The value to check.</param>
/// <returns>Returns <see langword="true"/> if the value is null,
/// empty, or consists only of white-space characters, otherwise
/// returns <see langword="false"/>.</returns>
public static bool IsNullOrWhiteSpace(this string value) => string.IsNullOrWhiteSpace(value);
public static string IfNullOrWhiteSpace(this string str, string defaultValue)
{
@@ -1436,14 +1434,25 @@ namespace Umbraco.Core
return ReplaceMany(text, regexSpecialCharacters);
}
/// <summary>
/// Checks whether a string "haystack" contains within it any of the strings in the "needles" collection and returns true if it does or false if it doesn't
/// </summary>
/// <param name="haystack">The string to check</param>
/// <param name="needles">The collection of strings to check are contained within the first string</param>
/// <param name="comparison">The type of comparision to perform - defaults to <see cref="StringComparison.CurrentCulture"/></param>
/// <returns>True if any of the needles are contained with haystack; otherwise returns false</returns>
/// Added fix to ensure the comparison is used - see http://issues.umbraco.org/issue/U4-11313
public static bool ContainsAny(this string haystack, IEnumerable<string> needles, StringComparison comparison = StringComparison.CurrentCulture)
{
if (haystack == null) throw new ArgumentNullException("haystack");
if (string.IsNullOrEmpty(haystack) == false || needles.Any())
if (haystack == null)
throw new ArgumentNullException("haystack");
if (string.IsNullOrEmpty(haystack) || needles == null || !needles.Any())
{
return needles.Any(value => haystack.IndexOf(value) >= 0);
return false;
}
return false;
return needles.Any(value => haystack.IndexOf(value, comparison) >= 0);
}
public static bool CsvContains(this string csv, string value)
+2 -2
View File
@@ -45,8 +45,8 @@
<Reference Include="AutoMapper.Net4, Version=3.3.1.0, Culture=neutral, PublicKeyToken=be96cd2c38ef1005, processorArchitecture=MSIL">
<HintPath>..\packages\AutoMapper.3.3.1\lib\net40\AutoMapper.Net4.dll</HintPath>
</Reference>
<Reference Include="ClientDependency.Core, Version=1.9.6.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\ClientDependency.1.9.6\lib\net45\ClientDependency.Core.dll</HintPath>
<Reference Include="ClientDependency.Core, Version=1.9.7.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\ClientDependency.1.9.7\lib\net45\ClientDependency.Core.dll</HintPath>
</Reference>
<Reference Include="HtmlAgilityPack, Version=1.4.9.5, Culture=neutral, PublicKeyToken=bd319b19eaf3b43a, processorArchitecture=MSIL">
<HintPath>..\packages\HtmlAgilityPack.1.4.9.5\lib\Net45\HtmlAgilityPack.dll</HintPath>
+1 -1
View File
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="AutoMapper" version="3.3.1" targetFramework="net45" />
<package id="ClientDependency" version="1.9.6" targetFramework="net45" />
<package id="ClientDependency" version="1.9.7" targetFramework="net45" />
<package id="HtmlAgilityPack" version="1.4.9.5" targetFramework="net45" />
<package id="ImageProcessor" version="2.5.6" targetFramework="net45" />
<package id="log4net" version="2.0.8" targetFramework="net45" />
@@ -285,8 +285,7 @@ AnotherContentFinder
public void Resolves_Attributed_Trees()
{
var trees = _manager.ResolveAttributedTrees();
// commit 6c5e35ec2cbfa31be6790d1228e0c2faf5f55bc8 brings the count down to 14
Assert.AreEqual(6, trees.Count());
Assert.AreEqual(5, trees.Count());
}
[Test]
@@ -300,7 +299,7 @@ AnotherContentFinder
public void Resolves_Trees()
{
var trees = _manager.ResolveTrees();
Assert.AreEqual(34, trees.Count());
Assert.AreEqual(33, trees.Count());
}
[Test]
@@ -1,4 +1,5 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using NUnit.Framework;
@@ -11,20 +12,20 @@ namespace Umbraco.Tests.Strings
[TestFixture]
public class StringExtensionsTests
{
[SetUp]
public void Setup()
{
[SetUp]
public void Setup()
{
ShortStringHelperResolver.Reset();
ShortStringHelperResolver.Current = new ShortStringHelperResolver(new MockShortStringHelper());
Resolution.Freeze();
}
Resolution.Freeze();
}
[TearDown]
public void TearDown()
{
ShortStringHelperResolver.Reset();
}
[TestCase("hello", "world", false)]
[TestCase("hello", "hello", true)]
[TestCase("hellohellohellohellohellohellohello", "hellohellohellohellohellohellohelloo", false)]
@@ -53,43 +54,43 @@ namespace Umbraco.Tests.Strings
[TestCase("hello.txt", "hello")]
[TestCase("this.is.a.Txt", "this.is.a")]
[TestCase("this.is.not.a. Txt", "this.is.not.a. Txt")]
[TestCase("not a file","not a file")]
[TestCase("not a file", "not a file")]
public void Strip_File_Extension(string input, string result)
{
var stripped = input.StripFileExtension();
Assert.AreEqual(stripped, result);
}
[TestCase("This is a string to encrypt")]
[TestCase("This is a string to encrypt\nThis is a second line")]
[TestCase(" White space is preserved ")]
[TestCase("\nWhite space is preserved\n")]
public void Encrypt_And_Decrypt(string input)
{
var encrypted = input.EncryptWithMachineKey();
var decrypted = encrypted.DecryptWithMachineKey();
Assert.AreNotEqual(input, encrypted);
Assert.AreEqual(input, decrypted);
}
[TestCase("This is a string to encrypt")]
[TestCase("This is a string to encrypt\nThis is a second line")]
[TestCase(" White space is preserved ")]
[TestCase("\nWhite space is preserved\n")]
public void Encrypt_And_Decrypt(string input)
{
var encrypted = input.EncryptWithMachineKey();
var decrypted = encrypted.DecryptWithMachineKey();
Assert.AreNotEqual(input, encrypted);
Assert.AreEqual(input, decrypted);
}
[Test()]
public void Encrypt_And_Decrypt_Long_Value()
{
// Generate a really long string
char[] chars = { 'a', 'b', 'c', '1', '2', '3', '\n' };
[Test()]
public void Encrypt_And_Decrypt_Long_Value()
{
// Generate a really long string
char[] chars = { 'a', 'b', 'c', '1', '2', '3', '\n' };
string valueToTest = string.Empty;
string valueToTest = string.Empty;
// Create a string 7035 chars long
for (int i = 0; i < 1005; i++)
for (int j = 0; j < chars.Length; j++)
valueToTest += chars[j].ToString();
// Create a string 7035 chars long
for (int i = 0; i < 1005; i++)
for (int j = 0; j < chars.Length; j++)
valueToTest += chars[j].ToString();
var encrypted = valueToTest.EncryptWithMachineKey();
var decrypted = encrypted.DecryptWithMachineKey();
Assert.AreNotEqual(valueToTest, encrypted);
Assert.AreEqual(valueToTest, decrypted);
}
var encrypted = valueToTest.EncryptWithMachineKey();
var decrypted = encrypted.DecryptWithMachineKey();
Assert.AreNotEqual(valueToTest, encrypted);
Assert.AreEqual(valueToTest, decrypted);
}
[TestCase("Hello this is my string", " string", "Hello this is my")]
[TestCase("Hello this is my string strung", " string", "Hello this is my string strung")]
@@ -147,6 +148,42 @@ namespace Umbraco.Tests.Strings
Assert.AreEqual(expected, output);
}
[TestCase("pineapple", new string[] { "banana", "apple", "blueberry", "strawberry" }, StringComparison.CurrentCulture, true)]
[TestCase("PINEAPPLE", new string[] { "banana", "apple", "blueberry", "strawberry" }, StringComparison.CurrentCulture, false)]
[TestCase("pineapple", new string[] { "banana", "Apple", "blueberry", "strawberry" }, StringComparison.CurrentCulture, false)]
[TestCase("pineapple", new string[] { "banana", "Apple", "blueberry", "strawberry" }, StringComparison.OrdinalIgnoreCase, true)]
[TestCase("pineapple", new string[] { "banana", "blueberry", "strawberry" }, StringComparison.OrdinalIgnoreCase, false)]
[TestCase("Strawberry unicorn pie", new string[] { "Berry" }, StringComparison.OrdinalIgnoreCase, true)]
[TestCase("empty pie", new string[0], StringComparison.OrdinalIgnoreCase, false)]
public void ContainsAny(string haystack, IEnumerable<string> needles, StringComparison comparison, bool expected)
{
bool output = haystack.ContainsAny(needles, comparison);
Assert.AreEqual(expected, output);
}
[TestCase("", true)]
[TestCase(" ", true)]
[TestCase("\r\n\r\n", true)]
[TestCase("\r\n", true)]
[TestCase(@"
Hello
", false)]
[TestCase(null, true)]
[TestCase("a", false)]
[TestCase("abc", false)]
[TestCase("abc ", false)]
[TestCase(" abc", false)]
[TestCase(" abc ", false)]
public void IsNullOrWhiteSpace(string value, bool expected)
{
// Act
bool result = value.IsNullOrWhiteSpace();
// Assert
Assert.AreEqual(expected, result);
}
// FORMAT STRINGS
// note: here we just ensure that the proper helper gets called properly
@@ -239,7 +276,7 @@ namespace Umbraco.Tests.Strings
[Test]
public void ReplaceManyByOneChar()
{
var output = "JUST-ANYTHING".ReplaceMany(new char[] {}, '*');
var output = "JUST-ANYTHING".ReplaceMany(new char[] { }, '*');
Assert.AreEqual("REPLACE-MANY-B::JUST-ANYTHING", output);
}
}
@@ -429,9 +429,10 @@ Umbraco.</p>
<CWS_NewsEventsList id="1155" parentID="1139" level="2" writerID="0" creatorID="0" nodeType="1126" template="1112" sortOrder="3" createDate="2009-02-27T09:57:30" updateDate="2010-04-22T02:18:31" nodeName="News and Events" urlName="news-and-events" writerName="Administrator" creatorName="Administrator" path="-1,1139,1155" isDoc="">
<CWS_EventItem id="1156" parentID="1155" level="3" writerID="0" creatorID="0" nodeType="1122" template="1107" sortOrder="1" createDate="2009-02-27T10:00:53" updateDate="2010-04-22T02:18:31" nodeName="Codegarden 09" urlName="codegarden-09" writerName="Administrator" creatorName="Administrator" path="-1,1139,1155,1156" isDoc="">
<eventDate>2009-06-22T00:00:00</eventDate>
<bodyText><![CDATA[
<h3>Come join the annual umbraco developer conference in Wonderful
Copenhagen on June 22nd - 23rd. Two days for insights, eye-openers,
<bodyText>
<![CDATA[
<h3>Come join the annual Umbraco developer conference in Wonderful
Odense on May 22nd - 24th. Two days for insights, eye-openers,
great conversations and friendly people.</h3>
<p>The who's who of umbraco will be gathered and share their
@@ -441,8 +442,8 @@ huge industrial venue in central Copenhagen where we'll have one
huge room, three rooms for breakout sessions and a Caf&eacute; that
serves your taste of espresso.</p>
<p>Come join the annual umbraco developer conference in Wonderful
Copenhagen on June 22nd - 23rd. Two days for insights, eye-openers,
<p>Come join the annual Umbraco developer conference in Wonderful
Odense on May 22nd - 24th. Two days for insights, eye-openers,
great conversations and friendly people.</p>
<p>We've planned a program that fits both experienced umbraco users
@@ -613,4 +614,4 @@ www.yourcompany.co.uk]]></emailMessageToFriend>
<umbracoUrlAlias />
<umbracoRedirect>0</umbracoRedirect>
</CWS_Home>
</root>
</root>
+12
View File
@@ -7,6 +7,7 @@ var sort = require('gulp-sort');
var connect = require('gulp-connect');
var open = require('gulp-open');
var runSequence = require('run-sequence');
const imagemin = require('gulp-imagemin');
var _ = require('lodash');
var MergeStream = require('merge-stream');
@@ -206,6 +207,17 @@ gulp.task('dependencies', function () {
//css, fonts and image files
stream.add(
gulp.src(sources.globs.assets)
.pipe(imagemin([
imagemin.gifsicle({interlaced: true}),
imagemin.jpegtran({progressive: true}),
imagemin.optipng({optimizationLevel: 5}),
imagemin.svgo({
plugins: [
{removeViewBox: true},
{cleanupIDs: false}
]
})
]))
.pipe(gulp.dest(root + targets.assets))
);
+1
View File
@@ -27,6 +27,7 @@
"gulp": "^3.9.1",
"gulp-concat": "^2.6.0",
"gulp-connect": "5.0.0",
"gulp-imagemin": "^4.1.0",
"gulp-less": "^3.5.0",
"gulp-ngdocs": "^0.3.0",
"gulp-open": "^2.1.0",
+23
View File
@@ -0,0 +1,23 @@
@ECHO OFF
ECHO.
ECHO.
ECHO This will only work when you have NPM available on the command line
ECHO Works great with NodeJS Portable - https://gareth.flowers/nodejs-portable/
ECHO.
ECHO.
set /P c=Are you sure you want to continue [Y/N]?
if /I "%c%" EQU "Y" goto :setupgulp
if /I "%c%" EQU "N" goto :eof
:setupgulp
call npm install
call npm -g install bower
call npm -g install gulp
call npm -g install gulp-cli
ECHO.
ECHO.
ECHO You should now be able to run: gulp build
ECHO.
ECHO.
@@ -67,97 +67,97 @@ Use this directive to render an umbraco button. The directive can be used to gen
@param {boolean=} disabled Set to <code>true</code> to disable the button.
**/
(function() {
'use strict';
(function () {
'use strict';
function ButtonDirective($timeout) {
function ButtonDirective($timeout) {
function link(scope, el, attr, ctrl) {
function link(scope, el, attr, ctrl) {
scope.style = null;
scope.style = null;
scope.innerState = "init";
function activate() {
function activate() {
scope.blockElement = false;
scope.blockElement = false;
if (!scope.state) {
scope.state = "init";
}
if (scope.buttonStyle) {
if (scope.buttonStyle) {
// make it possible to pass in multiple styles
if (scope.buttonStyle.startsWith("[") && scope.buttonStyle.endsWith("]")) {
// make it possible to pass in multiple styles
if(scope.buttonStyle.startsWith("[") && scope.buttonStyle.endsWith("]")) {
// when using an attr it will always be a string so we need to remove square brackets
// and turn it into and array
var withoutBrackets = scope.buttonStyle.replace(/[\[\]']+/g,'');
// split array by , + make sure to catch whitespaces
var array = withoutBrackets.split(/\s?,\s?/g);
angular.forEach(array, function(item){
scope.style = scope.style + " " + "btn-" + item;
if(item === "block") {
// when using an attr it will always be a string so we need to remove square brackets
// and turn it into and array
var withoutBrackets = scope.buttonStyle.replace(/[\[\]']+/g, '');
// split array by , + make sure to catch whitespaces
var array = withoutBrackets.split(/\s?,\s?/g);
angular.forEach(array, function (item) {
scope.style = scope.style + " " + "btn-" + item;
if (item === "block") {
scope.blockElement = true;
}
});
} else {
scope.style = "btn-" + scope.buttonStyle;
if (scope.buttonStyle === "block") {
scope.blockElement = true;
}
});
} else {
scope.style = "btn-" + scope.buttonStyle;
if(scope.buttonStyle === "block") {
scope.blockElement = true;
}
}
}
}
activate();
activate();
var unbindStateWatcher = scope.$watch('state', function (newValue, oldValue) {
if (newValue) {
scope.innerState = newValue;
}
var unbindStateWatcher = scope.$watch('state', function(newValue, oldValue) {
if (newValue === 'success' || newValue === 'error') {
$timeout(function () {
scope.innerState = 'init';
}, 2000);
}
if (newValue === 'success' || newValue === 'error') {
$timeout(function() {
scope.state = 'init';
}, 2000);
});
scope.$on('$destroy', function () {
unbindStateWatcher();
});
}
var directive = {
transclude: true,
restrict: 'E',
replace: true,
templateUrl: 'views/components/buttons/umb-button.html',
link: link,
scope: {
action: "&?",
href: "@?",
type: "@",
buttonStyle: "@?",
state: "=?",
shortcut: "@?",
shortcutWhenHidden: "@",
label: "@?",
labelKey: "@?",
icon: "@?",
disabled: "=",
size: "@?",
alias: "@?"
}
};
});
return directive;
scope.$on('$destroy', function() {
unbindStateWatcher();
});
}
}
var directive = {
transclude: true,
restrict: 'E',
replace: true,
templateUrl: 'views/components/buttons/umb-button.html',
link: link,
scope: {
action: "&?",
href: "@?",
type: "@",
buttonStyle: "@?",
state: "=?",
shortcut: "@?",
shortcutWhenHidden: "@",
label: "@?",
labelKey: "@?",
icon: "@?",
disabled: "=",
size: "@?",
alias: "@?"
}
};
return directive;
}
angular.module('umbraco.directives').directive('umbButton', ButtonDirective);
angular.module('umbraco.directives').directive('umbButton', ButtonDirective);
})();
@@ -77,6 +77,8 @@
resetLastListPageNumber($scope.content);
eventsService.emit("content.loaded", { content: $scope.content });
$scope.page.loading = false;
});
@@ -130,6 +132,8 @@
$scope.page.buttonGroupState = "busy";
eventsService.emit("content.saving", { content: $scope.content, action: args.action });
contentEditingHelper.contentEditorPerformSave({
statusMessage: args.statusMessage,
saveMethod: args.saveMethod,
@@ -144,6 +148,9 @@
$scope.page.buttonGroupState = "success";
deferred.resolve(data);
eventsService.emit("content.saved", { content: $scope.content, action: args.action });
}, function (err) {
//error
if (err) {
@@ -183,7 +190,9 @@
$scope.page.loading = false;
});
eventsService.emit("content.newReady", { content: $scope.content });
});
}
else {
@@ -198,6 +207,8 @@
$scope.page.buttonGroupState = "busy";
eventsService.emit("content.unpublishing", { content: $scope.content });
contentResource.unPublish($scope.content.id)
.then(function (data) {
@@ -215,6 +226,8 @@
$scope.page.buttonGroupState = "success";
eventsService.emit("content.unpublished", { content: $scope.content });
}, function(err) {
formHelper.showNotifications(err.data);
$scope.page.buttonGroupState = 'error';
@@ -140,37 +140,7 @@ function umbTreeDirective($compile, $log, $q, $rootScope, treeService, notificat
//Filter the path for root node ids (we don't want to pass in -1 or 'init')
args.path = _.filter(args.path, function (item) { return (item !== "init" && item !== "-1"); });
//Once those are filtered we need to check if the current user has a special start node id,
// if they do, then we're going to trim the start of the array for anything found from that start node
// and previous so that the tree syncs properly. The tree syncs from the top down and if there are parts
// of the tree's path in there that don't actually exist in the dom/model then syncing will not work.
userService.getCurrentUser().then(function (userData) {
var startNodes = [];
for (var i = 0; i < userData.startContentIds; i++) {
startNodes.push(userData.startContentIds[i]);
}
for (var j = 0; j < userData.startMediaIds; j++) {
startNodes.push(userData.startMediaIds[j]);
}
_.each(startNodes, function (i) {
var found = _.find(args.path, function (p) {
return String(p) === String(i);
});
if (found) {
args.path = args.path.splice(_.indexOf(args.path, found));
}
});
loadPath(args.path, args.forceReload, args.activate);
});
loadPath(args.path, args.forceReload, args.activate);
return deferred.promise;
};
@@ -1,12 +1,51 @@
/**
* @ngdoc directive
* @name umbraco.directives.directive:umbConfirm
* @function
* @description
* A confirmation dialog
*
* @restrict E
*/
@ngdoc directive
@name umbraco.directives.directive:umbConfirm
@restrict E
@scope
@description
A confirmation dialog
<h3>Markup example</h3>
<pre>
<div ng-controller="My.Controller as vm">
<umb-confirm caption="Title" on-confirm="vm.onConfirm()" on-cancel="vm.onCancel()"></umb-confirm>
</div>
</pre>
<h3>Controller example</h3>
<pre>
(function () {
"use strict";
function Controller() {
var vm = this;
vm.onConfirm = function() {
alert('Confirm clicked');
};
vm.onCancel = function() {
alert('Cancel clicked');
}
}
angular.module("umbraco").controller("My.Controller", Controller);
})();
</pre>
@param {string} caption (<code>attribute</code>): The caption shown above the buttons
@param {callback} on-confirm (<code>attribute</code>): The call back when the "OK" button is clicked. If not set the button will not be shown
@param {callback} on-cancel (<code>atribute</code>): The call back when the "Cancel" button is clicked. If not set the button will not be shown
**/
function confirmDirective() {
return {
restrict: "E", // restrict to an element
@@ -18,7 +57,16 @@ function confirmDirective() {
caption: '@'
},
link: function (scope, element, attr, ctrl) {
scope.showCancel = false;
scope.showConfirm = false;
if (scope.onConfirm) {
scope.showConfirm = true;
}
if (scope.onCancel) {
scope.showCancel = true;
}
}
};
}
@@ -348,9 +348,10 @@
}
};
//select which resource methods to use, eg document Type or Media Type versions
var availableContentTypeResource = scope.contentType === "documentType" ? contentTypeResource.getAvailableCompositeContentTypes : mediaTypeResource.getAvailableCompositeContentTypes;
var countContentTypeResource = scope.contentType === "documentType" ? contentTypeResource.getCount : mediaTypeResource.getCount;
var whereUsedContentTypeResource = scope.contentType === "documentType" ? contentTypeResource.getWhereCompositionIsUsedInContentTypes : mediaTypeResource.getWhereCompositionIsUsedInContentTypes;
var countContentTypeResource = scope.contentType === "documentType" ? contentTypeResource.getCount : mediaTypeResource.getCount;
//get the currently assigned property type aliases - ensure we pass these to the server side filer
var propAliasesExisting = _.filter(_.flatten(_.map(scope.model.groups, function(g) {
@@ -363,7 +364,14 @@
$q.all([
//get available composite types
availableContentTypeResource(scope.model.id, [], propAliasesExisting).then(function (result) {
setupAvailableContentTypesModel(result);
setupAvailableContentTypesModel(result);
}),
//get where used document types
whereUsedContentTypeResource(scope.model.id).then(function (whereUsed) {
//pass to the dialog model the content type eg documentType or mediaType
scope.compositionsDialogModel.section = scope.contentType;
//pass the list of 'where used' document types
scope.compositionsDialogModel.whereCompositionUsed = whereUsed;
}),
//get content type count
countContentTypeResource().then(function(result) {
@@ -91,12 +91,16 @@
(function () {
'use strict';
function NodePreviewDirective() {
function NodePreviewDirective(userService) {
function link(scope, el, attr, ctrl) {
if (!scope.editLabelKey) {
scope.editLabelKey = "general_edit";
}
userService.getCurrentUser().then(function (u) {
var isAdmin = u.userGroups.indexOf('admin') !== -1;
scope.alias = (Umbraco.Sys.ServerVariables.isDebuggingEnabled === true || isAdmin) ? scope.alias : null;
});
}
var directive = {
@@ -106,6 +110,7 @@
scope: {
icon: "=?",
name: "=",
alias: "=?",
description: "=?",
permissions: "=?",
published: "=?",
@@ -38,7 +38,37 @@ function contentTypeResource($q, $http, umbRequestHelper, umbDataFormatter) {
query),
'Failed to retrieve data for content type id ' + contentTypeId);
},
/**
* @ngdoc method
* @name umbraco.resources.contentTypeResource#getWhereCompositionIsUsedInContentTypes
* @methodOf umbraco.resources.contentTypeResource
*
* @description
* Returns a list of content types which use a specific composition with a given id
*
* ##usage
* <pre>
* contentTypeResource.getWhereCompositionIsUsedInContentTypes(1234)
* .then(function(contentTypeList) {
* console.log(contentTypeList);
* });
* </pre>
* @param {Int} contentTypeId id of the composition content type to retrieve the list of the content types where it has been used
* @returns {Promise} resourcePromise object.
*
*/
getWhereCompositionIsUsedInContentTypes: function (contentTypeId) {
var query = {
contentTypeId: contentTypeId
};
return umbRequestHelper.resourcePromise(
$http.post(
umbRequestHelper.getApiUrl(
"contentTypeApiBaseUrl",
"GetWhereCompositionIsUsedInContentTypes"),
query),
'Failed to retrieve data for content type id ' + contentTypeId);
},
/**
* @ngdoc method
@@ -0,0 +1,162 @@
/**
* @ngdoc service
* @name umbraco.resources.dictionaryResource
* @description Loads in data for dictionary items
**/
function dictionaryResource($q, $http, $location, umbRequestHelper, umbDataFormatter) {
/**
* @ngdoc method
* @name umbraco.resources.dictionaryResource#deleteById
* @methodOf umbraco.resources.dictionaryResource
*
* @description
* Deletes a dictionary item with a given id
*
* ##usage
* <pre>
* dictionaryResource.deleteById(1234)
* .then(function() {
* alert('its gone!');
* });
* </pre>
*
* @param {Int} id id of dictionary item to delete
* @returns {Promise} resourcePromise object.
*
**/
function deleteById(id) {
return umbRequestHelper.resourcePromise(
$http.post(
umbRequestHelper.getApiUrl(
"dictionaryApiBaseUrl",
"DeleteById",
[{ id: id }])),
"Failed to delete item " + id);
}
/**
* @ngdoc method
* @name umbraco.resources.dictionaryResource#create
* @methodOf umbraco.resources.dictionaryResource
*
* @description
* Creates a dictionary item with the gieven key and parent id
*
* ##usage
* <pre>
* dictionaryResource.create(1234,"Item key")
* .then(function() {
* alert('its created!');
* });
* </pre>
*
* @param {Int} parentid the parentid of the new dictionary item
* @param {String} key the key of the new dictionary item
* @returns {Promise} resourcePromise object.
*
**/
function create(parentid, key) {
return umbRequestHelper.resourcePromise(
$http.post(
umbRequestHelper.getApiUrl(
"dictionaryApiBaseUrl",
"Create",
{ parentId: parentid, key : key })),
"Failed to create item ");
}
/**
* @ngdoc method
* @name umbraco.resources.dictionaryResource#deleteById
* @methodOf umbraco.resources.dictionaryResource
*
* @description
* Gets a dictionary item with a given id
*
* ##usage
* <pre>
* dictionaryResource.getById(1234)
* .then(function() {
* alert('Found it!');
* });
* </pre>
*
* @param {Int} id id of dictionary item to get
* @returns {Promise} resourcePromise object.
*
**/
function getById(id) {
return umbRequestHelper.resourcePromise(
$http.get(
umbRequestHelper.getApiUrl(
"dictionaryApiBaseUrl",
"GetById",
[{ id: id }])),
"Failed to get item " + id);
}
/**
* @ngdoc method
* @name umbraco.resources.dictionaryResource#save
* @methodOf umbraco.resources.dictionaryResource
*
* @description
* Updates a dictionary
*
* @param {Object} dictionary dictionary object to update
* @param {Bool} nameIsDirty set to true if the name has been changed
* @returns {Promise} resourcePromise object.
*
*/
function save(dictionary, nameIsDirty) {
var saveModel = umbDataFormatter.formatDictionaryPostData(dictionary, nameIsDirty);
return umbRequestHelper.resourcePromise(
$http.post(umbRequestHelper.getApiUrl("dictionaryApiBaseUrl", "PostSave"), saveModel),
"Failed to save data for dictionary id " + dictionary.id);
}
/**
* @ngdoc method
* @name umbraco.resources.dictionaryResource#getList
* @methodOf umbraco.resources.dictionaryResource
*
* @description
* Gets a list of all dictionary items
*
* ##usage
* <pre>
* dictionaryResource.getList()
* .then(function() {
* alert('Found it!');
* });
* </pre>
*
* @returns {Promise} resourcePromise object.
*
**/
function getList() {
return umbRequestHelper.resourcePromise(
$http.get(
umbRequestHelper.getApiUrl(
"dictionaryApiBaseUrl",
"getList")),
"Failed to get list");
}
var resource = {
deleteById: deleteById,
create: create,
getById: getById,
save: save,
getList : getList
};
return resource;
}
angular.module("umbraco.resources").factory("dictionaryResource", dictionaryResource);
@@ -38,7 +38,38 @@ function mediaTypeResource($q, $http, umbRequestHelper, umbDataFormatter) {
query),
'Failed to retrieve data for content type id ' + contentTypeId);
},
/**
* @ngdoc method
* @name umbraco.resources.mediaTypeResource#getWhereCompositionIsUsedInContentTypes
* @methodOf umbraco.resources.mediaTypeResource
*
* @description
* Returns a list of media types which use a specific composition with a given id
*
* ##usage
* <pre>
* mediaTypeResource.getWhereCompositionIsUsedInContentTypes(1234)
* .then(function(mediaTypeList) {
* console.log(mediaTypeList);
* });
* </pre>
* @param {Int} contentTypeId id of the composition content type to retrieve the list of the media types where it has been used
* @returns {Promise} resourcePromise object.
*
*/
getWhereCompositionIsUsedInContentTypes: function (contentTypeId) {
var query = {
contentTypeId: contentTypeId
};
return umbRequestHelper.resourcePromise(
$http.post(
umbRequestHelper.getApiUrl(
"mediaTypeApiBaseUrl",
"GetWhereCompositionIsUsedInContentTypes"),
query),
'Failed to retrieve data for content type id ' + contentTypeId);
},
/**
* @ngdoc method
* @name umbraco.resources.mediaTypeResource#getAllowedTypes
@@ -166,7 +166,13 @@ function iconHelper($q, $timeout) {
var c = ".icon-";
for (var i = document.styleSheets.length - 1; i >= 0; i--) {
var classes = document.styleSheets[i].rules || document.styleSheets[i].cssRules;
var classes = null;
try {
classes = document.styleSheets[i].rules || document.styleSheets[i].cssRules;
} catch (e) {
console.warn("Can't read the css rules of: " + document.styleSheets[i].href, e);
continue;
}
if (classes !== null) {
for(var x=0;x<classes.length;x++) {
@@ -224,4 +230,4 @@ function iconHelper($q, $timeout) {
}
};
}
angular.module('umbraco.services').factory('iconHelper', iconHelper);
angular.module('umbraco.services').factory('iconHelper', iconHelper);
@@ -99,6 +99,28 @@
return saveModel;
},
/** formats the display model used to display the dictionary to the model used to save the dictionary */
formatDictionaryPostData : function(dictionary, nameIsDirty) {
var saveModel = {
parentId: dictionary.parentId,
id: dictionary.id,
name: dictionary.name,
nameIsDirty: nameIsDirty,
translations: [],
key : dictionary.key
};
for(var i = 0; i < dictionary.translations.length; i++) {
saveModel.translations.push({
isoCode: dictionary.translations[i].isoCode,
languageId: dictionary.translations[i].languageId,
translation: dictionary.translations[i].translation
});
}
return saveModel;
},
/** formats the display model used to display the user to the model used to save the user */
formatUserPostData: function (displayModel) {
@@ -29,9 +29,9 @@ angular.module("umbraco.install").factory('installerService', function($rootScop
"There's a pretty big chance, you've visited a website powered by Umbraco today",
"'Umbraco-spotting' is the game of spotting big brands running Umbraco",
"At least 4 people have the Umbraco logo tattooed on them",
"'Umbraco' is the danish name for an allen key",
"'Umbraco' is the Danish name for an allen key",
"Umbraco has been around since 2005, that's a looong time in IT",
"More than 600 people from all over the world meet each year in Denmark in June for our annual conference <a target='_blank' href='https://umbra.co/codegarden'>CodeGarden</a>",
"More than 600 people from all over the world meet each year in Denmark in May for our annual conference <a target='_blank' href='https://umbra.co/codegarden'>CodeGarden</a>",
"While you are installing Umbraco someone else on the other side of the planet is probably doing it too",
"You can extend Umbraco without modifying the source code using either JavaScript or C#",
"Umbraco has been installed in more than 198 countries"
@@ -32,7 +32,6 @@
ng-pattern="passwordPattern"
autocorrect="off"
autocapitalize="off"
autocomplete="off"
required
ng-model="installer.current.model.password" id="password" />
<small class="inline-help">At least {{installer.current.model.minCharLength}} characters long</small>
@@ -176,6 +176,7 @@
@import "hacks.less";
@import "healthcheck.less";
@import "getstarted.less";
// cleanup properties.less when it is done
@import "properties.less";
@@ -13,6 +13,7 @@
border-radius: 0 10px 10px 10px;
padding: 10px 10px 5px 10px;
box-sizing: border-box;
position:relative;
}
.umb-group-builder__group.-active {
@@ -0,0 +1,88 @@
.umb-getstarted {
display: flex;
flex-wrap: wrap;
margin-left: -10px;
margin-right: -10px;
}
.umb-getstartedcards {
display: flex;
flex-wrap: wrap;
margin: 0 auto;
max-width: 100%;
@media (min-width: 500px) {
margin: 0 -10px;
}
}
.umb-getstartedcard {
width: 100%;
padding: 0.5em;
text-align: center;
display: flex;
align-items: center;
border: 1px solid #d8d7d9;
background-color: #fff;
margin: 0 0 0.5em;
@media (min-width: 500px) {
display: block;
align-items: unset;
padding: 1em 1em 0 1em;
margin: 0 10px 20px;
width: auto;
flex-basis: 35%;
max-width: 35%;
}
@media (min-width: 768px) {
width: auto;
flex-basis: 14%;
max-width: 14%;
}
@media (min-width: 1930px) {
width: auto;
flex-basis: 7%;
max-width: 7%;
}
}
.umb-getstartedcard img {
height: 3em;
max-width: 100%;
@media (min-width: 500px) {
height: auto;
}
}
.umb-getstartedcards {
margin: 0 auto;
max-width: 100%;
}
.umb-getstartedbody {
font-weight: bold;
margin: 0.5em;
@media (min-width: 500px) {
padding: 10px;
margin: auto;
}
}
.umb-getstartedbody p {
margin: 0;
@media (min-width: 500px) {
margin: inherit;
}
}
.umb-getstartedcard:hover {
border: 1px solid @turquoise;
cursor: pointer;
}
@@ -182,6 +182,14 @@ h5.-black {
margin-left: 0;
}
label[for=""] {
cursor: default;
}
label:not([for]) {
cursor: default;
}
/* CONTROL VALIDATION */
.umb-control-required {
color: @controlRequiredColor;
@@ -22,7 +22,7 @@
<localize key="user_newPassword">New password</localize>
<small style="font-size: 13px;">{{invitedUserPasswordModel.passwordPolicyText}}</small>
</label>
<input type="password" ng-model="invitedUserPasswordModel.password" name="password" class="-full-width-input" umb-auto-focus required val-server-field="value" autocomplete="off" ng-minlength="{{invitedUserPasswordModel.passwordPolicies.minPasswordLength}}" />
<input type="password" ng-model="invitedUserPasswordModel.password" name="password" class="-full-width-input" umb-auto-focus required val-server-field="value" ng-minlength="{{invitedUserPasswordModel.passwordPolicies.minPasswordLength}}" />
<span class="help-inline" val-msg-for="password" val-toggle-msg="required"><localize key="user_passwordIsBlank">Your new password cannot be blank!</localize></span>
<span class="help-inline" val-msg-for="password" val-toggle-msg="minlength">Minimum {{invitedUserPasswordModel.passwordPolicies.minPasswordLength}} characters</span>
<span class="help-inline" val-msg-for="password" val-toggle-msg="valServerField"></span>
@@ -30,7 +30,7 @@
<div class="control-group" ng-class="{error: setPasswordForm.confirmPassword.$invalid}">
<label><localize key="user_confirmNewPassword">Confirm new password</localize></label>
<input type="password" ng-model="invitedUserPasswordModel.confirmPassword" name="confirmPassword" class="-full-width-input" required val-compare="password" autocomplete="off" />
<input type="password" ng-model="invitedUserPasswordModel.confirmPassword" name="confirmPassword" class="-full-width-input" required val-compare="password" />
<span class="help-inline" val-msg-for="confirmPassword" val-toggle-msg="required"><localize key="general_required">Required</localize></span>
<span class="help-inline" val-msg-for="confirmPassword" val-toggle-msg="valCompare"><localize key="user_passwordMismatch">The confirmed password doesn't match the new password!</localize></span>
</div>
@@ -150,7 +150,7 @@
<div class="control-group" ng-class="{error: loginForm.password.$invalid}">
<label><localize key="general_password">Password</localize></label>
<div class="password-toggle">
<input type="password" ng-model="password" name="password" class="-full-width-input" localize="placeholder" placeholder="@placeholders_password" autocomplete="off" /><a ng-click="togglePassword()">Toggle</a>
<input type="password" ng-model="password" name="password" class="-full-width-input" localize="placeholder" placeholder="@placeholders_password" /><a ng-click="togglePassword()">Toggle</a>
</div>
</div>
@@ -1,17 +1,23 @@
(function() {
"use strict";
function CompositionsOverlay($scope) {
function CompositionsOverlay($scope,$location) {
var vm = this;
vm.isSelected = isSelected;
vm.openContentType = openContentType;
function isSelected(alias) {
if($scope.model.contentType.compositeContentTypes.indexOf(alias) !== -1) {
return true;
}
}
function openContentType(contentType, section) {
var url = (section === "documentType" ? "/settings/documenttypes/edit/" : "/settings/mediaTypes/edit/") + contentType.id;
$location.path(url);
}
}
angular.module("umbraco").controller("Umbraco.Overlays.CompositionsOverlay", CompositionsOverlay);
@@ -22,11 +22,16 @@
position="center">
<localize key="contentTypeEditor_noAvailableCompositions"></localize>
</umb-empty-state>
<umb-empty-state ng-if="model.availableCompositeContentTypes.length === 0 && model.totalContentTypes > 1"
position="center">
<umb-empty-state ng-if="model.availableCompositeContentTypes.length === 0 && model.totalContentTypes > 1">
<localize key="contentTypeEditor_compositionInUse"></localize>
</umb-empty-state>
<div ng-if="model.availableCompositeContentTypes.length === 0 && model.totalContentTypes > 1 && model.whereCompositionUsed.length > 0">
<h5><localize key="contentTypeEditor_compositionUsageHeading"></localize></h5>
<p><localize key="contentTypeEditor_compositionUsageSpecification"></localize></p>
<ul class="umb-checkbox-list">
<li class="umb-checkbox-list__item" ng-repeat="contentTypeEntity in model.whereCompositionUsed"><a ng-click="vm.openContentType(contentTypeEntity.contentType, model.section)"><i class="{{contentTypeEntity.contentType.icon}}"></i>&nbsp;{{contentTypeEntity.contentType.name}}</a></li>
</ul>
</div>
<ul class="umb-checkbox-list">
<li class="umb-checkbox-list__item"
ng-repeat="compositeContentType in model.availableCompositeContentTypes | filter:searchTerm"
@@ -50,4 +55,4 @@
</li>
</ul>
</div>
</div>
@@ -154,14 +154,15 @@ angular.module("umbraco")
});
});
mediaTypeHelper.getAllowedImagetypes(folder.id)
.then(function(types) {
$scope.acceptedMediatypes = types;
});
} else {
$scope.path = [];
}
mediaTypeHelper.getAllowedImagetypes(folder.id)
.then(function (types) {
$scope.acceptedMediatypes = types;
});
$scope.lockedFolder = folder.id === -1 && $scope.model.startNodeIsVirtual;
$scope.currentFolder = folder;
@@ -317,20 +318,25 @@ angular.module("umbraco")
mediaItem.thumbnail = mediaHelper.resolveFileFromEntity(mediaItem, true);
mediaItem.image = mediaHelper.resolveFileFromEntity(mediaItem, false);
// set properties to match a media object
if (mediaItem.metaData &&
mediaItem.metaData.umbracoWidth &&
mediaItem.metaData.umbracoHeight) {
mediaItem.properties = [
{
mediaItem.properties = [];
if (mediaItem.metaData) {
if (mediaItem.metaData.umbracoWidth && mediaItem.metaData.umbracoHeight) {
mediaItem.properties.push({
alias: "umbracoWidth",
value: mediaItem.metaData.umbracoWidth.Value
},
{
});
mediaItem.properties.push({
alias: "umbracoHeight",
value: mediaItem.metaData.umbracoHeight.Value
}
];
});
}
if (mediaItem.metaData.umbracoFile) {
mediaItem.properties.push({
alias: "umbracoFile",
editor: mediaItem.metaData.umbracoFile.PropertyEditorAlias,
value: mediaItem.metaData.umbracoFile.Value
});
}
}
});
// update images
@@ -385,4 +391,4 @@ angular.module("umbraco")
onInit();
});
});
@@ -27,7 +27,8 @@
<umb-button type="button"
label-key="general_upload"
action="upload()"
disabled="lockedFolder">
disabled="lockedFolder"
ng-if="acceptedMediatypes.length > 0">
</umb-button>
</div>
@@ -1,15 +1,15 @@
<div class="umb-button" ng-class="{'umb-button--block': blockElement}" data-element="{{ alias ? 'button-' + alias : '' }}">
<div class="icon-check umb-button__success" ng-class="{'-hidden': state !== 'success', '-white': style}"></div>
<div class="icon-check umb-button__success" ng-class="{'-hidden': innerState !== 'success', '-white': style}"></div>
<div class="icon-delete umb-button__error" ng-class="{'-hidden': state !== 'error', '-white': style}"></div>
<div class="icon-delete umb-button__error" ng-class="{'-hidden': innerState !== 'error', '-white': style}"></div>
<div class="umb-button__progress" ng-class="{'-hidden': state !== 'busy', '-white': style}"></div>
<div class="umb-button__progress" ng-class="{'-hidden': innerState !== 'busy', '-white': style}"></div>
<div ng-if="state !== 'init'" class="umb-button__overlay"></div>
<div ng-if="innerState !== 'init'" class="umb-button__overlay"></div>
<a ng-if="type === 'link'" href="{{href}}" class="btn umb-button__button {{style}} umb-button--{{size}}" ng-click="action(model)" hotkey="{{shortcut}}" hotkey-when-hidden="{{shortcutWhenHidden}}">
<span class="umb-button__content" ng-class="{'-hidden': state !== 'init'}">
<span class="umb-button__content" ng-class="{'-hidden': innerState !== 'init'}">
<i ng-if="icon" class="{{icon}} umb-button__icon"></i>
<localize ng-if="labelKey" key="{{labelKey}}">{{label}}</localize>
<span ng-if="!labelKey">{{label}}</span>
@@ -17,7 +17,7 @@
</a>
<button ng-if="type === 'button'" type="button" class="btn umb-button__button {{style}} umb-button--{{size}}" ng-click="action(model)" hotkey="{{shortcut}}" hotkey-when-hidden="{{shortcutWhenHidden}}" ng-disabled="disabled">
<span class="umb-button__content" ng-class="{'-hidden': state !== 'init'}">
<span class="umb-button__content" ng-class="{'-hidden': innerState !== 'init'}">
<i ng-if="icon" class="{{icon}} umb-button__icon"></i>
<localize ng-if="labelKey" key="{{labelKey}}">{{label}}</localize>
<span ng-if="!labelKey">{{label}}</span>
@@ -25,7 +25,7 @@
</button>
<button ng-if="type === 'submit'" type="submit" class="btn umb-button__button {{style}} umb-button--{{size}}" hotkey="{{shortcut}}" hotkey-when-hidden="{{shortcutWhenHidden}}" ng-disabled="disabled">
<span class="umb-button__content" ng-class="{'-hidden': state !== 'init'}">
<span class="umb-button__content" ng-class="{'-hidden': innerState !== 'init'}">
<i ng-if="icon" class="{{icon}} umb-button__icon"></i>
<localize ng-if="labelKey" key="{{labelKey}}">{{label}}</localize>
<span ng-if="!labelKey">{{label}}</span>
@@ -180,6 +180,7 @@
<umb-node-preview style="max-width: 100%; margin-bottom: 0;"
icon="documentType.icon"
name="documentType.name"
alias="documentType.alias"
allow-open="allowOpen"
on-open="openDocumentType(documentType)">
</umb-node-preview>
@@ -11,4 +11,4 @@
<div class="controls controls-row" ng-transclude></div>
</div>
</div>
</div>
</div>
@@ -3,8 +3,8 @@
<div class="umb-pane btn-toolbar umb-btn-toolbar">
<div class="control-group umb-control-group">
<a href class="btn btn-link" ng-click="onCancel()"><localize key="general_cancel">Cancel</localize></a>
<a href class="btn btn-primary" ng-click="onConfirm()"><localize key="general_ok">Ok</localize></a>
<a ng-if="showCancel" href class="btn btn-link" ng-click="onCancel()"><localize key="general_cancel">Cancel</localize></a>
<a ng-if="showConfirm" href class="btn btn-primary" ng-click="onConfirm()"><localize key="general_ok">Ok</localize></a>
</div>
</div>
</div>
</div>
@@ -2,7 +2,7 @@
<i ng-if="icon" class="umb-node-preview__icon {{ icon }}"></i>
<div class="umb-node-preview__content">
<div class="umb-node-preview__name">{{ name }}</div>
<div class="umb-node-preview__name" ng-attr-title="{{alias}}">{{ name }}</div>
<div class="umb-node-preview__description" ng-if="description">{{ description }}</div>
<div class="umb-user-group-preview__permission" ng-if="permissions">
@@ -28,8 +28,7 @@
class="input-block-level umb-textstring textstring"
required
val-server-field="oldPassword"
no-dirty-check
autocomplete="off" />
no-dirty-check />
<span class="help-inline" val-msg-for="oldPassword" val-toggle-msg="required">Required</span>
<span class="help-inline" val-msg-for="oldPassword" val-toggle-msg="valServerField"></span>
</umb-control-group>
@@ -40,8 +39,7 @@
required
val-server-field="password"
ng-minlength="{{$parent.config.minPasswordLength}}"
no-dirty-check
autocomplete="off" />
no-dirty-check />
<span class="help-inline" val-msg-for="password" val-toggle-msg="required">Required</span>
<span class="help-inline" val-msg-for="password" val-toggle-msg="minlength">Minimum {{$parent.config.minPasswordLength}} characters</span>
<span class="help-inline" val-msg-for="password" val-toggle-msg="valServerField"></span>
@@ -51,8 +49,7 @@
<input type="password" name="confirmpassword" ng-model="$parent.passwordValues.confirm"
class="input-block-level umb-textstring textstring"
val-compare="password"
no-dirty-check
autocomplete="off" />
no-dirty-check />
<span class="help-inline" val-msg-for="confirmpassword" val-toggle-msg="valCompare">
<localize key="user_passwordMismatch">The confirmed password doesn't match the new password!</localize>
@@ -1,18 +1,15 @@
<h3>Hours of Umbraco training videos are only a click away</h3>
<p>Want to master Umbraco? Spend a couple of minutes learning some best practices by watching one of these videos about using Umbraco, then visit <a class="btn-link -underline" href="http://umbraco.tv" target="_blank">umbraco.tv</a> for even more Umbraco videos.</p>
<div class="row-fluid"
ng-init="init('http://umbraco.tv/videos/developer/chapterrss?sort=no')"
ng-controller="Umbraco.Dashboard.StartupVideosController">
<ul class="thumbnails" >
<li class="span2" ng-repeat="video in videos">
<a class="btn-link" target="_blank" href="{{video.link}}" title="{{video.title}}">
<div class="thumbnail" style="margin-right: 20px; padding: 20px;">
<img ng-src="{{video.thumbnail}}" alt="{{video.title}}">
<div style="font-weight: bold; text-align: center; margin: 20px 0 0;">{{video.title}}</div>
</div>
</a>
</li>
</ul>
</div>
<h3>Hours of Umbraco training videos are only a click away</h3>
<p>Want to master Umbraco? Spend a couple of minutes learning some best practices by watching one of these videos about using Umbraco, then visit <a class="btn-link -underline" href="http://umbraco.tv" target="_blank">umbraco.tv</a> for even more Umbraco videos.</p>
<div ng-init="init('http://umbraco.tv/videos/developer/chapterrss?sort=no')"
ng-controller="Umbraco.Dashboard.StartupVideosController">
<div class="umb-getstartedcards">
<a class="umb-getstartedcard" ng-repeat="video in videos" href="{{video.link}}" title="{{video.title}}" target="_blank" rel="noopener">
<img ng-src="{{video.thumbnail}}" alt="{{video.title}}">
<div class="umb-getstartedbody">
<p>{{video.title}}</p>
</div>
</a>
</div>
</div>
@@ -31,7 +31,7 @@
</div>
<div class="umb-healthcheck-message" ng-if="group.totalWarning > 0">
<i class="icon-alert color-yellow"></i>
<i class="icon-alert color-orange"></i>
{{ group.totalWarning }}
</div>
@@ -50,8 +50,9 @@ function DataTypeEditController($scope, $routeParams, $location, appState, navig
$scope.preValues = [];
if ($routeParams.create) {
$scope.page.loading = true;
$scope.showIdentifier = false;
//we are creating so get an empty data type item
dataTypeResource.getScaffold($routeParams.id)
@@ -77,6 +78,8 @@ function DataTypeEditController($scope, $routeParams, $location, appState, navig
$scope.page.loading = true;
$scope.showIdentifier = true;
//we are editing so get the content item from the server
dataTypeResource.getById($routeParams.id)
.then(function(data) {
@@ -21,28 +21,31 @@
<umb-editor-container class="form-horizontal">
<umb-property property="properties.selectedEditor">
<div>
<select name="selectedEditor"
ng-model="content.selectedEditor"
required
ng-options="e.alias as e.name for e in content.availableEditors"></select>
<span class="help-inline" val-msg-for="selectedEditor" val-toggle-msg="required"><localize key="general_required">Required</localize></span>
</div>
<umb-control-group label="Id" ng-if="showIdentifier">
<div>{{content.id}}</div>
<small>{{content.key}}</small>
</umb-control-group>
</umb-property>
<umb-property property="properties.selectedEditor">
<div>
<select name="selectedEditor"
ng-model="content.selectedEditor"
required
ng-options="e.alias as e.name for e in content.availableEditors"></select>
<span class="help-inline" val-msg-for="selectedEditor" val-toggle-msg="required"><localize key="general_required">Required</localize></span>
</div>
<umb-property property="properties.selectedEditorId">
<div>{{content.selectedEditor}}</div>
</umb-property>
</umb-property>
<umb-property property="properties.selectedEditorId">
<div>{{content.selectedEditor}}</div>
</umb-property>
<umb-property
property="preValue"
ng-repeat="preValue in preValues">
<umb-property property="preValue"
ng-repeat="preValue in preValues">
<umb-editor model="preValue" is-pre-value="true"></umb-editor>
</umb-property>
<umb-editor model="preValue" is-pre-value="true"></umb-editor>
</umb-property>
</umb-editor-container>
@@ -0,0 +1,19 @@
<div ng-controller="Umbraco.Editors.Dictionary.CreateController as vm">
<div class="umb-pane">
<h5><localize key="create_createUnder">Create an item under</localize> {{currentNode.name}}</h5>
</div>
<div class="umb-pane">
<form name="createDictionaryForm"
ng-submit="vm.createItem()"
val-form-manager>
<umb-control-group label="Enter a item-name" hide-label="true">
<input type="text" name="itemKey" ng-model="vm.itemKey" class="umb-textstring textstring input-block-level" required />
</umb-control-group>
<button type="submit" class="btn btn-primary"><localize key="general_create">Create</localize></button>
</form>
</div>
</div>
@@ -0,0 +1,12 @@
<div class="umb-dialog umb-pane" ng-controller="Umbraco.Editors.Dictionary.DeleteController as vm" >
<div class="umb-dialog-body" auto-scale="90">
<p class="umb-abstract">
<localize key="defaultdialogs_confirmdelete">Are you sure you want to delete</localize> <strong>{{currentNode.name}}</strong> ?
</p>
<umb-confirm on-confirm="vm.performDelete" on-cancel="vm.cancel">
</umb-confirm>
</div>
</div>
@@ -0,0 +1,44 @@
/**
* @ngdoc controller
* @name Umbraco.Editors.Dictionary.CreateController
* @function
*
* @description
* The controller for creating dictionary items
*/
function DictionaryCreateController($scope, $location, dictionaryResource, navigationService, notificationsService, formHelper, appState) {
var vm = this;
vm.itemKey = "";
function createItem() {
var node = $scope.dialogOptions.currentNode;
dictionaryResource.create(node.id, vm.itemKey).then(function (data) {
navigationService.hideMenu();
// set new item as active in tree
var currPath = node.path ? node.path : "-1";
navigationService.syncTree({ tree: "dictionary", path: currPath + "," + data, forceReload: true, activate: true });
// reset form state
formHelper.resetForm({ scope: $scope });
// navigate to edit view
var currentSection = appState.getSectionState("currentSection");
$location.path("/" + currentSection + "/dictionary/edit/" + data);
}, function (err) {
if (err.data && err.data.message) {
notificationsService.error(err.data.message);
navigationService.hideMenu();
}
});
}
vm.createItem = createItem;
}
angular.module("umbraco").controller("Umbraco.Editors.Dictionary.CreateController", DictionaryCreateController);
@@ -0,0 +1,50 @@
/**
* @ngdoc controller
* @name Umbraco.Editors.Dictionary.DeleteController
* @function
*
* @description
* The controller for deleting dictionary items
*/
function DictionaryDeleteController($scope, $location, dictionaryResource, treeService, navigationService, appState) {
var vm = this;
function cancel() {
navigationService.hideDialog();
}
function performDelete() {
// stop from firing again on double-click
if ($scope.busy) { return false; }
//mark it for deletion (used in the UI)
$scope.currentNode.loading = true;
$scope.busy = true;
dictionaryResource.deleteById($scope.currentNode.id).then(function () {
$scope.currentNode.loading = false;
// get the parent id
var parentId = $scope.currentNode.parentId;
treeService.removeNode($scope.currentNode);
navigationService.hideMenu();
var currentSection = appState.getSectionState("currentSection");
if (parentId !== "-1") {
// set the view of the parent item
$location.path("/" + currentSection + "/dictionary/edit/" + parentId);
} else {
// we have no parent, so redirect to section
$location.path("/" + currentSection + "/");
}
});
}
vm.cancel = cancel;
vm.performDelete = performDelete;
}
angular.module("umbraco").controller("Umbraco.Editors.Dictionary.DeleteController", DictionaryDeleteController);
@@ -0,0 +1,115 @@
/**
* @ngdoc controller
* @name Umbraco.Editors.Dictionary.EditController
* @function
*
* @description
* The controller for editing dictionary items
*/
function DictionaryEditController($scope, $routeParams, dictionaryResource, treeService, navigationService, appState, editorState, contentEditingHelper, formHelper, notificationsService, localizationService) {
var vm = this;
//setup scope vars
vm.nameDirty = false;
vm.page = {};
vm.page.loading = false;
vm.page.nameLocked = false;
vm.page.menu = {};
vm.page.menu.currentSection = appState.getSectionState("currentSection");
vm.page.menu.currentNode = null;
vm.description = "";
function loadDictionary() {
vm.page.loading = true;
//we are editing so get the content item from the server
dictionaryResource.getById($routeParams.id)
.then(function (data) {
bindDictionary(data);
vm.page.loading = false;
});
}
function createTranslationProperty(translation) {
return {
alias: translation.isoCode,
label: translation.displayName,
hideLabel : false
}
}
function bindDictionary(data) {
localizationService.localize("dictionaryItem_description").then(function (value) {
vm.description = value.replace("%0%", data.name);
});
// create data for umb-property displaying
for (var i = 0; i < data.translations.length; i++) {
data.translations[i].property = createTranslationProperty(data.translations[i]);
}
contentEditingHelper.handleSuccessfulSave({
scope: $scope,
savedContent: data
});
// set content
vm.content = data;
//share state
editorState.set(vm.content);
navigationService.syncTree({ tree: "dictionary", path: data.path, forceReload: true }).then(function (syncArgs) {
vm.page.menu.currentNode = syncArgs.node;
});
}
function onInit() {
loadDictionary();
}
function saveDictionary() {
if (formHelper.submitForm({ scope: $scope, statusMessage: "Saving..." })) {
vm.page.saveButtonState = "busy";
dictionaryResource.save(vm.content, vm.nameDirty)
.then(function (data) {
formHelper.resetForm({ scope: $scope, notifications: data.notifications });
bindDictionary(data);
vm.page.saveButtonState = "success";
},
function (err) {
contentEditingHelper.handleSaveError({
redirectOnFailure: false,
err: err
});
notificationsService.error(err.data.message);
vm.page.saveButtonState = "error";
});
}
}
vm.save = saveDictionary;
$scope.$watch("vm.content.name", function (newVal, oldVal) {
//when the value changes, we need to set the name dirty
if (newVal && (newVal !== oldVal) && typeof(oldVal) !== "undefined") {
vm.nameDirty = true;
}
});
onInit();
}
angular.module("umbraco").controller("Umbraco.Editors.Dictionary.EditController", DictionaryEditController);
@@ -0,0 +1,47 @@
/**
* @ngdoc controller
* @name Umbraco.Editors.Dictionary.ListController
* @function
*
* @description
* The controller for listting dictionary items
*/
function DictionaryListController($scope, $location, dictionaryResource, localizationService, appState) {
var vm = this;
vm.title = "Dictionary overview";
vm.loading = false;
vm.items = [];
function loadList() {
vm.loading = true;
dictionaryResource.getList()
.then(function (data) {
vm.items = data;
vm.loading = false;
});
}
function clickItem(id) {
var currentSection = appState.getSectionState("currentSection");
$location.path("/" + currentSection + "/dictionary/edit/" + id);
}
vm.clickItem = clickItem;
function onInit() {
localizationService.localize("dictionaryItem_overviewTitle").then(function (value) {
vm.title = value;
});
loadList();
}
onInit();
}
angular.module("umbraco").controller("Umbraco.Editors.Dictionary.ListController", DictionaryListController);
@@ -0,0 +1,43 @@
<div ng-controller="Umbraco.Editors.Dictionary.EditController as vm">
<umb-load-indicator ng-if="vm.page.loading"></umb-load-indicator>
<form name="contentForm"
ng-submit="vm.save()"
novalidate
val-form-manager>
<umb-editor-view ng-if="!vm.page.loading">
<umb-editor-header
menu="vm.page.menu"
name="vm.content.name"
name-locked="vm.page.nameLocked"
hide-icon="true"
hide-description="true"
hide-alias="true">
</umb-editor-header>
<umb-editor-container class="form-horizontal">
<p ng-bind-html="vm.description"></p>
<umb-property ng-repeat="translation in vm.content.translations" property="translation.property">
<textarea ng-model="translation.translation"></textarea>
</umb-property>
</umb-editor-container>
<umb-editor-footer>
<umb-editor-footer-content-right>
<umb-button
type="submit"
button-style="success"
state="vm.page.saveButtonState"
shortcut="ctrl+s"
label="Save"
label-key="buttons_save">
</umb-button>
</umb-editor-footer-content-right>
</umb-editor-footer>
</umb-editor-view>
</form>
</div>
@@ -0,0 +1,46 @@
<div ng-controller="Umbraco.Editors.Dictionary.ListController as vm">
<umb-load-indicator ng-if="vm.loading">
</umb-load-indicator>
<umb-editor-view ng-if="!vm.loading">
<umb-editor-header
name="vm.title"
hide-alias="true"
hide-description="true"
hide-icon="true"
name-locked="true">
</umb-editor-header>
<umb-editor-container>
<div>
<div class="umb-table" ng-if="vm.items">
<div class="umb-table-head">
<div class="umb-table-row">
<div class="umb-table-cell umb-table__name not-fixed">
<span><localize key="general_name">Name</localize></span>
</div>
<div class="umb-table-cell" ng-repeat="column in vm.items[0].translations">
<span ng-bind="column.displayName"></span>
</div>
</div>
</div>
</div>
<div class="umb-table-body">
<div class="umb-table-row"
ng-repeat="item in vm.items">
<div class="umb-table-cell umb-table__name not-fixed">
<a title="{{ item.name }}" class="umb-table-body__link" prevent-default
ng-click="vm.clickItem(item.id)"
ng-bind="item.name" style="padding-left:{{item.level*10}}px">
</a>
</div>
<div class="umb-table-cell" ng-repeat="column in item.translations">
<i class="{{column.hasTranslation ? 'icon-check color-green' : 'icon-alert color-red'}}"></i>
</div>
</div>
</div>
</div>
</umb-editor-container>
</umb-editor-view>
</div>
@@ -1,4 +1,30 @@
angular.module("umbraco").controller("Umbraco.PrevalueEditors.BooleanController",
function ($scope) {
$scope.htmlId = "bool-" + String.CreateGuid();
function updateToggleValue() {
$scope.toggleValue = false;
if ($scope.model && $scope.model.value && ($scope.model.value.toString() === "1" || angular.lowercase($scope.model.value) === "true")) {
$scope.toggleValue = true;
}
}
if($scope.model.value === null){
$scope.model.value = "0";
}
updateToggleValue();
$scope.toggle = function(){
if($scope.model.value === 1 || $scope.model.value === "1"){
$scope.model.value = "0";
updateToggleValue();
return;
}
$scope.model.value = "1";
updateToggleValue();
}
});
@@ -1,4 +1,6 @@
<label ng-controller="Umbraco.PrevalueEditors.BooleanController" for="{{htmlId}}" class="checkbox">
<input name="boolean" type="checkbox" ng-model="model.value" ng-true-value="1" ng-false-value="0" id="{{htmlId}}" />
<localize key="general_yes">Yes</localize>
</label>
<div ng-controller="Umbraco.PrevalueEditors.BooleanController">
<umb-toggle
checked="toggleValue"
on-click="toggle()">
</umb-toggle>
</div>
@@ -4,7 +4,7 @@ function booleanEditorController($scope, $rootScope, assetsService) {
$scope.renderModel = {
value: false
};
if ($scope.model.config && $scope.model.config.default && $scope.model.config.default.toString() === "1" && $scope.model && !$scope.model.value) {
$scope.renderModel.value = true;
}
@@ -16,9 +16,9 @@ function booleanEditorController($scope, $rootScope, assetsService) {
setupViewModel();
$scope.$watch("renderModel.value", function (newVal) {
$scope.model.value = newVal === true ? "1" : "0";
});
if( $scope.model && !$scope.model.value ) {
$scope.model.value = ($scope.renderModel.value === true) ? '1' : '0';
}
//here we declare a special method which will be called whenever the value has changed from the server
//this is instead of doing a watch on the model.value = faster
@@ -27,5 +27,17 @@ function booleanEditorController($scope, $rootScope, assetsService) {
setupViewModel();
};
// Update the value when the toggle is clicked
$scope.toggle = function(){
if($scope.renderModel.value){
$scope.model.value = "0";
setupViewModel();
return;
}
$scope.model.value = "1";
setupViewModel();
};
}
angular.module("umbraco").controller("Umbraco.PropertyEditors.BooleanController", booleanEditorController);
@@ -1,3 +1,6 @@
<div class="umb-editor umb-boolean" ng-controller="Umbraco.PropertyEditors.BooleanController">
<input type="checkbox" ng-model="renderModel.value" id="{{model.alias}}" />
</div>
<umb-toggle
checked="renderModel.value"
on-click="toggle()">
</umb-toggle>
</div>
@@ -1,6 +1,21 @@
angular.module("umbraco")
.controller("Umbraco.PropertyEditors.GridController",
function ($scope, $http, assetsService, localizationService, $rootScope, dialogService, gridService, mediaResource, imageHelper, $timeout, umbRequestHelper, angularHelper) {
function (
$scope,
$http,
assetsService,
localizationService,
$rootScope,
dialogService,
gridService,
mediaResource,
imageHelper,
$timeout,
umbRequestHelper,
angularHelper,
$element,
eventsService
) {
// Grid status variables
var placeHolder = "";
@@ -335,6 +350,8 @@ angular.module("umbraco")
$scope.showRowConfigurations = false;
eventsService.emit("grid.rowAdded", { scope: $scope, element: $element, row: row });
};
$scope.removeRow = function (section, $index) {
@@ -584,6 +601,8 @@ angular.module("umbraco")
cell.controls.push(newControl);
eventsService.emit("grid.itemAdded", { scope: $scope, element: $element, cell: cell, item: newControl });
};
$scope.addTinyMce = function (cell) {
@@ -873,8 +892,13 @@ angular.module("umbraco")
// *********************************************
// Init grid
// *********************************************
eventsService.emit("grid.initializing", { scope: $scope, element: $element });
$scope.initContent();
eventsService.emit("grid.initialized", { scope: $scope, element: $element });
});
//Clean the grid value before submitting to the server, we don't need
@@ -75,7 +75,8 @@
'-active': row.active,
'-active-child': row.hasActiveChild}"
on-outside-click="clickOutsideRow($index, section.rows)"
bind-click-on="{{row.active}}">
bind-click-on="{{row.active}}"
data-rowid="{{row.$uniqueId}}">
<div class="umb-row-title-bar">
@@ -175,7 +176,8 @@
ng-class="{'-active': control.active}"
on-outside-click="clickOutsideControl($index, area.controls, area)"
bind-click-on="{{control.active}}"
umb-set-dirty-on-change="{{control.value}}">
umb-set-dirty-on-change="{{control.value}}"
data-itemid="{{control.$uniqueId}}">
<div class="umb-control-click-overlay" ng-show="!control.active && !sortMode"></div>
@@ -516,9 +516,13 @@
var availableMasterTemplates = [];
// filter out the current template and the selected master template
angular.forEach(vm.templates, function(template){
if(template.alias !== vm.template.alias && template.alias !== vm.template.masterTemplateAlias) {
availableMasterTemplates.push(template);
angular.forEach(vm.templates, function (template) {
if (template.alias !== vm.template.alias && template.alias !== vm.template.masterTemplateAlias) {
var templatePathArray = template.path.split(',');
// filter descendant templates of current template
if (templatePathArray.indexOf(String(vm.template.id)) === -1) {
availableMasterTemplates.push(template);
}
}
});
@@ -8,14 +8,16 @@
<umb-box-content class="block-form">
<umb-control-group label="@general_email" required="true">
<umb-control-group label="@general_email" required="true" alias="email">
<input type="email"
localize="placeholder"
placeholder="@placeholders_enteremail"
class="input-block-level"
ng-model="model.user.email"
umb-auto-focus name="email"
umb-auto-focus
name="email"
id="email"
val-email
required
val-server-field="Email" />
@@ -358,4 +360,4 @@
</div>
</div>
</div>
+6 -4
View File
@@ -49,6 +49,7 @@
<RestorePackages>true</RestorePackages>
<MvcProjectUpgradeChecked>true</MvcProjectUpgradeChecked>
<UseGlobalApplicationHostFile />
<Use64BitIISExpress />
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<OutputPath>bin\</OutputPath>
@@ -116,8 +117,8 @@
<HintPath>..\packages\AutoMapper.3.3.1\lib\net40\AutoMapper.Net4.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="ClientDependency.Core, Version=1.9.6.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\ClientDependency.1.9.6\lib\net45\ClientDependency.Core.dll</HintPath>
<Reference Include="ClientDependency.Core, Version=1.9.7.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\ClientDependency.1.9.7\lib\net45\ClientDependency.Core.dll</HintPath>
</Reference>
<Reference Include="ClientDependency.Core.Mvc, Version=1.8.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\ClientDependency-Mvc5.1.8.0.0\lib\net45\ClientDependency.Core.Mvc.dll</HintPath>
@@ -492,6 +493,7 @@
<Content Include="Umbraco\Config\Lang\tr.xml" />
<Content Include="Umbraco\Config\Lang\zh_tw.xml" />
<Content Include="Umbraco\create.aspx" />
<Content Include="Umbraco\Developer\Packages\installer.aspx" />
<Content Include="Umbraco\Logout.aspx" />
<Content Include="Umbraco\umbraco.aspx" />
<Content Include="Umbraco_Client\Application\JQuery\jquery.unobtrusive-ajax.min.js" />
@@ -1034,9 +1036,9 @@ xcopy "$(ProjectDir)"..\packages\SqlServerCE.4.0.0.1\x86\*.* "$(TargetDir)x86\"
<WebProjectProperties>
<UseIIS>True</UseIIS>
<AutoAssignPort>True</AutoAssignPort>
<DevelopmentServerPort>7110</DevelopmentServerPort>
<DevelopmentServerPort>7112</DevelopmentServerPort>
<DevelopmentServerVPath>/</DevelopmentServerVPath>
<IISUrl>http://localhost:7110</IISUrl>
<IISUrl>http://localhost:7112</IISUrl>
<NTLMAuthentication>False</NTLMAuthentication>
<UseCustomServer>False</UseCustomServer>
<CustomServerUrl>
@@ -10,6 +10,7 @@
<link href="../assets/css/canvasdesigner.css" type="text/css" rel="stylesheet" />
<link href="../lib/spectrum/spectrum.css" type="text/css" rel="stylesheet" />
<link href="../lib/jquery-ui/jquery-ui-1.10.4.custom.min.css" type="text/css" rel="stylesheet" />
<meta name="robots" content="noindex, nofollow">
</head>
<body id="canvasdesignerPanel" ng-mouseover="outlinePositionHide()" ng-class="{ leftOpen: (showStyleEditor || showPalettePicker) && !showDevicesPreview }" ng-controller="Umbraco.canvasdesignerController">
<div class="wait" ng-show="!frameLoaded"></div>
@@ -0,0 +1,10 @@
<%@ Page Language="c#" MasterPageFile="../../masterpages/umbracoPage.Master"
AutoEventWireup="True" Inherits="umbraco.presentation.developer.packages.Installer" Trace="false" ValidateRequest="false" %>
<%@ Register TagPrefix="cc1" Namespace="umbraco.uicontrols" Assembly="controls" %>
<asp:Content ContentPlaceHolderID="body" runat="server">
<cc1:UmbracoPanel ID="Panel1" Text="Install package" runat="server" Width="496px" Height="584px">
<cc1:Pane ID="pane_installing" runat="server" Visible="false" Text=""></cc1:Pane>
<cc1:Pane ID="pane_optional" runat="server" Visible="false" />
</cc1:UmbracoPanel>
</asp:Content>
@@ -1,4 +1,4 @@
[
[
{
"name": "Introduction",
"alias": "umbIntroIntroduction",
@@ -24,7 +24,7 @@
"element": "#applications",
"elementPreventClick": true,
"title": "Main Menu",
"content": "This is the main menu in Umbraco backoffice. Here you can navigate betweeen the different sections, see your user profile and open the help drawer",
"content": "This is the main menu in Umbraco backoffice. Here you can navigate between the different sections, see your user profile and open the help drawer.",
"backdropOpacity": 0.6
},
{
@@ -38,7 +38,7 @@
"element": "#tree",
"elementPreventClick": true,
"title": "The Tree",
"content": "<p>This is the <b>Tree</b> and is the main navigation inside a section.</p><p>In the Content section the tree is called the <b>Content tree</b> and here you can navigate the content of your website.</p>"
"content": "<p>This is the <b>Tree</b> and it is the main navigation inside a section.</p><p>In the Content section the tree is called the <b>Content tree</b> and here you can navigate the content of your website.</p>"
},
{
"element": "[data-element='editor-container']",
@@ -67,13 +67,13 @@
{
"element": "[data-element~='overlay-user'] [data-element='button-overlayClose']",
"title": "User profile",
"content": "Let's close the user profile again",
"content": "Let's close the user profile again.",
"event": "click"
},
{
"element": "#applications [data-element='section-help']",
"title": "Help",
"content": "If you ever find yourself in trouble click here to open the help drawer.",
"content": "If you ever find yourself in trouble click here to open the Help drawer.",
"event": "click",
"backdropOpacity": 0.6
},
@@ -108,7 +108,7 @@
"steps": [
{
"title": "Create your first Document Type",
"content": "<p>Step 1 of any site is to create a <strong>Document Type</strong>.<br> A Document Type is a template for content. For each <em>type</em> of content you want to create you'll create a Document Type. This will define were content based on this Document Type can be created, how many properties it holds and what the input method should be for these properties.</p><p>When you have at least one Document type in place you can start creating content and this content can the be used in a template.</p><p>In this tour you will learn how to set up a basic Document Type with a property to enter a short text.</p>",
"content": "<p>Step 1 of any site is to create a <strong>Document Type</strong>.<br> A Document Type is a template for content. For each <em>type</em> of content you want to create you'll create a Document Type. This will define where content based on this Document Type can be created, how many properties it holds and what the input method should be for these properties.</p><p>When you have at least one Document Type in place you can start creating content and this content can then be used in a template.</p><p>In this tour you will learn how to set up a basic Document Type with a property to enter a short text.</p>",
"type": "intro"
},
{
@@ -121,14 +121,14 @@
{
"element": "#tree [data-element='tree-item-documentTypes']",
"title": "Create Document Type",
"content": "<p>Hover the Document Type tree and click the <b>three small dots</b> to open the <b>context menu</b>.</p>",
"content": "<p>Hover over the Document Type tree and click the <b>three small dots</b> to open the <b>context menu</b>.</p>",
"event": "click",
"eventElement": "#tree [data-element='tree-item-documentTypes'] [data-element='tree-item-options']"
},
{
"element": "#dialog [data-element='action-documentType']",
"title": "Create Document Type",
"content": "<p>Click <b>Document Type</b> to create a new document type with a template. The template will be automatically created and set as the default template for this Document Type</p><p>You will use the template in a later tour render content.</p>",
"content": "<p>Click <b>Document Type</b> to create a new document type with a template. The template will be automatically created and set as the default template for this Document Type.</p><p>You will use the template in a later tour to render content.</p>",
"event": "click"
},
{
@@ -157,7 +157,7 @@
{
"element": "[data-element='property-add']",
"title": "Add a property",
"content": "<p>Properties are the different input fields on a content page.</p><p>On our Home Page we wan't to add a welcome text.</p><p>Click <b>Add property</b> to open the property dialog.</p>",
"content": "<p>Properties are the different input fields on a content page.</p><p>On our Home Page we want to add a welcome text.</p><p>Click <b>Add property</b> to open the property dialog.</p>",
"event": "click"
},
{
@@ -181,7 +181,7 @@
"element": "[data-element~='overlay-editor-picker']",
"elementPreventClick": true,
"title": "Editor picker",
"content": "<p>In the editor picker dialog we can pick one of the many build in editor.</p><p><em>You can choose from preconfigured data types (Reuse) or create a new configuration (Available editors)</em></p>"
"content": "<p>In the editor picker dialog we can pick one of the many built-in editors.</p><p><em>You can choose from preconfigured data types (Reuse) or create a new configuration (Available editors)</em>.</p>"
},
{
"element": "[data-element~='overlay-editor-picker'] [data-element='editor-Textarea']",
@@ -193,12 +193,12 @@
"element": "[data-element~='overlay-editor-settings']",
"elementPreventClick": true,
"title": "Editor settings",
"content": "Each property editor can have individual settings. For the textarea editor you can set a charachter limit but in this case it is not needed"
"content": "Each property editor can have individual settings. For the textarea editor you can set a character limit but in this case it is not needed."
},
{
"element": "[data-element~='overlay-editor-settings'] [data-element='button-overlaySubmit']",
"title": "Save editor",
"content": "Click <b>Submit</b> to save the editor.",
"content": "Click <b>Submit</b> to save the changes.",
"event": "click"
},
{
@@ -245,7 +245,7 @@
{
"element": "[data-element='tree-root']",
"title": "Open context menu",
"content": "<p>Open the context menu by hovering the root of the content section.</p><p>Now click the <b>three small dots</b> to the right.</p>",
"content": "<p>Open the context menu by hovering over the root of the content section.</p><p>Now click the <b>three small dots</b> to the right.</p>",
"event": "click",
"eventElement": "[data-element='tree-root'] [data-element='tree-item-options']"
},
@@ -264,7 +264,7 @@
{
"element": "[data-element='editor-content'] [data-element='property-welcomeText']",
"title": "Add a welcome text",
"content": "<p>Add content to the <b>Welcome Text</b> field</p><p>If you don't have any ideas here is a start:<br/> <pre>I am learning Umbraco. High Five I Rock #H5IR</pre>.</p>"
"content": "<p>Add content to the <b>Welcome Text</b> field.</p><p>If you don't have any ideas here is a start:<br/> <pre>I am learning Umbraco. High Five I Rock #H5IR</pre>.</p>"
},
{
"element": "[data-element='editor-content'] [data-element='button-saveAndPublish']",
@@ -291,13 +291,13 @@
"steps": [
{
"title": "Render your content in a template",
"content": "<p>Templating in Umbraco builds on the concept of <b>Razor Views</b> from asp.net MVC. - This tour is a sneak peak on how to write templates in Umbraco.</p><p>In this tour you will learn how to render content from the <b>Home Page</b> document type so you can see the content added to our <b>Home</b> content page.</p>",
"content": "<p>Templating in Umbraco builds on the concept of <b>Razor Views</b> from ASP.NET MVC. This tour is a sneak peak on how to write templates in Umbraco.</p><p>In this tour you will learn how to render content from the <b>Home Page</b> document type so you can see the content added to our <b>Home</b> content page.</p>",
"type": "intro"
},
{
"element": "#applications [data-element='section-settings']",
"title": "Navigate to the Settings section",
"content": "<p>In the <b>Settings</b> section you will find all the templates</p><p>It is of course also possible to edit all your code files in your favorite code editor.</p>",
"content": "<p>In the <b>Settings</b> section you will find all the templates.</p><p>It is of course also possible to edit all your code files in your favorite code editor.</p>",
"event": "click",
"backdropOpacity": 0.6
},
@@ -346,7 +346,7 @@
"steps": [
{
"title": "View your Umbraco site",
"content": "<p>Our three main components to a page is done: <b>Document type, Template, and Content</b> - it is now time to see the result.</p><p>In this tour you will learn how to see your published website.</p>",
"content": "<p>Our three main components to a page are done: <b>Document type, Template, and Content</b>. It is now time to see the result.</p><p>In this tour you will learn how to see your published website.</p>",
"type": "intro"
},
{
@@ -359,7 +359,7 @@
{
"element": "#tree [data-element='tree-item-Home']",
"title": "Open the Home page",
"content": "<p>Click the <b>Home</b> page to open it</p>",
"content": "<p>Click the <b>Home</b> page to open it.</p>",
"event": "click",
"eventElement": "#tree [data-element='tree-item-Home'] a.umb-tree-item__label"
},
@@ -408,7 +408,7 @@
{
"element": "#tree [data-element='tree-root']",
"title": "Create a new folder",
"content": "<p>First create a folder for your images. Hover the media root node and click the <b>three small dots</b> on the right side of the item.</p>",
"content": "<p>First create a folder for your images. Hover over the media root node and click the <b>three small dots</b> on the right side of the item.</p>",
"event": "click",
"eventElement": "#tree [data-element='tree-root'] [data-element='tree-item-options']"
},
@@ -427,19 +427,19 @@
{
"element": "[data-element='editor-media'] [data-element='button-save']",
"title": "Save the folder",
"content": "<p>Click the <b>Save</b> button to create the new folder</p>",
"content": "<p>Click the <b>Save</b> button to create the new folder.</p>",
"event": "click"
},
{
"element": "[data-element='editor-media'] [data-element='dropzone']",
"title": "Upload images",
"content": "<p>In the upload area you can upload your media items.</p><p>Click the <b>Click here to choose files</b>-button and select a couple of images on your computer and upload them.</p>",
"content": "<p>In the upload area you can upload your media items.</p><p>Click the <b>Click here to choose files</b> button and select a couple of images on your computer and upload them.</p>",
"view": "uploadimages"
},
{
"element": "[data-element='editor-media'] [data-element='media-grid-item-0']",
"title": "View media item details",
"content": "Hover the media item and <b>Click the purple bar</b> to view details about the media item",
"content": "Hover over the media item and <b>Click the purple bar</b> to view details about the media item.",
"event": "click",
"eventElement": "[data-element='editor-media'] [data-element='media-grid-item-0'] [data-element='media-grid-item-edit']"
},
@@ -26,37 +26,45 @@
<apiEndpoint><![CDATA[http://embed.gettyimages.com/oembed]]></apiEndpoint>
<requestParams type="Umbraco.Web.Media.EmbedProviders.Settings.Dictionary, umbraco"></requestParams>
</provider>
<!-- Poll Everywhere Settigs -->
<!-- Poll Everywhere Settings -->
<provider name="PollEverywhere" type="Umbraco.Web.Media.EmbedProviders.OEmbedJson, umbraco">
<urlShemeRegex><![CDATA[polleverywhere\.com/]]></urlShemeRegex>
<apiEndpoint><![CDATA[http://www.polleverywhere.com/services/oembed/]]></apiEndpoint>
<requestParams type="Umbraco.Web.Media.EmbedProviders.Settings.Dictionary, umbraco"></requestParams>
</provider>
<!-- Poll Daddy Settigs -->
<!-- Poll Daddy Settings -->
<provider name="PollDaddy" type="Umbraco.Web.Media.EmbedProviders.OEmbedJson, umbraco">
<urlShemeRegex><![CDATA[polldaddy\.com/]]></urlShemeRegex>
<apiEndpoint><![CDATA[http://polldaddy.com/oembed/]]></apiEndpoint>
<requestParams type="Umbraco.Web.Media.EmbedProviders.Settings.Dictionary, umbraco"></requestParams>
</provider>
<!-- IFTTT Settigs -->
<!-- IFTTT Settings -->
<provider name="IFTTT" type="Umbraco.Web.Media.EmbedProviders.OEmbedJson, umbraco">
<urlShemeRegex><![CDATA[ifttt\.com/]]></urlShemeRegex>
<apiEndpoint><![CDATA[http://www.ifttt.com/oembed/]]></apiEndpoint>
<requestParams type="Umbraco.Web.Media.EmbedProviders.Settings.Dictionary, umbraco"></requestParams>
</provider>
<!-- Instagram Settigs -->
<!-- Instagram Settings -->
<provider name="Instagram" type="Umbraco.Web.Media.EmbedProviders.OEmbedJson, umbraco">
<urlShemeRegex><![CDATA[instagram\.com/]]></urlShemeRegex>
<apiEndpoint><![CDATA[http://api.instagram.com/oembed]]></apiEndpoint>
<requestParams type="Umbraco.Web.Media.EmbedProviders.Settings.Dictionary, umbraco"></requestParams>
</provider>
<!-- Rdio Settigs -->
<!-- Issuu Settings-->
<provider name="Issuu" type="Umbraco.Web.Media.EmbedProviders.OEmbedJson, umbraco">
<urlShemeRegex><![CDATA[issuu.com/(?:.*)/docs]]></urlShemeRegex>
<apiEndpoint><![CDATA[https://issuu.com/oembed]]></apiEndpoint>
<requestParams type="Umbraco.Web.Media.EmbedProviders.Settings.Dictionary, umbraco">
<param name="format">json</param>
</requestParams>
</provider>
<!-- Rdio Settings -->
<provider name="Rdio" type="Umbraco.Web.Media.EmbedProviders.OEmbedJson, umbraco">
<urlShemeRegex><![CDATA[rdio\.com/]]></urlShemeRegex>
<apiEndpoint><![CDATA[http://www.rdio.com/api/oembed/]]></apiEndpoint>
<requestParams type="Umbraco.Web.Media.EmbedProviders.Settings.Dictionary, umbraco"></requestParams>
</provider>
<!-- SoundCloud Settigs -->
<!-- SoundCloud Settings -->
<provider name="SoundCloud" type="Umbraco.Web.Media.EmbedProviders.OEmbedRich, umbraco">
<urlShemeRegex><![CDATA[soundcloud\.com/]]></urlShemeRegex>
<apiEndpoint><![CDATA[http://soundcloud.com/oembed]]></apiEndpoint>
+14 -6
View File
@@ -26,37 +26,45 @@
<apiEndpoint><![CDATA[http://embed.gettyimages.com/oembed]]></apiEndpoint>
<requestParams type="Umbraco.Web.Media.EmbedProviders.Settings.Dictionary, umbraco"></requestParams>
</provider>
<!-- Poll Everywhere Settigs -->
<!-- Poll Everywhere Settings -->
<provider name="PollEverywhere" type="Umbraco.Web.Media.EmbedProviders.OEmbedJson, umbraco">
<urlShemeRegex><![CDATA[polleverywhere\.com/]]></urlShemeRegex>
<apiEndpoint><![CDATA[http://www.polleverywhere.com/services/oembed/]]></apiEndpoint>
<requestParams type="Umbraco.Web.Media.EmbedProviders.Settings.Dictionary, umbraco"></requestParams>
</provider>
<!-- Poll Daddy Settigs -->
<!-- Poll Daddy Settings -->
<provider name="PollDaddy" type="Umbraco.Web.Media.EmbedProviders.OEmbedJson, umbraco">
<urlShemeRegex><![CDATA[polldaddy\.com/]]></urlShemeRegex>
<apiEndpoint><![CDATA[http://polldaddy.com/oembed/]]></apiEndpoint>
<requestParams type="Umbraco.Web.Media.EmbedProviders.Settings.Dictionary, umbraco"></requestParams>
</provider>
<!-- IFTTT Settigs -->
<!-- IFTTT Settings -->
<provider name="IFTTT" type="Umbraco.Web.Media.EmbedProviders.OEmbedJson, umbraco">
<urlShemeRegex><![CDATA[ifttt\.com/]]></urlShemeRegex>
<apiEndpoint><![CDATA[http://www.ifttt.com/oembed/]]></apiEndpoint>
<requestParams type="Umbraco.Web.Media.EmbedProviders.Settings.Dictionary, umbraco"></requestParams>
</provider>
<!-- Instagram Settigs -->
<!-- Instagram Settings -->
<provider name="Instagram" type="Umbraco.Web.Media.EmbedProviders.OEmbedJson, umbraco">
<urlShemeRegex><![CDATA[instagram\.com/]]></urlShemeRegex>
<apiEndpoint><![CDATA[http://api.instagram.com/oembed]]></apiEndpoint>
<requestParams type="Umbraco.Web.Media.EmbedProviders.Settings.Dictionary, umbraco"></requestParams>
</provider>
<!-- Rdio Settigs -->
<!-- Issuu Settings -->
<provider name="Issuu" type="Umbraco.Web.Media.EmbedProviders.OEmbedJson, umbraco">
<urlShemeRegex><![CDATA[issuu.com/(?:.*)/docs]]></urlShemeRegex>
<apiEndpoint><![CDATA[https://issuu.com/oembed]]></apiEndpoint>
<requestParams type="Umbraco.Web.Media.EmbedProviders.Settings.Dictionary, umbraco">
<param name="format">json</param>
</requestParams>
</provider>
<!-- Rdio Settings -->
<provider name="Rdio" type="Umbraco.Web.Media.EmbedProviders.OEmbedJson, umbraco">
<urlShemeRegex><![CDATA[rdio\.com/]]></urlShemeRegex>
<apiEndpoint><![CDATA[http://www.rdio.com/api/oembed/]]></apiEndpoint>
<requestParams type="Umbraco.Web.Media.EmbedProviders.Settings.Dictionary, umbraco"></requestParams>
</provider>
<!-- SoundCloud Settigs -->
<!-- SoundCloud Settings -->
<provider name="SoundCloud" type="Umbraco.Web.Media.EmbedProviders.OEmbedRich, umbraco">
<urlShemeRegex><![CDATA[soundcloud\.com/]]></urlShemeRegex>
<apiEndpoint><![CDATA[http://soundcloud.com/oembed]]></apiEndpoint>
@@ -16,8 +16,9 @@
<add application="settings" alias="stylesheetProperty" title="Stylesheet Property" type="umbraco.loadStylesheetProperty, umbraco" iconClosed="" iconOpen="" initialize="false" sortOrder="0" />
<add application="settings" alias="scripts" title="Scripts" type="Umbraco.Web.Trees.ScriptTreeController, umbraco" iconClosed="icon-folder" iconOpen="icon-folder" sortOrder="4" />
<add application="settings" alias="languages" title="Languages" iconClosed="icon-folder" iconOpen="icon-folder-open" type="Umbraco.Web.Trees.LanguageTreeController, umbraco" sortOrder="5" />
<add application="settings" alias="dictionary" title="Dictionary" type="umbraco.loadDictionary, umbraco" iconClosed="icon-folder" iconOpen="icon-folder" sortOrder="6" />
<add application="settings" alias="dictionary" title="Dictionary" type="Umbraco.Web.Trees.DictionaryTreeController, umbraco" iconClosed="icon-folder" iconOpen="icon-folder" sortOrder="6" />
<add initialize="true" sortOrder="7" alias="mediaTypes" application="settings" title="Media Types" iconClosed="icon-folder" iconOpen="icon-folder-open" type="Umbraco.Web.Trees.MediaTypeTreeController, umbraco" />
<add initialize="true" sortOrder="8" alias="contentBlueprints" application="settings" iconClosed="icon-folder" iconOpen="icon-folder-open" type="Umbraco.Web.Trees.ContentBlueprintTreeController, umbraco" />
<!--Developer-->
<add initialize="true" sortOrder="0" alias="packager" application="developer" iconClosed="icon-folder" iconOpen="icon-folder-open" type="Umbraco.Web.Trees.PackagesTreeController, umbraco" />
@@ -44,4 +45,4 @@
<!--<add application="myApplication" alias="myTree" title="Me Tree" type="MyNamespace.myTree, MyAssembly"
iconClosed="icon-folder" iconOpen="icon-folder" sortOrder="10" />-->
</trees>
</trees>
+13 -13
View File
@@ -14,7 +14,7 @@
<add application="settings" alias="stylesheetProperty" title="Stylesheet Property" type="umbraco.loadStylesheetProperty, umbraco" iconClosed="" iconOpen="" initialize="false" sortOrder="0" />
<add application="settings" alias="scripts" title="Scripts" type="Umbraco.Web.Trees.ScriptTreeController, umbraco" iconClosed="icon-folder" iconOpen="icon-folder" sortOrder="4" />
<add application="settings" alias="languages" title="Languages" iconClosed="icon-folder" iconOpen="icon-folder-open" type="Umbraco.Web.Trees.LanguageTreeController, umbraco" sortOrder="5" />
<add application="settings" alias="dictionary" title="Dictionary" type="umbraco.loadDictionary, umbraco" iconClosed="icon-folder" iconOpen="icon-folder" sortOrder="6" />
<add application="settings" alias="dictionary" title="Dictionary" type="Umbraco.Web.Trees.DictionaryTreeController, umbraco" iconClosed="icon-folder" iconOpen="icon-folder" sortOrder="6" />
<add initialize="true" sortOrder="7" alias="mediaTypes" application="settings" title="Media Types" iconClosed="icon-folder" iconOpen="icon-folder-open" type="Umbraco.Web.Trees.MediaTypeTreeController, umbraco" />
<add initialize="true" sortOrder="8" alias="contentBlueprints" application="settings" iconClosed="icon-folder" iconOpen="icon-folder-open" type="Umbraco.Web.Trees.ContentBlueprintTreeController, umbraco" />
<!--Developer-->
@@ -23,21 +23,21 @@
<add initialize="true" sortOrder="2" alias="macros" application="developer" iconClosed="icon-folder" iconOpen="icon-folder-open" type="Umbraco.Web.Trees.MacroTreeController, umbraco" />
<add application="developer" alias="relationTypes" title="Relation Types" type="umbraco.loadRelationTypes, umbraco" iconClosed="icon-folder" iconOpen="icon-folder" sortOrder="4" />
<add initialize="true" sortOrder="5" alias="xslt" application="developer" iconClosed="icon-folder" iconOpen="icon-folder-open" type="Umbraco.Web.Trees.XsltTreeController, umbraco" />
<add application="developer" alias="partialViewMacros" type="Umbraco.Web.Trees.PartialViewMacrosTreeController, umbraco" silent="false" initialize="true" sortOrder="6" title="Partial View Macro Files" iconClosed="icon-folder" iconOpen="icon-folder" />
<!--Users-->
<add initialize="true" sortOrder="0" alias="users" application="users" iconClosed="icon-folder" iconOpen="icon-folder-open" type="Umbraco.Web.Trees.UserTreeController, umbraco" />
<!--Members-->
<add initialize="true" sortOrder="0" alias="member" application="member" title="Members" iconClosed="icon-folder" iconOpen="icon-folder-open" type="Umbraco.Web.Trees.MemberTreeController, umbraco" />
<add initialize="true" sortOrder="1" alias="memberTypes" application="member" title="Member Types" iconClosed="icon-folder" iconOpen="icon-folder-open" type="Umbraco.Web.Trees.MemberTypeTreeController, umbraco" />
<add application="member" sortOrder="2" alias="memberGroups" title="Member Groups" type="umbraco.loadMemberGroups, umbraco" iconClosed="icon-folder" iconOpen="icon-folder" />
<!--Translation-->
<add silent="false" initialize="true" sortOrder="1" alias="openTasks" application="translation" title="Tasks assigned to you" iconClosed="icon-folder" iconOpen="icon-folder" type="umbraco.loadOpenTasks, umbraco" />
<add silent="false" initialize="true" sortOrder="2" alias="yourTasks" application="translation" title="Tasks created by you" iconClosed="icon-folder" iconOpen="icon-folder" type="umbraco.loadYourTasks, umbraco" />
<!-- Custom -->
<add application="developer" alias="partialViewMacros" type="Umbraco.Web.Trees.PartialViewMacrosTreeController, umbraco" silent="false" initialize="true" sortOrder="6" title="Partial View Macro Files" iconClosed="icon-folder" iconOpen="icon-folder" />
<!--Users-->
<add initialize="true" sortOrder="0" alias="users" application="users" iconClosed="icon-folder" iconOpen="icon-folder-open" type="Umbraco.Web.Trees.UserTreeController, umbraco" />
<!--Members-->
<add initialize="true" sortOrder="0" alias="member" application="member" title="Members" iconClosed="icon-folder" iconOpen="icon-folder-open" type="Umbraco.Web.Trees.MemberTreeController, umbraco" />
<add initialize="true" sortOrder="1" alias="memberTypes" application="member" title="Member Types" iconClosed="icon-folder" iconOpen="icon-folder-open" type="Umbraco.Web.Trees.MemberTypeTreeController, umbraco" />
<add application="member" sortOrder="2" alias="memberGroups" title="Member Groups" type="umbraco.loadMemberGroups, umbraco" iconClosed="icon-folder" iconOpen="icon-folder" />
<!--Translation-->
<add silent="false" initialize="true" sortOrder="1" alias="openTasks" application="translation" title="Tasks assigned to you" iconClosed="icon-folder" iconOpen="icon-folder" type="umbraco.loadOpenTasks, umbraco" />
<add silent="false" initialize="true" sortOrder="2" alias="yourTasks" application="translation" title="Tasks created by you" iconClosed="icon-folder" iconOpen="icon-folder" type="umbraco.loadYourTasks, umbraco" />
<!-- Custom -->
<!--<add application="myApplication" alias="myTree" title="Me Tree" type="MyNamespace.myTree, MyAssembly"
iconClosed="icon-folder" iconOpen="icon-folder" sortOrder="10" />-->
<add initialize="true" sortOrder="2" alias="datasource" application="forms" title="Datasources" iconClosed="icon-folder" iconOpen="icon-folder-open" type="Umbraco.Forms.Web.Trees.DataSourceTreeController, Umbraco.Forms.Web" />
<add initialize="true" sortOrder="0" alias="form" application="forms" title="Forms" iconClosed="icon-folder" iconOpen="icon-folder-open" type="Umbraco.Forms.Web.Trees.FormTreeController, Umbraco.Forms.Web" />
<add initialize="true" sortOrder="3" alias="prevaluesource" application="forms" title="Prevalue sources" iconClosed="icon-folder" iconOpen="icon-folder-open" type="Umbraco.Forms.Web.Trees.PreValueSourceTreeController, Umbraco.Forms.Web" />
<add initialize="true" sortOrder="3" alias="formsecurity" application="users" title="Forms Security" iconClosed="icon-folder" iconOpen="icon-folder-open" type="Umbraco.Forms.Web.Trees.FormSecurityTreeController, Umbraco.Forms.Web" />
</trees>
</trees>
@@ -14,7 +14,7 @@
<!-- automatically updates dimension, filesize and extension attributes on upload -->
<autoFillImageProperties>
<uploadField alias="umbracoFile">
<widthFieldAlias>umbracoWidth</widthFieldAlias>
<widthFieldAlias>umbracoWidth</widthFieldAlias>
<heightFieldAlias>umbracoHeight</heightFieldAlias>
<lengthFieldAlias>umbracoBytes</lengthFieldAlias>
<extensionFieldAlias>umbracoExtension</extensionFieldAlias>
+1 -1
View File
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="AutoMapper" version="3.3.1" targetFramework="net45" />
<package id="ClientDependency" version="1.9.6" targetFramework="net45" />
<package id="ClientDependency" version="1.9.7" targetFramework="net45" />
<package id="ClientDependency-Mvc5" version="1.8.0.0" targetFramework="net45" />
<package id="dotless" version="1.5.2" targetFramework="net45" />
<package id="Examine" version="0.1.89" targetFramework="net45" />
@@ -73,7 +73,7 @@
<delete assembly="umbraco" type="stylesheetPropertyTasks" />
</tasks>
</nodeType>
<nodeType alias="initdictionary">
<nodeType alias="initdictionary-obsolete">
<header>Dictionary editor egenskab</header>
<usercontrol>/create/simple.ascx</usercontrol>
<tasks>
@@ -418,6 +418,7 @@
The key '%0%' already exists.
]]>
</key>
<key alias="overviewTitle">Dictionary overview</key>
</area>
<area alias="placeholders">
<key alias="username">Enter your username</key>
@@ -1652,6 +1653,9 @@ To manage your website, simply open the Umbraco back office and start adding con
<key alias="showOnMemberProfileDescription">Allow this property value to be displayed on the member profile page</key>
<key alias="tabHasNoSortOrder">tab has no sort order</key>
<key alias="compositionUsageHeading">Where is this composition used?</key>
<key alias="compositionUsageSpecification">This composition is currently used in the composition of the following content types:</key>
</area>
<area alias="modelsBuilder">
@@ -417,6 +417,7 @@
The key '%0%' already exists.
]]>
</key>
<key alias="overviewTitle">Dictionary overview</key>
</area>
<area alias="placeholders">
<key alias="username">Enter your username</key>
@@ -1644,6 +1645,9 @@ To manage your website, simply open the Umbraco back office and start adding con
<key alias="showOnMemberProfileDescription">Allow this property value to be displayed on the member profile page</key>
<key alias="tabHasNoSortOrder">tab has no sort order</key>
<key alias="compositionUsageHeading">Where is this composition used?</key>
<key alias="compositionUsageSpecification">This composition is currently used in the composition of the following content types:</key>
</area>
<area alias="modelsBuilder">
+335 -42
View File
@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<language alias="ru" intName="Russian" localName="русский" lcid="" culture="ru-RU">
<creator>
<name>The Umbraco community</name>
@@ -19,6 +19,7 @@
<key alias="disable">Отключить</key>
<key alias="emptyTrashcan">Очистить корзину</key>
<key alias="enable">Включить</key>
<key alias="export">Экспорт</key>
<key alias="exportDocumentType">Экспортировать</key>
<key alias="importDocumentType">Импортировать</key>
<key alias="importPackage">Импортировать пакет</key>
@@ -158,8 +159,9 @@
<key alias="returnToList">Вернуться к списку</key>
<key alias="save">Сохранить</key>
<key alias="saveAndGenerateModels">Сохранить и построить модели</key>
<key alias="saveAndPublish">Сохранить и опубликовать</key>
<key alias="saveToPublish">Сохранить и направить на публикацию</key>
<key alias="saveAndPublish">Опубликовать</key>
<key alias="saveAndSchedule">Запланировать</key>
<key alias="saveToPublish">Направить на публикацию</key>
<key alias="saveListView">Сохранить список</key>
<key alias="select">Выбрать</key>
<key alias="selectCurrentFolder">Выбрать текущую папку</key>
@@ -201,7 +203,20 @@
<key alias="yellow">Желтый</key>
<key alias="orange">Оранжевый</key>
<key alias="blue">Синий</key>
<key alias="bluegrey">Серо-синий</key>
<key alias="grey">Серый</key>
<key alias="brown">Коричневый</key>
<key alias="lightblue">Светло-синий</key>
<key alias="cyan">Голубой</key>
<key alias="lightgreen">Светло-зеленый</key>
<key alias="lime">Лайм</key>
<key alias="amber">Янтарный</key>
<key alias="deeporange">Рыжий</key>
<key alias="red">Красный</key>
<key alias="pink">Розовый</key>
<key alias="purple">Лиловый</key>
<key alias="deeppurple">Темно-лиловый</key>
<key alias="indigo">Индиго</key>
</area>
<area alias="content">
<key alias="about">Об этой странице</key>
@@ -221,6 +236,8 @@
<key alias="expireDate">Скрыть</key>
<key alias="getUrlException">ВНИМАНИЕ: невозможно получить URL документа (внутренняя ошибка - подробности в системном журнале)</key>
<key alias="isPublished" version="7.2">Опубликовано</key>
<key alias="isSensitiveValue">Это значение скрыто. Если Вам нужен доступ к просмотру этого значения, свяжитесь с администратором веб-сайта.</key>
<key alias="isSensitiveValue_short">Это значение скрыто.</key>
<key alias="itemChanged">Этот документ был изменен после публикации</key>
<key alias="itemNotPublished">Этот документ не опубликован</key>
<key alias="lastPublished">Документ опубликован</key>
@@ -236,19 +253,24 @@
<key alias="membertype">Тип участника</key>
<key alias="nestedContentDeleteItem">Вы уверены, что хотите удалить этот элемент?</key>
<key alias="nestedContentEditorNotSupported">Свойство '%0%' использует редактор '%1%', который не поддерживается для вложенного содержимого.</key>
<key alias="noChanges">Не было сделано никаких изменений</key>
<key alias="noDate">Дата не указана</key>
<key alias="nodeName">Заголовок страницы</key>
<key alias="noMediaLink">Этот медиа-элемент не содержит ссылки</key>
<key alias="notmemberof">Доступные группы</key>
<key alias="otherElements">Свойства</key>
<key alias="parentNotPublished">Этот документ опубликован, но скрыт, потому что его родительский документ '%0%' не опубликован</key>
<key alias="parentNotPublishedAnomaly">ВНИМАНИЕ: этот документ опубликован, но его нет в глобальном кэше (внутренняя ошибка - подробности в системном журнале)</key>
<key alias="publish">Опубликовать</key>
<key alias="published">Опубликовано</key>
<key alias="publishedPendingChanges">Опубликовано (есть измененения)</key>
<key alias="publishStatus">Состояние публикации</key>
<key alias="releaseDate">Опубликовать</key>
<key alias="removeDate">Очистить дату</key>
<key alias="routeError">ВНИМАНИЕ: этот документ опубликован, но его URL вступает в противоречие с документом %0%</key>
<key alias="scheduledPublishServerTime">Это время будет соответствовать следующему времени на сервере:</key>
<key alias="scheduledPublishDocumentation"><![CDATA[<a href="https://our.umbraco.org/documentation/Getting-Started/Data/Scheduled-Publishing/#timezones" target="_blank">Что это означает?</a>]]></key>
<key alias="setDate">Задать дату</key>
<key alias="sortDone">Порядок сортировки обновлен</key>
<key alias="sortHelp">Для сортировки узлов просто перетаскивайте узлы или нажмите на заголовке столбца. Вы можете выбрать несколько узлов, удерживая клавиши "shift" или "ctrl" при пометке</key>
<key alias="statistics">Статистика</key>
@@ -256,6 +278,7 @@
<key alias="titleOptional">Заголовок (необязательно)</key>
<key alias="type">Тип</key>
<key alias="unPublish">Скрыть</key>
<key alias="unpublished">Распубликовано</key>
<key alias="unpublishDate">Распубликовать</key>
<key alias="updateDate">Последняя правка</key>
<key alias="updateDateDesc" version="7.0">Дата/время редактирования документа</key>
@@ -265,6 +288,10 @@
<key alias="addTextBox">Добавить новое поле текста</key>
<key alias="removeTextBox">Удалить это поле текста</key>
</area>
<area alias="contentPicker">
<key alias="pickedTrashedItem">Выбран элемент содержимого, который в настоящее время удален или находится в корзине</key>
<key alias="pickedTrashedItems">Выбраны элементы содержимого, которые в настоящее время удалены или находятся в корзине</key>
</area>
<area alias="contentTypeEditor">
<key alias="compositions">Композиции</key>
<key alias="noTabs">Вы не добавили ни одной вкладки</key>
@@ -289,6 +316,8 @@
<key alias="chooseChildNode">Выбрать дочерний узел</key>
<key alias="compositionsDescription">Унаследовать вкладки и свойства из уже существующего типа документов. Вкладки будут либо добавлены в создаваемый тип, либо в случае совпадения названий вкладок будут добавлены наследуемые свойства.</key>
<key alias="compositionInUse">Этот тип документов уже участвует в композиции другого типа, поэтому сам не может быть композицией.</key>
<key alias="compositionUsageHeading">Где используется эта композиция?</key>
<key alias="compositionUsageSpecification">Эта композиция сейчас используется при создании следующих типов документов:</key>
<key alias="noAvailableCompositions">В настоящее время нет типов документов, допустимых для построения композиции.</key>
<key alias="availableEditors">Доступные редакторы</key>
@@ -320,7 +349,11 @@
<key alias="thisEditorUpdateSettings">, использующие этот редактор, будут обновлены с применением этих установок</key>
<key alias="memberCanEdit">Участник может изменить</key>
<key alias="memberCanEditDescription">Разрешает редактирование значение данного свойства участником в своем профиле</key>
<key alias="isSensitiveData">Конфеденциальные данные</key>
<key alias="isSensitiveDataDescription">Скрывает значение это свойства от редакторов содержимого, не имеющих доступа к конфеденциальной информации</key>
<key alias="showOnMemberProfile">Показать в профиле участника</key>
<key alias="showOnMemberProfileDescription">Разрешает показ данного свойства в профиле участника</key>
<key alias="tabHasNoSortOrder">для вкладки не указан порядок сортировки</key>
</area>
<area alias="create">
@@ -447,6 +480,7 @@
Ключ '%0%' уже существует в словаре.
]]>
</key>
<key alias="overviewTitle">Обзор словаря</key>
</area>
<area alias="editcontenttype">
<key alias="allowAtRoot" version="7.2">Допустим как корневой</key>
@@ -569,13 +603,16 @@
<key alias="error">Ошибка</key>
<key alias="findDocument">Найти</key>
<key alias="first">Начало</key>
<key alias="general">Общее</key>
<key alias="groups">Группы</key>
<key alias="folder">Папка</key>
<key alias="height">Высота</key>
<key alias="help">Справка</key>
<key alias="hide">Скрыть</key>
<key alias="history">История</key>
<key alias="icon">Иконка</key>
<key alias="import">Импорт</key>
<key alias="info">Инфо</key>
<key alias="innerMargin">Внутренний отступ</key>
<key alias="insert">Вставить</key>
<key alias="install">Установить</key>
@@ -585,6 +622,7 @@
<key alias="language">Язык</key>
<key alias="last">Конец</key>
<key alias="layout">Макет</key>
<key alias="links">Ссылки</key>
<key alias="loading">Загрузка</key>
<key alias="locked">БЛОКИРОВКА</key>
<key alias="login">Войти</key>
@@ -605,6 +643,7 @@
<key alias="ok">Ok</key>
<key alias="open">Открыть</key>
<key alias="on">Вкл</key>
<key alias="options">Варианты</key>
<key alias="or">или</key>
<key alias="orderBy">Сортировка по</key>
<key alias="password">Пароль</key>
@@ -624,6 +663,7 @@
<key alias="retrieve">Получить</key>
<key alias="retry">Повторить</key>
<key alias="rights">Разрешения</key>
<key alias="scheduledPublishing">Публикация по расписанию</key>
<key alias="search">Поиск</key>
<key alias="searchNoResult">К сожалению, ничего подходящего не нашлось</key>
<key alias="searchResults">Результаты поиска</key>
@@ -657,7 +697,8 @@
<key alias="saving">Сохранение...</key>
<key alias="current">текущий</key>
<key alias="selected">выбрано</key>
<key alias="embed">Внедрить</key>
<key alias="embed">Встроить</key>
<key alias="retrieve">Получить</key>
</area>
<area alias="graphicheadline">
<key alias="backgroundcolor">Цвет фона</key>
@@ -667,12 +708,12 @@
<key alias="text">Текст</key>
</area>
<area alias="grid">
<key alias="rte">Rich Text Editor</key>
<key alias="media">Image</key>
<key alias="macro">Macro</key>
<key alias="embed">Embed</key>
<key alias="headline">Headline</key>
<key alias="quote">Quote</key>
<key alias="rte">Редактор текста</key>
<key alias="media">Изображение</key>
<key alias="macro">Макрос</key>
<key alias="embed">Встраивание</key>
<key alias="headline">Заголовок</key>
<key alias="quote">Цитата</key>
<key alias="addElement">Добавить содержимое</key>
<key alias="dropElement">Сбросить содержимое</key>
<key alias="addGridLayout">Добавить шаблон сетки</key>
@@ -754,9 +795,10 @@
<key alias="xmlDataIntegrityCheckMedia">Медиа - всего в XML: %0%, всего: %1%Б с ошибками: %2%</key>
<key alias="xmlDataIntegrityCheckContent">Содержимое - всего в XML: %0%, всего опубликовано: %1%, с ошибками: %2%</key>
<key alias="healthCheckInvalidUrl">Ошибка проверки адреса URL %0% - '%1%'</key>
<key alias="httpsCheckValidCertificate">Сертификат Вашего веб-сайта отмечен как проверенный.</key>
<key alias="httpsCheckInvalidCertificate">Ошибка проверки сертификата: '%0%'</key>
<key alias="healthCheckInvalidUrl">Ошибка проверки адреса URL %0% - '%1%'</key>
<key alias="httpsCheckIsCurrentSchemeHttps">Сейчас Вы %0% просматриваете сайт, используя протокол HTTPS.</key>
<key alias="httpsCheckConfigurationRectifyNotPossible">Параметр 'umbracoUseSSL' в секции 'appSetting' установлен в 'false' в файле web.config. Если Вам необходим доступ к сайту по протоколу HTTPS, нужно установить данный параметр в 'true'.</key>
<key alias="httpsCheckConfigurationCheckResult">Параметр 'umbracoUseSSL' в секции 'appSetting' в файле установлен в '%0%', значения cookies %1% маркированы как безопасные.</key>
@@ -796,11 +838,27 @@
<key alias="clickJackingCheckHeaderFound"><![CDATA[Был обнаружен заголовок или мета-тэг <strong>X-Frame-Options</strong>, использующийся для управления возможностью помещать сайт в IFRAME на другом сайте.]]></key>
<key alias="clickJackingCheckHeaderNotFound"><![CDATA[Заголовок или мета-тэг <strong>X-Frame-Options</strong>, использующийся для управления возможностью помещать сайт в IFRAME на другом сайте, не обнаружен.]]></key>
<key alias="setHeaderInConfig">Установить заголовок в файле конфигурации</key>
<key alias="clickJackingSetHeaderInConfigDescription">Добавляет значение в секцию 'httpProtocol/customHeaders' файла web.config, препятствующее возможному использованию этого сайта внутри IFRAME на другом сайте.</key>
<key alias="clickJackingSetHeaderInConfigSuccess">Значение, добавляющее заголовок, препятствующий использованию этого сайта внутри IFRAME другого сайта, успешно добавлено в файл web.config.</key>
<key alias="setHeaderInConfig">Установить заголовок в файле конфигурации</key>
<key alias="setHeaderInConfigError">Невозможно обновить файл web.config. Ошибка: %0%</key>
<key alias="noSniffCheckHeaderFound"><![CDATA[Заголовок или мета-тэг <strong>X-Content-Type-Options</strong>, использующиеся для защиты от MIME-уязвимостей, обнаружены.]]></key>
<key alias="noSniffCheckHeaderNotFound"><![CDATA[Заголовок или мета-тэг <strong>X-Content-Type-Options</strong>, использующиеся для защиты от MIME-уязвимостей, не найдены.]]></key>
<key alias="noSniffSetHeaderInConfigDescription">Добавляет значение в секцию httpProtocol/customHeaders файла web.config, препятствующее использованию MIME-уязвимостей.</key>
<key alias="noSniffSetHeaderInConfigSuccess">Значение, добавляющее заголовок, препятствующий использованию MIME-уязвимостей, успешно добавлено в файл web.config.</key>
<key alias="hSTSCheckHeaderFound"><![CDATA[Заголовок <strong>Strict-Transport-Security</strong>, известный также как HSTS-header, обнаружен.]]></key>
<key alias="hSTSCheckHeaderNotFound"><![CDATA[Заголовок <strong>Strict-Transport-Security</strong> не найден.]]></key>
<key alias="hSTSSetHeaderInConfigDescription">Добавляет заголовок 'Strict-Transport-Security' и его значение 'max-age=10886400; preload' в секцию httpProtocol/customHeaders файла web.config. Применяйте этот способ только в случае, если доступ к Вашим сайтам будет осуществляться по протоколу https как минимум ближайшие 18 недель.</key>
<key alias="hSTSSetHeaderInConfigSuccess">Заголовок HSTS-header успешно добавлен в файл web.config.</key>
<key alias="xssProtectionCheckHeaderFound"><![CDATA[Заголовок <strong>X-XSS-Protection</strong> обнаружен.]]></key>
<key alias="xssProtectionCheckHeaderNotFound"><![CDATA[Заголовок <strong>X-XSS-Protection</strong> не найден.]]></key>
<key alias="xssProtectionSetHeaderInConfigDescription">Добавляет заголовок 'X-XSS-Protection' и его значение '1; mode=block' в секцию httpProtocol/customHeaders файла web.config. </key>
<key alias="xssProtectionSetHeaderInConfigSuccess">Заголовок X-XSS-Protection успешно добавлен в файл web.config.</key>
<!-- The following key get these tokens passed in:
0: Comma delimitted list of headers found
-->
@@ -970,7 +1028,87 @@
<key alias="resetCodeExpired">Ссылка, по которой Вы попали сюда, неверна или устарела</key>
<key alias="resetPasswordEmailCopySubject">Umbraco: сброс пароля</key>
<key alias="resetPasswordEmailCopyFormat">
<![CDATA[<html><body><p>Ваше имя пользователя для входа в панель администрирования Umbraco: <strong>%0%</strong></p><p>Перейдите по <a href="%1%"><strong>этой ссылке</strong></a> для того, чтобы сбросить Ваш пароль, или скопируйте текст ссылки и вставьте в адресную строку своего браузера:</p><p><em>%1%</em></p></body></html>]]>
<![CDATA[
<html>
<head>
<meta name='viewport' content='width=device-width'>
<meta http-equiv='Content-Type' content='text/html; charset=UTF-8'>
</head>
<body class='' style='font-family: sans-serif; -webkit-font-smoothing: antialiased; font-size: 14px; color: #392F54; line-height: 22px; -ms-text-size-adjust: 100%; -webkit-text-size-adjust: 100%; background: #1d1333; margin: 0; padding: 0;' bgcolor='#1d1333'>
<style type='text/css'> @media only screen and (max-width: 620px) {table[class=body] h1 {font-size: 28px !important; margin-bottom: 10px !important; } table[class=body] .wrapper {padding: 32px !important; } table[class=body] .article {padding: 32px !important; } table[class=body] .content {padding: 24px !important; } table[class=body] .container {padding: 0 !important; width: 100% !important; } table[class=body] .main {border-left-width: 0 !important; border-radius: 0 !important; border-right-width: 0 !important; } table[class=body] .btn table {width: 100% !important; } table[class=body] .btn a {width: 100% !important; } table[class=body] .img-responsive {height: auto !important; max-width: 100% !important; width: auto !important; } } .btn-primary table td:hover {background-color: #34495e !important; } .btn-primary a:hover {background-color: #34495e !important; border-color: #34495e !important; } .btn a:visited {color:#FFFFFF;} </style>
<table border="0" cellpadding="0" cellspacing="0" class="body" style="border-collapse: separate; mso-table-lspace: 0pt; mso-table-rspace: 0pt; width: 100%; background: #1d1333;" bgcolor="#1d1333">
<tr>
<td style="font-family: sans-serif; font-size: 14px; vertical-align: top; padding: 24px;" valign="top">
<table style="border-collapse: separate; mso-table-lspace: 0pt; mso-table-rspace: 0pt; width: 100%;">
<tr>
<td background="https://umbraco.com/umbraco/assets/img/application/logo.png" bgcolor="#1d1333" width="28" height="28" valign="top" style="font-family: sans-serif; font-size: 14px; vertical-align: top;">
<!--[if gte mso 9]> <v:rect xmlns:v="urn:schemas-microsoft-com:vml" fill="true" stroke="false" style="width:30px;height:30px;"> <v:fill type="tile" src="https://umbraco.com/umbraco/assets/img/application/logo.png" color="#1d1333" /> <v:textbox inset="0,0,0,0"> <![endif]-->
<div> </div>
<!--[if gte mso 9]> </v:textbox> </v:rect> <![endif]-->
</td>
<td style="font-family: sans-serif; font-size: 14px; vertical-align: top;" valign="top"></td>
</tr>
</table>
</td>
</tr>
</table>
<table border='0' cellpadding='0' cellspacing='0' class='body' style='border-collapse: separate; mso-table-lspace: 0pt; mso-table-rspace: 0pt; width: 100%; background: #1d1333;' bgcolor='#1d1333'>
<tr>
<td style='font-family: sans-serif; font-size: 14px; vertical-align: top;' valign='top'> </td>
<td class='container' style='font-family: sans-serif; font-size: 14px; vertical-align: top; display: block; max-width: 560px; width: 560px; margin: 0 auto; padding: 10px;' valign='top'>
<div class='content' style='box-sizing: border-box; display: block; max-width: 560px; margin: 0 auto; padding: 10px;'>
<br>
<table class='main' style='border-collapse: separate; mso-table-lspace: 0pt; mso-table-rspace: 0pt; width: 100%; border-radius: 3px; background: #FFFFFF;' bgcolor='#FFFFFF'>
<tr>
<td class='wrapper' style='font-family: sans-serif; font-size: 14px; vertical-align: top; box-sizing: border-box; padding: 50px;' valign='top'>
<table border='0' cellpadding='0' cellspacing='0' style='border-collapse: separate; mso-table-lspace: 0pt; mso-table-rspace: 0pt; width: 100%;'>
<tr>
<td style='line-height: 24px; font-family: sans-serif; font-size: 14px; vertical-align: top;' valign='top'>
<h1 style='color: #392F54; font-family: sans-serif; font-weight: bold; line-height: 1.4; font-size: 24px; text-align: left; text-transform: capitalize; margin: 0 0 30px;' align='left'>
Запрошен сброс пароля
</h1>
<p style='color: #392F54; font-family: sans-serif; font-size: 14px; font-weight: normal; margin: 0 0 15px;'>
Ваше имя пользователя для входа в административную панель Umbraco: <strong>%0%</strong>
</p>
<p style='color: #392F54; font-family: sans-serif; font-size: 14px; font-weight: normal; margin: 0 0 15px;'>
<table border='0' cellpadding='0' cellspacing='0' style='border-collapse: separate; mso-table-lspace: 0pt; mso-table-rspace: 0pt; width: auto;'>
<tbody>
<tr>
<td style='font-family: sans-serif; font-size: 14px; vertical-align: top; border-radius: 5px; text-align: center; background: #35C786;' align='center' bgcolor='#35C786' valign='top'>
<a href='%1%' target='_blank' style='color: #FFFFFF; text-decoration: none; -ms-word-break: break-all; word-break: break-all; border-radius: 5px; box-sizing: border-box; cursor: pointer; display: inline-block; font-size: 14px; font-weight: bold; text-transform: capitalize; background: #35C786; margin: 0; padding: 12px 30px; border: 1px solid #35c786;'>
Нажмите на эту ссылку для того, чтобы сбросить пароль
</a>
</td>
</tr>
</tbody>
</table>
</p>
<p style='max-width: 400px; display: block; color: #392F54; font-family: sans-serif; font-size: 14px; line-height: 20px; font-weight: normal; margin: 15px 0;'>Если Вы не имеете возможности нажать на сслыку, скопируйте следующий адрес (URL) и вставьте в адресную строку Вашего браузера:</p>
<table border='0' cellpadding='0' cellspacing='0'>
<tr>
<td style='-ms-word-break: break-all; word-break: break-all; font-family: sans-serif; font-size: 11px; line-height:14px;'>
<font style="-ms-word-break: break-all; word-break: break-all; font-size: 11px; line-height:14px;">
<a style='-ms-word-break: break-all; word-break: break-all; color: #392F54; text-decoration: underline; font-size: 11px; line-height:15px;' href='%1%'>%1%</a>
</font>
</td>
</tr>
</table>
</p>
</td>
</tr>
</table>
</td>
</tr>
</table>
<br><br><br>
</div>
</td>
<td style='font-family: sans-serif; font-size: 14px; vertical-align: top;' valign='top'> </td>
</tr>
</table>
</body>
</html>
]]>
</key>
</area>
<area alias="main">
@@ -988,6 +1126,11 @@
<key alias="maxFileSize">Максимально допустимый размер файла: </key>
<key alias="mediaRoot">Начальный узел медиа</key>
</area>
<area alias="mediaPicker">
<key alias="pickedTrashedItem">Выбран медиа-элемент, который в настоящее время удален или находится в корзине</key>
<key alias="pickedTrashedItems">Выбраны медиа-элементы, которые в настоящее время удалены или находятся в корзине</key>
<key alias="deletedItem">Удаленный элемент</key>
</area>
<area alias="member">
<key alias="createNewMember">Создать нового участника</key>
<key alias="allMembers">Все участники</key>
@@ -1027,34 +1170,88 @@
Удачи!
Генератор уведомлений Umbraco.
]]></key>
<key alias="mailBodyHtml"><![CDATA[<p>Здравствуйте, %0%</p>
<p>Это автоматически сгенерированное уведомление. Операция <strong>'%1%'</strong>
была произведена на странице <a href="http://%4%/actions/preview.aspx?id=%5%"><strong>'%2%'</strong></a>
пользователем <strong>'%3%'</strong>.</p>
<div style="margin: 8px 0; padding: 8px; display: block;">
<br />
<a style="color: white; font-weight: bold; background-color: #5372c3; text-decoration : none; margin-right: 20px; border: 8px solid #5372c3; width: 150px;" href="http://%4%/#/content/content/edit/%5%">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ИЗМЕНИТЬ&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</a> &nbsp;
<br />
</div>
<p>
<h3>Сводка обновлений:</h3>
<table style="width: 100%;">
%6%
</table>
</p>
<div style="margin: 8px 0; padding: 8px; display: block;">
<br />
<a style="color: white; font-weight: bold; background-color: #5372c3; text-decoration : none; margin-right: 20px; border: 8px solid #5372c3; width: 150px;" href="http://%4%/#/content/content/edit/%5%">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ИЗМЕНИТЬ&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</a> &nbsp;
<br />
</div>
<p>Удачи!<br /><br />Генератор уведомлений Umbraco
</p>]]></key>
]]>
</key>
<key alias="mailBodyHtml">
<![CDATA[
<html>
<head>
<meta name='viewport' content='width=device-width'>
<meta http-equiv='Content-Type' content='text/html; charset=UTF-8'>
</head>
<body class='' style='font-family: sans-serif; -webkit-font-smoothing: antialiased; font-size: 14px; color: #392F54; line-height: 22px; -ms-text-size-adjust: 100%; -webkit-text-size-adjust: 100%; background: #1d1333; margin: 0; padding: 0;' bgcolor='#1d1333'>
<style type='text/css'> @media only screen and (max-width: 620px) {table[class=body] h1 {font-size: 28px !important; margin-bottom: 10px !important; } table[class=body] .wrapper {padding: 32px !important; } table[class=body] .article {padding: 32px !important; } table[class=body] .content {padding: 24px !important; } table[class=body] .container {padding: 0 !important; width: 100% !important; } table[class=body] .main {border-left-width: 0 !important; border-radius: 0 !important; border-right-width: 0 !important; } table[class=body] .btn table {width: 100% !important; } table[class=body] .btn a {width: 100% !important; } table[class=body] .img-responsive {height: auto !important; max-width: 100% !important; width: auto !important; } } .btn-primary table td:hover {background-color: #34495e !important; } .btn-primary a:hover {background-color: #34495e !important; border-color: #34495e !important; } .btn a:visited {color:#FFFFFF;} </style>
<table border="0" cellpadding="0" cellspacing="0" class="body" style="border-collapse: separate; mso-table-lspace: 0pt; mso-table-rspace: 0pt; width: 100%; background: #1d1333;" bgcolor="#1d1333">
<tr>
<td style="font-family: sans-serif; font-size: 14px; vertical-align: top; padding: 24px;" valign="top">
<table style="border-collapse: separate; mso-table-lspace: 0pt; mso-table-rspace: 0pt; width: 100%;">
<tr>
<td background="https://umbraco.com/umbraco/assets/img/application/logo.png" bgcolor="#1d1333" width="28" height="28" valign="top" style="font-family: sans-serif; font-size: 14px; vertical-align: top;">
<!--[if gte mso 9]> <v:rect xmlns:v="urn:schemas-microsoft-com:vml" fill="true" stroke="false" style="width:30px;height:30px;"> <v:fill type="tile" src="https://umbraco.com/umbraco/assets/img/application/logo.png" color="#1d1333" /> <v:textbox inset="0,0,0,0"> <![endif]-->
<div> </div>
<!--[if gte mso 9]> </v:textbox> </v:rect> <![endif]-->
</td>
<td style="font-family: sans-serif; font-size: 14px; vertical-align: top;" valign="top"></td>
</tr>
</table>
</td>
</tr>
</table>
<table border='0' cellpadding='0' cellspacing='0' class='body' style='border-collapse: separate; mso-table-lspace: 0pt; mso-table-rspace: 0pt; width: 100%; background: #1d1333;' bgcolor='#1d1333'>
<tr>
<td style='font-family: sans-serif; font-size: 14px; vertical-align: top;' valign='top'> </td>
<td class='container' style='font-family: sans-serif; font-size: 14px; vertical-align: top; display: block; max-width: 560px; width: 560px; margin: 0 auto; padding: 10px;' valign='top'>
<div class='content' style='box-sizing: border-box; display: block; max-width: 560px; margin: 0 auto; padding: 10px;'>
<br>
<table class='main' style='border-collapse: separate; mso-table-lspace: 0pt; mso-table-rspace: 0pt; width: 100%; border-radius: 3px; background: #FFFFFF;' bgcolor='#FFFFFF'>
<tr>
<td class='wrapper' style='font-family: sans-serif; font-size: 14px; vertical-align: top; box-sizing: border-box; padding: 50px;' valign='top'>
<table border='0' cellpadding='0' cellspacing='0' style='border-collapse: separate; mso-table-lspace: 0pt; mso-table-rspace: 0pt; width: 100%;'>
<tr>
<td style='line-height: 24px; font-family: sans-serif; font-size: 14px; vertical-align: top;' valign='top'>
<h1 style='color: #392F54; font-family: sans-serif; font-weight: bold; line-height: 1.4; font-size: 24px; text-align: left; text-transform: capitalize; margin: 0 0 30px;' align='left'>
Здравствуйте, %0%,
</h1>
<p style='color: #392F54; font-family: sans-serif; font-size: 14px; font-weight: normal; margin: 0 0 15px;'>
Это автоматически сгенерированное сообщение, отправленное, чтобы уведомить Вас о том, что операция <strong>'%1%'</strong> была выполнена на странице <a style="color: #392F54; text-decoration: none; -ms-word-break: break-all; word-break: break-all;" href="http://%4%/#/content/content/edit/%5%"><strong>'%2%'</strong></a> пользователем <strong>'%3%'</strong>
</p>
<table border='0' cellpadding='0' cellspacing='0' class='btn btn-primary' style='border-collapse: separate; mso-table-lspace: 0pt; mso-table-rspace: 0pt; width: 100%; box-sizing: border-box;'>
<tbody>
<tr>
<td align='left' style='font-family: sans-serif; font-size: 14px; vertical-align: top; padding-bottom: 15px;' valign='top'>
<table border='0' cellpadding='0' cellspacing='0' style='border-collapse: separate; mso-table-lspace: 0pt; mso-table-rspace: 0pt; width: auto;'><tbody><tr>
<td style='font-family: sans-serif; font-size: 14px; vertical-align: top; border-radius: 5px; text-align: center; background: #35C786;' align='center' bgcolor='#35C786' valign='top'>
<a href='http://%4%/#/content/content/edit/%5%' target='_blank' style='color: #FFFFFF; text-decoration: none; -ms-word-break: break-all; word-break: break-all; border-radius: 5px; box-sizing: border-box; cursor: pointer; display: inline-block; font-size: 14px; font-weight: bold; text-transform: capitalize; background: #35C786; margin: 0; padding: 12px 30px; border: 1px solid #35c786;'>ВНЕСТИ ИЗМЕНЕНИЯ</a> </td> </tr></tbody></table>
</td>
</tr>
</tbody>
</table>
<p style='color: #392F54; font-family: sans-serif; font-size: 14px; font-weight: normal; margin: 0 0 15px;'>
<h3>Обзор обновления:</h3>
<table style="width: 100%;">
%6%
</table>
</p>
<p style='color: #392F54; font-family: sans-serif; font-size: 14px; font-weight: normal; margin: 0 0 15px;'>
Удачного дня!<br /><br />
К Вашим услугам, почтовый робот Umbraco
</p>
</td>
</tr>
</table>
</td>
</tr>
</table>
<br><br><br>
</div>
</td>
<td style='font-family: sans-serif; font-size: 14px; vertical-align: top;' valign='top'> </td>
</tr>
</table>
</body>
</html>
]]>
</key>
<key alias="mailSubject">[%0%] Уведомление об операции %1% над документом %2%</key>
<key alias="notifications">Уведомления</key>
</area>
@@ -1409,6 +1606,8 @@
<key alias="unlockUsersError">При разблокировке пользователей произошла ошибка</key>
<key alias="unlockUserSuccess">'%0%' сейчас разблокирован</key>
<key alias="unlockUserError">При разблокировке пользователя произошла ошибка</key>
<key alias="memberExportedSuccess">Данные участника успешно экспортированы в файл</key>
<key alias="memberExportedError">Во время экспортирования данных участника произошла ошибка</key>
</area>
<area alias="stylesheet">
<key alias="aliasHelp">Используется синтаксис селекторов CSS, например: h1, .redHeader, .blueTex</key>
@@ -1682,9 +1881,103 @@
<key alias="failedPasswordAttempts">Неудачных попыток входа</key>
<key alias="goToProfile">К профилю пользователя</key>
<key alias="groupsHelp">Добавьте пользователя в группу(ы) для задания прав доступа</key>
<key alias="invite">Пригласить</key>
<key alias="inviteEmailCopySubject">Приглашение в панель администрирования Umbraco</key>
<key alias="inviteEmailCopyFormat">
<![CDATA[<html><body><p>Здравствуйте, %0%,<br><br>Вы были приглашены пользователем %1%, и Вам предоставлен доступ в панель администрирования Umbraco.</p><p>Сообщение от %1%: <em>%2%</em></p><p>Перейдите по <a href="%3%" target="_blank">этой ссылке</a>, чтобы принять приглашение.</p><p><small>Если Вы не имеете возможности перейти по ссылке, скопируйте нижеследующий текст ссылки и вставьте в адресную строку Вашего браузера.<br/><br/>%3%</small></p></body></html>]]>
<![CDATA[
<html>
<head>
<meta name='viewport' content='width=device-width'>
<meta http-equiv='Content-Type' content='text/html; charset=UTF-8'>
</head>
<body class='' style='font-family: sans-serif; -webkit-font-smoothing: antialiased; font-size: 14px; color: #392F54; line-height: 22px; -ms-text-size-adjust: 100%; -webkit-text-size-adjust: 100%; background: #1d1333; margin: 0; padding: 0;' bgcolor='#1d1333'>
<style type='text/css'> @media only screen and (max-width: 620px) {table[class=body] h1 {font-size: 28px !important; margin-bottom: 10px !important; } table[class=body] .wrapper {padding: 32px !important; } table[class=body] .article {padding: 32px !important; } table[class=body] .content {padding: 24px !important; } table[class=body] .container {padding: 0 !important; width: 100% !important; } table[class=body] .main {border-left-width: 0 !important; border-radius: 0 !important; border-right-width: 0 !important; } table[class=body] .btn table {width: 100% !important; } table[class=body] .btn a {width: 100% !important; } table[class=body] .img-responsive {height: auto !important; max-width: 100% !important; width: auto !important; } } .btn-primary table td:hover {background-color: #34495e !important; } .btn-primary a:hover {background-color: #34495e !important; border-color: #34495e !important; } .btn a:visited {color:#FFFFFF;} </style>
<table border="0" cellpadding="0" cellspacing="0" class="body" style="border-collapse: separate; mso-table-lspace: 0pt; mso-table-rspace: 0pt; width: 100%; background: #1d1333;" bgcolor="#1d1333">
<tr>
<td style="font-family: sans-serif; font-size: 14px; vertical-align: top; padding: 24px;" valign="top">
<table style="border-collapse: separate; mso-table-lspace: 0pt; mso-table-rspace: 0pt; width: 100%;">
<tr>
<td background="https://umbraco.com/umbraco/assets/img/application/logo.png" bgcolor="#1d1333" width="28" height="28" valign="top" style="font-family: sans-serif; font-size: 14px; vertical-align: top;">
<!--[if gte mso 9]> <v:rect xmlns:v="urn:schemas-microsoft-com:vml" fill="true" stroke="false" style="width:30px;height:30px;"> <v:fill type="tile" src="https://umbraco.com/umbraco/assets/img/application/logo.png" color="#1d1333" /> <v:textbox inset="0,0,0,0"> <![endif]-->
<div> </div>
<!--[if gte mso 9]> </v:textbox> </v:rect> <![endif]-->
</td>
<td style="font-family: sans-serif; font-size: 14px; vertical-align: top;" valign="top"></td>
</tr>
</table>
</td>
</tr>
</table>
<table border='0' cellpadding='0' cellspacing='0' class='body' style='border-collapse: separate; mso-table-lspace: 0pt; mso-table-rspace: 0pt; width: 100%; background: #1d1333;' bgcolor='#1d1333'>
<tr>
<td style='font-family: sans-serif; font-size: 14px; vertical-align: top;' valign='top'> </td>
<td class='container' style='font-family: sans-serif; font-size: 14px; vertical-align: top; display: block; max-width: 560px; width: 560px; margin: 0 auto; padding: 10px;' valign='top'>
<div class='content' style='box-sizing: border-box; display: block; max-width: 560px; margin: 0 auto; padding: 10px;'>
<br>
<table class='main' style='border-collapse: separate; mso-table-lspace: 0pt; mso-table-rspace: 0pt; width: 100%; border-radius: 3px; background: #FFFFFF;' bgcolor='#FFFFFF'>
<tr>
<td class='wrapper' style='font-family: sans-serif; font-size: 14px; vertical-align: top; box-sizing: border-box; padding: 50px;' valign='top'>
<table border='0' cellpadding='0' cellspacing='0' style='border-collapse: separate; mso-table-lspace: 0pt; mso-table-rspace: 0pt; width: 100%;'>
<tr>
<td style='line-height: 24px; font-family: sans-serif; font-size: 14px; vertical-align: top;' valign='top'>
<h1 style='color: #392F54; font-family: sans-serif; font-weight: bold; line-height: 1.4; font-size: 24px; text-align: left; text-transform: capitalize; margin: 0 0 30px;' align='left'>
Здравствуйте, %0%,
</h1>
<p style='color: #392F54; font-family: sans-serif; font-size: 14px; font-weight: normal; margin: 0 0 15px;'>
Вы были приглашены пользователем <a href="mailto:%4%" style="text-decoration: underline; color: #392F54; -ms-word-break: break-all; word-break: break-all;">%1%</a> в панель администрирования веб-сайта.
</p>
<p style='color: #392F54; font-family: sans-serif; font-size: 14px; font-weight: normal; margin: 0 0 15px;'>
Сообщение от пользователя <a href="mailto:%1%" style="text-decoration: none; color: #392F54; -ms-word-break: break-all; word-break: break-all;">%1%</a>:
<br/>
<em>%2%</em>
</p>
<table border='0' cellpadding='0' cellspacing='0' class='btn btn-primary' style='border-collapse: separate; mso-table-lspace: 0pt; mso-table-rspace: 0pt; width: 100%; box-sizing: border-box;'>
<tbody>
<tr>
<td align='left' style='font-family: sans-serif; font-size: 14px; vertical-align: top; padding-bottom: 15px;' valign='top'>
<table border='0' cellpadding='0' cellspacing='0' style='border-collapse: separate; mso-table-lspace: 0pt; mso-table-rspace: 0pt; width: auto;'>
<tbody>
<tr>
<td style='font-family: sans-serif; font-size: 14px; vertical-align: top; border-radius: 5px; text-align: center; background: #35C786;' align='center' bgcolor='#35C786' valign='top'>
<a href='%3%' target='_blank' style='color: #FFFFFF; text-decoration: none; -ms-word-break: break-all; word-break: break-all; border-radius: 5px; box-sizing: border-box; cursor: pointer; display: inline-block; font-size: 14px; font-weight: bold; text-transform: capitalize; background: #35C786; margin: 0; padding: 12px 30px; border: 1px solid #35c786;'>
Нажмите на эту ссылку, чтобы принять приглашение
</a>
</td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
<p style='max-width: 400px; display: block; color: #392F54; font-family: sans-serif; font-size: 14px; line-height: 20px; font-weight: normal; margin: 15px 0;'>Если Вы не имеете возможности нажать на ссылку, скопируйте следующий адрес (URL) и вставьте в адресную строку Вашего браузера:</p>
<table border='0' cellpadding='0' cellspacing='0'>
<tr>
<td style='-ms-word-break: break-all; word-break: break-all; font-family: sans-serif; font-size: 11px; line-height:14px;'>
<font style="-ms-word-break: break-all; word-break: break-all; font-size: 11px; line-height:14px;">
<a style='-ms-word-break: break-all; word-break: break-all; color: #392F54; text-decoration: underline; font-size: 11px; line-height:15px;' href='%3%'>%3%</a>
</font>
</td>
</tr>
</table>
</p>
</td>
</tr>
</table>
</td>
</tr>
</table>
<br><br><br>
</div>
</td>
<td style='font-family: sans-serif; font-size: 14px; vertical-align: top;' valign='top'> </td>
</tr>
</table>
</body>
</html>
]]>
</key>
<key alias="inviteAnotherUser">Пригласить еще одного пользователя</key>
<key alias="inviteUser">Пригласить пользователя</key>
@@ -1735,7 +2028,7 @@
<key alias="sortNameDescending">Имя (Я-А)</key>
<key alias="sortCreateDateDescending">Сначала новые</key>
<key alias="sortCreateDateAscending">Сначала старые</key>
<key alias="sortLastLoginDateDescending">Недавно зашедшие</key>
<key alias="sortLastLoginDateDescending">Недавно заходившие</key>
<key alias="stateActive">Активные</key>
<key alias="stateAll">Все</key>
<key alias="stateDisabled">Отключенные</key>
@@ -372,7 +372,7 @@ namespace Umbraco.Web.Editors
{
if (loginInfo == null) throw new ArgumentNullException("loginInfo");
if (response == null) throw new ArgumentNullException("response");
ExternalSignInAutoLinkOptions autoLinkOptions = null;
//Here we can check if the provider associated with the request has been configured to allow
// new users (auto-linked external accounts). This would never be used with public providers such as
@@ -383,8 +383,10 @@ namespace Umbraco.Web.Editors
{
Logger.Warn<BackOfficeController>("Could not find external authentication provider registered: " + loginInfo.Login.LoginProvider);
}
var autoLinkOptions = authType.GetExternalAuthenticationOptions();
else
{
autoLinkOptions = authType.GetExternalAuthenticationOptions();
}
// Sign in the user with this external login provider if the user already has a login
var user = await UserManager.FindAsync(loginInfo.Login);
@@ -268,6 +268,10 @@ namespace Umbraco.Web.Editors
"codeFileApiBaseUrl", _urlHelper.GetUmbracoApiServiceBaseUrl<CodeFileController>(
controller => controller.GetByPath("", ""))
},
{
"dictionaryApiBaseUrl", _urlHelper.GetUmbracoApiServiceBaseUrl<DictionaryController>(
controller => controller.DeleteById(int.MaxValue))
},
{
"helpApiBaseUrl", _urlHelper.GetUmbracoApiServiceBaseUrl<HelpController>(
controller => controller.GetContextHelpForPage("","",""))
@@ -276,6 +280,7 @@ namespace Umbraco.Web.Editors
"backOfficeAssetsApiBaseUrl", _urlHelper.GetUmbracoApiServiceBaseUrl<BackOfficeAssetsController>(
controller => controller.GetSupportedMomentLocales())
}
}
},
{
@@ -133,6 +133,22 @@ namespace Umbraco.Web.Editors
});
return Request.CreateResponse(result);
}
/// <summary>
/// Returns where a particular composition has been used
/// This has been wrapped in a dto instead of simple parameters to support having multiple parameters in post request body
/// </summary>
/// <param name="filter"></param>
/// <returns></returns>
[HttpPost]
public HttpResponseMessage GetWhereCompositionIsUsedInContentTypes(GetAvailableCompositionsFilter filter)
{
var result = PerformGetWhereCompositionIsUsedInContentTypes(filter.ContentTypeId, UmbracoObjectTypes.DocumentType)
.Select(x => new
{
contentType = x
});
return Request.CreateResponse(result);
}
[UmbracoTreeAuthorize(
Constants.Trees.DocumentTypes, Constants.Trees.Content,
@@ -311,8 +327,8 @@ namespace Umbraco.Web.Editors
{
basic.Name = localizedTextService.UmbracoDictionaryTranslate(basic.Name);
basic.Description = localizedTextService.UmbracoDictionaryTranslate(basic.Description);
}
}
//map the blueprints
var blueprints = Services.ContentService.GetBlueprintsForContentTypes(types.Select(x => x.Id).ToArray()).ToArray();
foreach (var basic in basics)
@@ -322,7 +338,7 @@ namespace Umbraco.Web.Editors
{
basic.Blueprints[blueprint.Id] = blueprint.Name;
}
}
}
return basics;
}
@@ -133,7 +133,66 @@ namespace Umbraco.Web.Editors
.ToList();
}
/// <summary>
/// Returns a list of content types where a particular composition content type is used
/// </summary>
/// <param name="type">Type of content Type, eg documentType or mediaType</param>
/// <param name="contentTypeId">Id of composition content type</param>
/// <returns></returns>
protected IEnumerable<EntityBasic> PerformGetWhereCompositionIsUsedInContentTypes(int contentTypeId,
UmbracoObjectTypes type)
{
IContentTypeComposition source = null;
//below is all ported from the old doc type editor and comes with the same weaknesses /insanity / magic
IContentTypeComposition[] allContentTypes;
switch (type)
{
case UmbracoObjectTypes.DocumentType:
if (contentTypeId > 0)
{
source = Services.ContentTypeService.GetContentType(contentTypeId);
if (source == null) throw new HttpResponseException(Request.CreateResponse(HttpStatusCode.NotFound));
}
allContentTypes = Services.ContentTypeService.GetAllContentTypes().Cast<IContentTypeComposition>().ToArray();
break;
case UmbracoObjectTypes.MediaType:
if (contentTypeId > 0)
{
source = Services.ContentTypeService.GetMediaType(contentTypeId);
if (source == null) throw new HttpResponseException(Request.CreateResponse(HttpStatusCode.NotFound));
}
allContentTypes = Services.ContentTypeService.GetAllMediaTypes().Cast<IContentTypeComposition>().ToArray();
break;
case UmbracoObjectTypes.MemberType:
if (contentTypeId > 0)
{
source = Services.MemberTypeService.Get(contentTypeId);
if (source == null) throw new HttpResponseException(Request.CreateResponse(HttpStatusCode.NotFound));
}
allContentTypes = Services.MemberTypeService.GetAll().Cast<IContentTypeComposition>().ToArray();
break;
default:
throw new ArgumentOutOfRangeException("The entity type was not a content type");
}
var contentTypesWhereCompositionIsUsed = Services.ContentTypeService.GetWhereCompositionIsUsedInContentTypes(source, allContentTypes);
return contentTypesWhereCompositionIsUsed
.Select(x => Mapper.Map<IContentTypeComposition, EntityBasic>(x))
.Select(x =>
{
//translate the name
x.Name = TranslateItem(x.Name);
return x;
})
.ToList();
}
protected string TranslateItem(string text)
{
if (text == null)
@@ -479,4 +538,4 @@ namespace Umbraco.Web.Editors
}
}
}
@@ -0,0 +1,234 @@
using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Http;
using System.Web.Http;
using AutoMapper;
using Umbraco.Core.Models;
using Umbraco.Web.Models.ContentEditing;
using Umbraco.Web.Mvc;
using Umbraco.Web.UI;
using Umbraco.Web.WebApi;
using Umbraco.Web.WebApi.Filters;
using Constants = Umbraco.Core.Constants;
using Notification = Umbraco.Web.Models.ContentEditing.Notification;
namespace Umbraco.Web.Editors
{
/// <inheritdoc />
/// <summary>
/// The API controller used for editing dictionary items
/// </summary>
/// <remarks>
/// The security for this controller is defined to allow full CRUD access to dictionary if the user has access to either:
/// Dictionar
/// </remarks>
[PluginController("UmbracoApi")]
[UmbracoTreeAuthorize(Constants.Trees.Dictionary)]
[EnableOverrideAuthorization]
public class DictionaryController : BackOfficeNotificationsController
{
/// <summary>
/// Deletes a data type wth a given ID
/// </summary>
/// <param name="id"></param>
/// <returns><see cref="HttpResponseMessage"/></returns>
[HttpDelete]
[HttpPost]
public HttpResponseMessage DeleteById(int id)
{
var foundDictionary = Services.LocalizationService.GetDictionaryItemById(id);
if (foundDictionary == null)
throw new HttpResponseException(HttpStatusCode.NotFound);
Services.LocalizationService.Delete(foundDictionary, Security.CurrentUser.Id);
return Request.CreateResponse(HttpStatusCode.OK);
}
/// <summary>
/// Creates a new dictoinairy item
/// </summary>
/// <param name="parentId">
/// The parent id.
/// </param>
/// <param name="key">
/// The key.
/// </param>
/// <returns>
/// The <see cref="HttpResponseMessage"/>.
/// </returns>
[HttpPost]
public HttpResponseMessage Create(int parentId, string key)
{
if (string.IsNullOrEmpty(key))
return Request
.CreateNotificationValidationErrorResponse("Key can not be empty;"); // TODO translate
if (Services.LocalizationService.DictionaryItemExists(key))
{
var message = Services.TextService.Localize(
"dictionaryItem/changeKeyError",
Security.CurrentUser.GetUserCulture(Services.TextService),
new Dictionary<string, string> { { "0", key } });
return Request.CreateNotificationValidationErrorResponse(message);
}
try
{
Guid? parentGuid = null;
if (parentId > 0)
parentGuid = Services.LocalizationService.GetDictionaryItemById(parentId).Key;
var item = Services.LocalizationService.CreateDictionaryItemWithIdentity(
key,
parentGuid,
string.Empty);
return Request.CreateResponse(HttpStatusCode.OK, item.Id);
}
catch (Exception exception)
{
Logger.Error(GetType(), "Error creating dictionary", exception);
return Request.CreateNotificationValidationErrorResponse("Error creating dictionary item");
}
}
/// <summary>
/// Gets a dictionary item by id
/// </summary>
/// <param name="id">
/// The id.
/// </param>
/// <returns>
/// The <see cref="DictionaryDisplay"/>.
/// </returns>
/// <exception cref="HttpResponseException">
/// Returrns a not found response when dictionary item does not exist
/// </exception>
public DictionaryDisplay GetById(int id)
{
var dictionary = Services.LocalizationService.GetDictionaryItemById(id);
if (dictionary == null)
throw new HttpResponseException(HttpStatusCode.NotFound);
return Mapper.Map<IDictionaryItem, DictionaryDisplay>(dictionary);
}
/// <summary>
/// Saves a dictionary item
/// </summary>
/// <param name="dictionary">
/// The dictionary.
/// </param>
/// <returns>
/// The <see cref="DictionaryDisplay"/>.
/// </returns>
public DictionaryDisplay PostSave(DictionarySave dictionary)
{
var dictionaryItem =
Services.LocalizationService.GetDictionaryItemById(int.Parse(dictionary.Id.ToString()));
if (dictionaryItem == null)
throw new HttpResponseException(Request.CreateNotificationValidationErrorResponse("Dictionary item does not exist"));
var userCulture = Security.CurrentUser.GetUserCulture(Services.TextService);
if (dictionary.NameIsDirty)
{
// if the name (key) has changed, we need to check if the new key does not exist
var dictionaryByKey = Services.LocalizationService.GetDictionaryItemByKey(dictionary.Name);
if (dictionaryByKey != null && dictionaryItem.Id != dictionaryByKey.Id)
{
var message = Services.TextService.Localize(
"dictionaryItem/changeKeyError",
userCulture,
new Dictionary<string, string> { { "0", dictionary.Name } });
ModelState.AddModelError("Name", message);
throw new HttpResponseException(Request.CreateValidationErrorResponse(ModelState));
}
dictionaryItem.ItemKey = dictionary.Name;
}
foreach (var translation in dictionary.Translations)
{
Services.LocalizationService.AddOrUpdateDictionaryValue(dictionaryItem,
Services.LocalizationService.GetLanguageById(translation.LanguageId), translation.Translation);
}
try
{
Services.LocalizationService.Save(dictionaryItem);
var model = Mapper.Map<IDictionaryItem, DictionaryDisplay>(dictionaryItem);
model.Notifications.Add(new Notification(
Services.TextService.Localize("speechBubbles/dictionaryItemSaved", userCulture), string.Empty,
SpeechBubbleIcon.Success));
return model;
}
catch (Exception e)
{
Logger.Error(GetType(), "Error saving dictionary", e);
throw new HttpResponseException(Request.CreateNotificationValidationErrorResponse("Something went wrong saving dictionary"));
}
}
/// <summary>
/// Retrieves a list with all dictionary items
/// </summary>
/// <returns>
/// The <see cref="IEnumerable{T}"/>.
/// </returns>
public IEnumerable<DictionaryOverviewDisplay> GetList()
{
var list = new List<DictionaryOverviewDisplay>();
const int level = 0;
foreach (var dictionaryItem in Services.LocalizationService.GetRootDictionaryItems())
{
var item = Mapper.Map<IDictionaryItem, DictionaryOverviewDisplay>(dictionaryItem);
item.Level = 0;
list.Add(item);
GetChildItemsForList(dictionaryItem, level + 1, list);
}
return list;
}
/// <summary>
/// Get child items for list.
/// </summary>
/// <param name="dictionaryItem">
/// The dictionary item.
/// </param>
/// <param name="level">
/// The level.
/// </param>
/// <param name="list">
/// The list.
/// </param>
private void GetChildItemsForList(IDictionaryItem dictionaryItem, int level, List<DictionaryOverviewDisplay> list)
{
foreach (var childItem in Services.LocalizationService.GetDictionaryItemChildren(
dictionaryItem.Key))
{
var item = Mapper.Map<IDictionaryItem, DictionaryOverviewDisplay>(childItem);
item.Level = level;
list.Add(item);
GetChildItemsForList(childItem, level + 1, list);
}
}
}
}
+14 -1
View File
@@ -1,9 +1,11 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Text;
using System.Threading;
using System.Web.Http;
using System.Web.SessionState;
using AutoMapper;
@@ -115,6 +117,17 @@ namespace Umbraco.Web.Editors
//the 'easiest' way might be to create an IPublishedContent manually and populate the legacy 'page' object with that
//and then set the legacy parameters.
// When rendering the macro in the backoffice the default setting would be to use the Culture of the logged in user.
// Since a Macro might contain thing thats related to the culture of the "IPublishedContent" (ie Dictionary keys) we want
// to set the current culture to the culture related to the content item. This is hacky but it works.
var publishedContent = UmbracoContext.ContentCache.GetById(doc.Id);
var culture = publishedContent?.GetCulture();
if (culture != null)
{
Thread.CurrentThread.CurrentCulture = culture;
Thread.CurrentThread.CurrentUICulture = culture;
}
var legacyPage = new global::umbraco.page(doc);
UmbracoContext.HttpContext.Items["pageID"] = doc.Id;
UmbracoContext.HttpContext.Items["pageElements"] = legacyPage.Elements;
@@ -158,4 +171,4 @@ namespace Umbraco.Web.Editors
public string VirtualPath { get; set; }
}
}
}
}

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