- All property types & property data
- using this data type will be deleted permanently, please confirm you want to delete these as well.
+ All property types & property data
+ using this data type will be deleted permanently, please confirm you want to delete these as well.
- Select the folder to move {{currentNode.name}} to in the tree structure below
+ Select the folder to move{{currentNode.name}}to in the tree structure below
@@ -17,7 +17,7 @@
-
{{currentNode.name}} was moved underneath {{target.name}}
+
{{currentNode.name}}was moved underneath{{target.name}}
diff --git a/src/Umbraco.Web.UI.Client/src/views/packager/views/install-local.controller.js b/src/Umbraco.Web.UI.Client/src/views/packager/views/install-local.controller.js
index b540df524c..566345b68e 100644
--- a/src/Umbraco.Web.UI.Client/src/views/packager/views/install-local.controller.js
+++ b/src/Umbraco.Web.UI.Client/src/views/packager/views/install-local.controller.js
@@ -1,7 +1,7 @@
(function () {
"use strict";
- function PackagesInstallLocalController($scope, $route, $location, Upload, umbRequestHelper, packageResource, localStorageService, $timeout, $window, localizationService) {
+ function PackagesInstallLocalController($scope, $route, $location, Upload, umbRequestHelper, packageResource, localStorageService, $timeout, $window, localizationService, $q) {
var vm = this;
vm.state = "upload";
@@ -117,10 +117,37 @@
.then(function(pack) {
vm.installState.progress = "25";
vm.installState.status = localizationService.localize("packager_installStateInstalling");
- vm.installState.progress = "50";
return packageResource.installFiles(pack);
},
installError)
+ .then(function(pack) {
+ vm.installState.status = localizationService.localize("packager_installStateRestarting");
+ vm.installState.progress = "50";
+ var deferred = $q.defer();
+
+ //check if the app domain is restarted ever 2 seconds
+ var count = 0;
+ function checkRestart() {
+ $timeout(function () {
+ packageResource.checkRestart(pack).then(function (d) {
+ count++;
+ //if there is an id it means it's not restarted yet but we'll limit it to only check 10 times
+ if (d.isRestarting && count < 10) {
+ checkRestart();
+ }
+ else {
+ //it's restarted!
+ deferred.resolve(d);
+ }
+ },
+ installError);
+ }, 2000);
+ }
+
+ checkRestart();
+
+ return deferred.promise;
+ }, installError)
.then(function(pack) {
vm.installState.status = localizationService.localize("packager_installStateRestarting");
vm.installState.progress = "75";
diff --git a/src/Umbraco.Web.UI.Client/src/views/packager/views/install-local.html b/src/Umbraco.Web.UI.Client/src/views/packager/views/install-local.html
index 1ef87baf83..b265a346b3 100644
--- a/src/Umbraco.Web.UI.Client/src/views/packager/views/install-local.html
+++ b/src/Umbraco.Web.UI.Client/src/views/packager/views/install-local.html
@@ -24,7 +24,7 @@
- Drop to upload
+ Drop to upload
- - or click here to choose files
+ - or click here to choose files
@@ -42,9 +42,9 @@
-
Upload package
+
Upload package
- Install a local package by selecting it from your machine. Only install packages from sources you know and trust.
+ Install a local package by selecting it from your machine. Only install packages from sources you know and trust.
- This package cannot be installed, it requires a minimum Umbraco version of {{vm.localPackage.umbracoVersion}}
+ This package cannot be installed, it requires a minimum Umbraco version of {{vm.localPackage.umbracoVersion}}
You don’t have any packages installed. Either install a local package by selecting it from your machine, or browse through available packages using the "Package" icon in the top right of your screen."
+
You don’t have any packages installed.
+
You don’t have any packages installed. Either install a local package by selecting it from your machine, or browse through available packages using the "Packages" icon in the top right of your screen.
This package is compatible with the following versions of Umbraco, as reported by community members. Full compatability cannot be gauranteed for versions reported below 100%
+
Compatibility
+
This package is compatible with the following versions of Umbraco, as reported by community members. Full compatability cannot be gauranteed for versions reported below 100%
- This package cannot be installed, it requires a minimum Umbraco version of {{vm.localPackage.umbracoVersion}}
+ This package cannot be installed, it requires a minimum Umbraco version of {{vm.localPackage.umbracoVersion}}
- Required
+ Required{{datePickerForm.datepicker.errorMsg}}
- Invalid date
+ Invalid date
This translates to the following time on the server: {{serverTime}}
diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/decimal/decimal.html b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/decimal/decimal.html
index 64730bbfb2..9b619bc6b5 100644
--- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/decimal/decimal.html
+++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/decimal/decimal.html
@@ -1,4 +1,4 @@
-
+
- Not a number
+ Not a number{{propertyForm.requiredField.errorMsg}}
-
- Tab:
- Select the tab who's properties should be displayed. If left blank, the first tab on the doc type will be used.
+ Tab:
+ Select the tab who's properties should be displayed. If left blank, the first tab on the doc type will be used.
- Name template:
+ Template:
Enter an angular expression to evaluate against each item for its name. Use {{$index}} to display the item index
\ No newline at end of file
diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/nestedcontent/nestedcontent.html b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/nestedcontent/nestedcontent.html
index 4799167452..bc3e4547b9 100644
--- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/nestedcontent/nestedcontent.html
+++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/nestedcontent/nestedcontent.html
@@ -26,7 +26,7 @@
-
+
diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/rte/rte.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/rte/rte.controller.js
index 45e8856132..485b674594 100644
--- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/rte/rte.controller.js
+++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/rte/rte.controller.js
@@ -1,6 +1,6 @@
angular.module("umbraco")
.controller("Umbraco.PropertyEditors.RTEController",
- function ($rootScope, $scope, $q, dialogService, $log, imageHelper, assetsService, $timeout, tinyMceService, angularHelper, stylesheetResource, macroService) {
+ function ($rootScope, $scope, $q, $locale, dialogService, $log, imageHelper, assetsService, $timeout, tinyMceService, angularHelper, stylesheetResource, macroService) {
$scope.isLoading = true;
@@ -100,9 +100,45 @@ angular.module("umbraco")
//stores a reference to the editor
var tinyMceEditor = null;
+ // these languages are available for localization
+ var availableLanguages = [
+ 'da',
+ 'de',
+ 'en',
+ 'en_us',
+ 'fi',
+ 'fr',
+ 'he',
+ 'it',
+ 'ja',
+ 'nl',
+ 'no',
+ 'pl',
+ 'pt',
+ 'ru',
+ 'sv',
+ 'zh'
+ ];
+
+ //define fallback language
+ var language = 'en_us';
+ //get locale from angular and match tinymce format. Angular localization is always in the format of ru-ru, de-de, en-gb, etc.
+ //wheras tinymce is in the format of ru, de, en, en_us, etc.
+ var localeId = $locale.id.replace('-', '_');
+ //try matching the language using full locale format
+ var languageMatch = _.find(availableLanguages, function(o) { return o === localeId; });
+ //if no matches, try matching using only the language
+ if (languageMatch === undefined) {
+ var localeParts = localeId.split('_');
+ languageMatch = _.find(availableLanguages, function(o) { return o === localeParts[0]; });
+ }
+ //if a match was found - set the language
+ if (languageMatch !== undefined) {
+ language = languageMatch;
+ }
+
//wait for queue to end
$q.all(await).then(function () {
-
//create a baseline Config to exten upon
var baseLineConfigObj = {
mode: "exact",
@@ -119,10 +155,10 @@ angular.module("umbraco")
toolbar: toolbar,
content_css: stylesheets,
relative_urls: false,
- style_formats: styleFormats
+ style_formats: styleFormats,
+ language: language
};
-
if (tinyMceConfig.customConfig) {
//if there is some custom config, we need to see if the string value of each item might actually be json and if so, we need to
@@ -295,10 +331,7 @@ angular.module("umbraco")
});
};
-
-
-
-
+
/** Loads in the editor */
function loadTinyMce() {
diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/rte/rte.html b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/rte/rte.html
index 656f5b7490..774f860c31 100644
--- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/rte/rte.html
+++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/rte/rte.html
@@ -1,5 +1,5 @@
-
-
Loading...
+
+
Loading...
diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/textarea/textarea.html b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/textarea/textarea.html
index 0d1fae3f6f..aba4c52ed3 100644
--- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/textarea/textarea.html
+++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/textarea/textarea.html
@@ -1,3 +1,3 @@
-
-Required
-
\ No newline at end of file
+
+Required
+
diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/textbox/textbox.html b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/textbox/textbox.html
index c55fc350fa..1848574f8b 100644
--- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/textbox/textbox.html
+++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/textbox/textbox.html
@@ -1,9 +1,9 @@
-
+
- Required
+ Required
diff --git a/src/Umbraco.Web.UI.Client/test/config/karma.conf.js b/src/Umbraco.Web.UI.Client/test/config/karma.conf.js
index ede7c20538..0e06085ff4 100644
--- a/src/Umbraco.Web.UI.Client/test/config/karma.conf.js
+++ b/src/Umbraco.Web.UI.Client/test/config/karma.conf.js
@@ -32,7 +32,7 @@ module.exports = function(karma) {
'test/config/app.unit.js',
'src/common/mocks/umbraco.servervariables.js',
- 'src/common/directives/*.js',
+ 'src/common/directives/**/*.js',
'src/common/filters/*.js',
'src/common/services/*.js',
'src/common/security/*.js',
diff --git a/src/Umbraco.Web.UI.Client/test/unit/app/content/create-content-controller.spec.js b/src/Umbraco.Web.UI.Client/test/unit/app/content/create-content-controller.spec.js
new file mode 100644
index 0000000000..46f5a7bbc9
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/test/unit/app/content/create-content-controller.spec.js
@@ -0,0 +1,124 @@
+(function() {
+
+ describe("create content dialog",
+ function() {
+
+ var scope,
+ allowedTypes = [
+ { id: 1, alias: "x" },
+ { id: 2, alias: "y", blueprints: { "1": "a", "2": "b" } }
+ ],
+ location,
+ searcher,
+ controller,
+ rootScope,
+ contentTypeResource;
+
+ beforeEach(module("umbraco"));
+
+ function initialize(blueprintConfig) {
+ scope = rootScope.$new();
+ scope.currentNode = { id: 1234 };
+ var dependencies = {
+ $scope: scope,
+ contentTypeResource: contentTypeResource
+ };
+ if (blueprintConfig) {
+ dependencies.blueprintConfig = blueprintConfig;
+ }
+ controller("Umbraco.Editors.Content.CreateController",
+ dependencies);
+
+ scope.$digest();
+
+ }
+
+ beforeEach(inject(function($controller, $rootScope, $q, $location) {
+ contentTypeResource = {
+ getAllowedTypes: function() {
+ var def = $q.defer();
+ def.resolve(allowedTypes);
+ return def.promise;
+ }
+ };
+ location = $location;
+ controller = $controller;
+ rootScope = $rootScope;
+
+ searcher = { search: function() {} };
+ spyOn(location, "path").andReturn(searcher);
+ spyOn(searcher, "search");
+
+ initialize();
+ }));
+
+ it("shows available child document types for the given node",
+ function() {
+ expect(scope.selectContentType).toBe(true);
+ expect(scope.allowedTypes).toBe(allowedTypes);
+ });
+
+ it("creates content directly when there are no blueprints",
+ function() {
+ scope.createOrSelectBlueprintIfAny(allowedTypes[0]);
+
+ expect(location.path).toHaveBeenCalledWith("/content/content/edit/1234");
+ expect(searcher.search).toHaveBeenCalledWith("doctype=x&create=true");
+ });
+
+ it("shows list of blueprints when there are some",
+ function() {
+ scope.createOrSelectBlueprintIfAny(allowedTypes[1]);
+ expect(scope.selectContentType).toBe(false);
+ expect(scope.selectBlueprint).toBe(true);
+ expect(scope.docType).toBe(allowedTypes[1]);
+ });
+
+ it("creates blueprint when selected",
+ function() {
+ scope.createOrSelectBlueprintIfAny(allowedTypes[1]);
+ scope.createFromBlueprint("1");
+
+ expect(location.path).toHaveBeenCalledWith("/content/content/edit/1234");
+ expect(searcher.search).toHaveBeenCalledWith("doctype=y&create=true&blueprintId=1");
+ });
+
+ it("skips selection and creates first blueprint when configured to",
+ function() {
+ initialize({
+ allowBlank: true,
+ skipSelect: true
+ });
+
+ scope.createOrSelectBlueprintIfAny(allowedTypes[1]);
+
+ expect(location.path).toHaveBeenCalledWith("/content/content/edit/1234");
+ expect(searcher.search).toHaveBeenCalledWith("doctype=y&create=true&blueprintId=1");
+ });
+
+ it("allows blank to be selected",
+ function() {
+ expect(scope.allowBlank).toBe(true);
+ });
+
+ it("creates blank when selected",
+ function() {
+ scope.createBlank(allowedTypes[1]);
+
+ expect(location.path).toHaveBeenCalledWith("/content/content/edit/1234");
+ expect(searcher.search).toHaveBeenCalledWith("doctype=y&create=true");
+ });
+
+ it("hides blank when configured to",
+ function() {
+ initialize({
+ allowBlank: false,
+ skipSelect: false
+ });
+
+ expect(scope.allowBlank).toBe(false);
+ });
+
+ });
+
+}());
\ No newline at end of file
diff --git a/src/Umbraco.Web.UI.Client/test/unit/app/content/edit-content-controller.spec.js b/src/Umbraco.Web.UI.Client/test/unit/app/content/edit-content-controller.spec.js
index 0d9b8a29e2..ae3c33a19a 100644
--- a/src/Umbraco.Web.UI.Client/test/unit/app/content/edit-content-controller.spec.js
+++ b/src/Umbraco.Web.UI.Client/test/unit/app/content/edit-content-controller.spec.js
@@ -1,12 +1,16 @@
+// The content editor has been wrapped in a directive
+// The current setup will have problems with loading the HTML etc.
+// These tests are therefore ignored for now.
+
describe('edit content controller tests', function () {
- var scope, controller, routeParams, httpBackend;
+ var scope, controller, routeParams, httpBackend, wasSaved, q;
routeParams = {id: 1234, create: false};
beforeEach(module('umbraco'));
//inject the contentMocks service
- beforeEach(inject(function ($rootScope, $controller, angularHelper, $httpBackend, contentMocks, entityMocks, mocksUtils, localizationMocks) {
-
+ beforeEach(inject(function ($rootScope, $q, $controller, $compile, angularHelper, $httpBackend, contentMocks, entityMocks, mocksUtils, localizationMocks) {
+ q = $q;
//for these tests we don't want any authorization to occur
mocksUtils.disableAuth();
@@ -20,27 +24,32 @@ describe('edit content controller tests', function () {
localizationMocks.register();
//this controller requires an angular form controller applied to it
- scope.contentForm = angularHelper.getNullForm("contentForm");
-
- controller = $controller('Umbraco.Editors.Content.EditController', {
+ scope.contentForm = angularHelper.getNullForm("contentForm");
+
+ var deferred = $q.defer();
+ wasSaved = false;
+ scope.saveMethod = function() { wasSaved = true; };
+ scope.getMethod = function() { return function() { return deferred.promise; } };
+ scope.treeAlias = "content";
+
+ controller = $controller('Umbraco.Editors.Content.EditorDirectiveController', {
$scope: scope,
$routeParams: routeParams
});
//For controller tests its easiest to have the digest and flush happen here
//since its intially always the same $http calls made
-
- //scope.$digest resolves the promise against the httpbackend
- scope.$digest();
- //httpbackend.flush() resolves all request against the httpbackend
- //to fake a async response, (which is what happens on a real setup)
- httpBackend.flush();
+
+ // Resolve the get method
+ deferred.resolve(mocksUtils.getMockContent(1234));
+
+ //scope.$digest resolves the promise
+ scope.$digest();
}));
describe('content edit controller save and publish', function () {
- it('it should have an content object', function() {
-
+ it('it should have an content object', function() {
//controller should have a content object
expect(scope.content).toNotBe(undefined);
diff --git a/src/Umbraco.Web.UI/config/trees.config b/src/Umbraco.Web.UI/config/trees.config
index bad6931dd6..b237e957a3 100644
--- a/src/Umbraco.Web.UI/config/trees.config
+++ b/src/Umbraco.Web.UI/config/trees.config
@@ -16,6 +16,7 @@
+
diff --git a/src/Umbraco.Web.UI/umbraco/config/lang/en.xml b/src/Umbraco.Web.UI/umbraco/config/lang/en.xml
index e09f2dae90..3a149ebd73 100644
--- a/src/Umbraco.Web.UI/umbraco/config/lang/en.xml
+++ b/src/Umbraco.Web.UI/umbraco/config/lang/en.xml
@@ -40,6 +40,7 @@
TranslateUpdateDefault value
+ Create blueprintPermission denied.
@@ -177,6 +178,16 @@
TargetThis translates to the following time on the server:What does this mean?]]>
+ Are you sure you want to delete this item?
+ Property %0% uses editor %1% which is not supported by Nested Content.
+ Add another text box
+ Remove this text box
+ Create a blueprint from %0%
+ Blank
+ Select a blueprint
+ Blueprint created
+ Blueprint was created from %0%
+ Another Blueprint with the same name already exists.Click to upload
@@ -304,6 +315,7 @@
Link to pageOpens the linked document in a new window or tabLink to media
+ Link to fileSelect mediaSelect iconSelect item
@@ -320,9 +332,10 @@
StacktraceInner ExceptionLink your
- Un-Link your
+ Un-link youraccountSelect editor
+ Select snippetRelated stylesheetsShow labelWidth and height
+ All property types & property data
+ using this data type will be deleted permanently, please confirm you want to delete these as well
+ Yes, delete
+ and all property types & property data using this data type
+ Select the folder to move
+ to in the tree structure below
+ was moved underneathYour data has been saved, but before you can publish this page there are some errors you need to fix first:
@@ -438,6 +458,7 @@
Close WindowCommentConfirm
+ ConstrainConstrain proportionsContinueCopy
@@ -449,6 +470,7 @@
DeletedDeleting...Design
+ DictionaryDimensionsDownDownload
@@ -458,6 +480,7 @@
EmailErrorFind
+ FirstHeightHelpIcon
@@ -468,6 +491,7 @@
InvalidJustifyLanguage
+ LastLayoutLoadingLocked
@@ -495,6 +519,7 @@
Email to receive form dataRecycle BinRemaining
+ RemoveRenameRenewRequired
@@ -806,6 +831,39 @@ To manage your website, simply open the Umbraco back office and start adding con
Choose Package from your machine, by clicking the Browse
button and locating the package. Umbraco packages usually have a ".zip" extension.
]]>
+ Drop to upload
+ or click here to choose files
+ Upload package
+ Install a local package by selecting it from your machine. Only install packages from sources you know and trust
+ Upload another package
+ Cancel and upload another package
+ License
+ I accept
+ terms of use
+ Install package
+ Finish
+ Installed packages
+ You don’t have any packages installed
+ 'Packages' icon in the top right of your screen]]>
+ Search for packages
+ Results for
+ We couldn’t find anything for
+ Please try searching for another package or browse through the categories
+ Popular
+ New releases
+ has
+ karma points
+ Information
+ Owner
+ Contributors
+ Created
+ Current version
+ .NET version
+ Downloads
+ Likes
+ Compatibility
+ This package is compatible with the following versions of Umbraco, as reported by community members. Full compatability cannot be gauranteed for versions reported below 100%
+ External sourcesAuthorDemonstrationDocumentation
@@ -818,7 +876,7 @@ To manage your website, simply open the Umbraco back office and start adding con
Package optionsPackage readmePackage repository
- Confirm uninstall
+ Confirm package uninstallPackage was uninstalledThe package was successfully uninstalledUninstall package
@@ -833,14 +891,15 @@ To manage your website, simply open the Umbraco back office and start adding con
Package version historyView package websitePackage already installed
- This package cannot be installed, it requires a minimum Umbraco version of %0%
+ This package cannot be installed, it requires a minimum Umbraco version ofUninstalling...Downloading...Importing...Installing...Restarting, please wait...All done, your browser will now refresh, please wait...
- Please click finish to complete installation and reload page.
+ Please click 'Finish' to complete installation and reload the page.
+ Uploading package...Paste with full formatting (Not recommended)
@@ -908,6 +967,10 @@ To manage your website, simply open the Umbraco back office and start adding con
Reset
+ Define crop
+ Give the crop an alias and its default width and height
+ Save crop
+ Add new cropCurrent version
@@ -1118,6 +1181,7 @@ To manage your website, simply open the Umbraco back office and start adding con
Query builder
+ Build a queryitems returned, inI want
@@ -1263,34 +1327,46 @@ To manage your website, simply open the Umbraco back office and start adding con
+ Add fallback field
+ Fallback field
+ Add default value
+ Default valueAlternative fieldAlternative TextCasingEncodingChoose fieldConvert line breaks
- Replaces line breaks with html-tag <br>
+ Yes, convert line breaks
+ Replaces line breaks with 'br' html tagCustom Fields
- Yes, Date only
+ Date only
+ Format and encodingFormat as date
+ Format the value as a date, or a date with time, according to the active cultureHTML encodeWill replace special characters by their HTML equivalent.Will be inserted after the field valueWill be inserted before the field valueLowercase
+ Modify outputNone
+ Output sampleInsert after fieldInsert before fieldRecursive
- Remove Paragraph tags
- Will remove any <P> in the beginning and end of the text
+ Yes, make it recursive
+ Remove paragraph tags
+ Yes, remove paragraph tags
+ Will remove any paragraph tag in the beginning and end of the text
+ SeparatorStandard FieldsUppercaseURL encodeWill format special characters in URLsWill only be used when the field values above are emptyThis field will only be used if the primary field is empty
- Yes, with time. Separator:
+ Date and timeTasks assigned to you
@@ -1342,6 +1418,7 @@ To manage your website, simply open the Umbraco back office and start adding con
Upload translation XML
+ Content BlueprintsCache BrowserRecycle BinCreated packages
@@ -1439,12 +1516,20 @@ To manage your website, simply open the Umbraco back office and start adding con
- Validation
- Validate as email
- Validate as a number
- Validate as a Url
- ...or enter a custom validation
- Field is mandatory
+ Validation
+ Validate as email
+ Validate as a number
+ Validate as a Url
+ ...or enter a custom validation
+ Field is mandatory
+ Enter a regular expression
+ You need to add at least
+ You can only have
+ items
+ items selected
+ Invalid date
+ Not a number
+ Invalid email
+ Wartość jest ustawiona na rekomendowaną wartość: '%0%'.
+ Wartość została ustawiona na '%1%' dla XPath '%2%' w pliku konfiguracyjnym '%3%'.
+ Oczekiwana jest wartość '%1%' dla '%2%' w pliku konfiguracyjnym '%3%', ale znaleziono '%0%'.
+ Znaleziono nieoczekiwaną wartość '%0%' dla '%2%' w pliku konfiguracyjnym '%3%'.
+
+
+ Niestandardowe błędy są ustawione na '%0%'.
+ Niestandardowe błędy są obecnie ustawione na '%0%'. Zaleca się ustawienie ich na '%1%' przed wypuszczeniem strony na produkcję.
+ Niestandardowe błędy zostały z powodzeniem ustawione na '%0%'.
+
+ MacroErrors są ustawione na '%0%'.
+ MacroErrors są ustawione na '%0%' co uniemożliwi częściowe lub całkowite załadowanie stron w Twojej witrynie jeśli wystąpią jakiekolwiek błędy w makro. Korekta ustawi wartość na '%1%'.
+ MacroErrors są teraz ustawione na '%0%'.
+
+
+ Try Skip IIS Custom Errors jest ustawione na '%0%' a Ty używasz IIS w wersji '%1%'.
+ Try Skip IIS Custom Errors wynosi obecnie '%0%'. Zalecane jest ustawienie go na '%1%' dla Twojego IIS w wersji (%2%).
+ Try Skip IIS Custom Errors ustawiono z powodzeniem na '%0%'.
+
+
+ Plik nie istnieje: '%0%'.
+ '%0%' w pliku konfiguracyjnym '%1%'.]]>
+ Wystąpił błąd, sprawdź logi, aby wyświetlić pełen opis błędu: %0%.
+
+ Członkowie - Suma XML: %0%, Suma: %1%, Suma niepoprawnych: %2%
+ Media - Suma XML: %0%, Suma: %1%, Suma niepoprawnych: %2%
+ Zawartość - Suma XML: %0%, Suma opublikowanych: %1%, Suma niepoprawnych: %2%
+
+ Certifikat Twojej strony został oznaczony jako poprawny.
+ Błąd walidacji certyfikatu: '%0%'
+ Błąd pingowania adresu URL %0% - '%1%'
+ Oglądasz %0% stronę używając HTTPS.
+ appSetting 'umbracoUseSSL' został ustawiony na 'false' w Twoim pliku web.config. Po uzyskaniu dostępu do strony, używając HTTPS, powinieneś go ustawić na 'true'.
+ appSetting 'umbracoUseSSL' został ustawiony na '%0%' w Twoim pliku web.config, Twoje ciasteczka są %1% ustawione jako bezpieczne.
+ Nie można zaktualizaować ustawień 'umbracoUseSSL' w Twoim pliku web.config file. Błąd: %0%
+
+
+ Włącz HTTPS
+ Ustawia umbracoSSL na 'true' w appSettings pliku web.config.
+ appSetting 'umbracoUseSSL' jest teraz ustawione na 'true' w Twoim pliku web.config, Twoje ciasteczka będą oznaczone jako bezpieczne.
+
+ Napraw
+ Nie można naprawić sprawdzenia z wartością typu porównania 'ShouldNotEqual'.
+ Nie można naprawić sprawdzenia z wartością typu porównania 'ShouldEqual' z wprowadzoną wartością.
+ Nie wprowadzono wartości do naprawy sprawdzenia.
+
+ Tryb kompilacji debugowania jest wyłączony.
+ Tryb kompilacji debugowania jest obecnie włączony. Zaleca się wyłączenie tego ustawienia przed wypuszczeniem strony na produkcję.
+ Tryb komplikacji debugowania został wyłączony z powodzeniem.
+
+ Tryb śledzenia jest wyłączony.
+ Tryb śledzenia jest obecnie włączony. Zaleca się wyłączenie tego ustawienia przed wypuszczeniem strony na produkcję.
+ Tryb śledzenia został wyłączony z powodzeniem
+
+ Wszystkie foldery mają ustawione poprawne ustawienia.
+
+ %0%.]]>
+ %0%. Jeśli nie będzie nic w nich pisane, żadne działania nie muszą być podejmowane.]]>
+
+ Wszystkie pliki mają ustawione poprawne uprawnienia.
+
+ %0%.]]>
+ %0%. Jeśli nie będzie nic w nich pisane, żadne działania nie muszą być podejmowane.]]>
+
+ X-Frame-Options używany do kontrolowania czy strona może być IFRAME'owana przez inną został znaleziony.]]>
+ X-Frame-Options używany do kontrolowania czy strona może być IFRAME'owana przez inną nie został znaleziony.]]>
+ Ustaw nagłówek w Config
+ Dodaje wartość do sekcji httpProtocol/customHeaders pliku web.config, aby zapobiec IFRAME'owania strony przez inne witryny.
+ Ustawienie do tworzenia nagłówka, zapobiegającego IFRAME'owania strony przez inne witryny zostało dodane do Twojego pliku web.config.
+ Nie można zaktualizować pliku web.config. Błąd: %0%
+
+
+ %0%.]]>
+ Nie znaleziono żadnych nagłówków, ujawniających informacji o technologii strony.
+
+ Nie znaleziono system.net/mailsettings w pliku Web.config.
+ Host nie jest skonfigurowany w sekcji system.net/mailsettings pliku Web.config.
+ Ustawienia SMTP są skonfigurowane poprawnie i serwis działa według oczekiwań.
+ Nie można połączyć się z serwerem SMTP skonfigurowanym z hostem '%0%' i portem '%1%'. Proszę sprawdzić ponownie, czy ustawienia system.net/mailsettings w pliku Web.config są poprawne.
+
+ %0%.]]>
+ %0%.]]>
+
+
+ Wyłącz śledzenie URL
+ Włącz śledzenie URL
+ Oryginalny URL
+ Przekierowane do
+ Nie stworzono żadnych przekierowań
+ Kiedy nazwa opublikowanej strony zostanie zmieniona lub zostanie ona przeniesiona, zostanie stworzone automatyczne przekierowanie na nową stronę.
+ Usuń
+ Czy jesteś pewien, że chcesz usunąć przekierowanie z '%0%' do '%1%'?
+ Przekierowanie URL zostało usunięte.
+ Wystąpił błąd podczas usuwania przekierowania URL.
+ Czy jesteś pewien, że chcesz wyłączyć śledzenie URL?
+ Śledzenie URL zostało wyłączone.
+ Wystąpił błąd podczas wyłączania śledzenia URL, więcej informacji znajdziesz w pliku z logami.
+ Śledzenie URL zostało włączone.
+ Wystąpił błąd podczas włączania śledzenia URL, więcej informacji znajdziesz w pliku z logami.
+
+
+ Brak elementów słownika do wyboru
+
+
diff --git a/src/Umbraco.Web.UI/umbraco/config/lang/ru.xml b/src/Umbraco.Web.UI/umbraco/config/lang/ru.xml
index 991a2c7024..1a0d55b6c4 100644
--- a/src/Umbraco.Web.UI/umbraco/config/lang/ru.xml
+++ b/src/Umbraco.Web.UI/umbraco/config/lang/ru.xml
@@ -187,12 +187,12 @@
Ссылка на медиа-элементыТип медиа-контентаГруппа участников
- Член групп(ы)
+ Включен в группу(ы)Роль участникаТип участникаДата не указанаЗаголовок ссылки
- Не является членом групп(ы)
+ Доступные группыСвойстваЭтот документ опубликован, но скрыт, потому что его родительский документ '%0%' не опубликованВНИМАНИЕ: этот документ опубликован, но его нет в глобальном кэше (внутренняя ошибка - подробности в системном журнале)
@@ -216,13 +216,15 @@
ОбновленоУдалить файлСсылка на документ
+ Добавить новое поле текста
+ Удалить это поле текстаКомпозицииВы не добавили ни одной вкладкиДобавить вкладкуДобавить новую вкладку
- Унаследован от
+ Унаследовано отДобавить свойствоОбязательная метка
@@ -364,6 +366,7 @@
Выбрать участникаВыбрать группу участниковЭто макрос без параметров
+ Нет макросов доступных для вставки в редакторПровайдеры аутентификацииПодробное сообщение об ошибкеТрассировка стека
@@ -372,6 +375,7 @@
Разорвать связьучетную записьВыбрать редактор
+ Выбрать образецСопоставленные стили CSSПоказать меткуШирина и высота
+ ВСЕ типы свойств и данные в свойствах документов,
+ использующие этот тип данных, будут удалены безвозвратно, подтвердите их удаление
+ Да, можно удалить
+ и все типы свойств и данные свойств, использующие этот тип данных
+ Выберите папку, чтобы переместить в нее
+ в структуре дерева ниже
+ был перемещен в папкуНет доступных элементов словаря
@@ -487,6 +498,7 @@
УдаленоУдаляется...Дизайн
+ СловарьРазмерыВнизСкачать
@@ -496,6 +508,7 @@
Email адресОшибкаНайти
+ НачалоПапкаВысотаСправка
@@ -508,6 +521,7 @@
ВыравниваниеНазваниеЯзык
+ КонецМакетЗагрузкаБЛОКИРОВКА
@@ -520,7 +534,7 @@
ПереместитьНазваниеНовый
- Следующий
+ СледНетизOk
@@ -530,12 +544,13 @@
ПутьИдентификатор контейнераМинуточку...
- Предыдущий
+ ПредСвойстваEmail адрес для получения данныхКорзинаВаша корзина пустаОсталось
+ УдалитьПереименоватьОбновитьОбязательное
@@ -731,6 +746,10 @@
Сбросить
+ Задать рамку
+ Задайте рамке имя (алиас), а также ширину и высоту по-умолчанию
+ Сохранить рамку
+ Добавить новую рамкуПрограмма установки не может установить подключение к базе данных.
@@ -968,6 +987,39 @@
Выберите файл пакета на своем компьютере, нажав на кнопку 'Обзор'
и указав на нужный файл. Пакеты Umbraco обычно являются архивами с расширением ".umb" или ".zip".
]]>
+ Перетащите сюда
+ или нажмите здесь для выбора файла пакета
+ Загрузить пакет
+ Установите локальный пакет из файла, расположенного на Вашем компьютере. Остерегайтесь устанавливать пакеты из непроверенных источников!
+ Загрузить еще один пакет
+ Отменить и загрузить другой пакет
+ Лицензия
+ Я принимаю
+ условия использования
+ Установить пакет
+ Завершить
+ Установленные пакеты
+ Ни одного пакета еще не установлено
+ 'Packages' наверху справа]]>
+ Поиск по пакетам
+ Результаты поиска по
+ Ничего не найдено по запросу
+ Пожалуйста, повторите поиск, уточнив запрос, или воспользуйтесь просмотром по категориям
+ Популярные
+ Недавно созданные
+ имеет на счету
+ очков кармы
+ Информация
+ Владелец
+ Соавторы
+ Создан
+ Текущая версия
+ Версия .NET
+ Загрузок
+ Нравится
+ Совместимость
+ Этот пакет совместим со следующими версиями Umbraco, по сообщениям участников сообщества. Полная совместимость не гарантируется для версий со значением ниже 100%
+ Внешние источникиАвторДемонстрацияДокументация (описание)
@@ -980,7 +1032,7 @@
Опции пакетаКраткий обзор пакетаРепозиторий пакета
- Подтверждение деинсталляции
+ Подтверждение деинсталляции пакетаПакет деинсталлированУказанный пакет успешно удален из системыДеинсталлировать пакет
@@ -995,14 +1047,15 @@
История версий пакетаПерейти на веб-сайт пакетаЭтот пакет уже установлен в системе
- Этот пакет не может быть установлен, он требует наличия Umbraco версии как минимум %0%
+ Этот пакет не может быть установлен, он требует наличия Umbraco версии как минимумУдаление...Загрузка...Импорт...Установка...Перезапуск, подождите, пожалуйста...Все готово, сейчас браузер перезагрузит страницу, подождите, пожалуйста...
- Пожалуйста, нажмите кнопку 'finish' для завершения установки и перезагрузки страницы.
+ Пожалуйста, нажмите кнопку 'Завершить' для завершения установки и перезагрузки страницы.
+ Загрузка пакета...Вставить, полностью сохранив форматирование (не рекомендуется)
@@ -1184,7 +1237,7 @@
Порядок сортировкиДата созданияСортировка завершена
- Перетаскивайте элементы на нужное место вверх или вниз для определения необходимого Вам порядка сортировки. Также можно щелкнуть по заголовкам столбцов, чтобы отсортировать все элементы сразу.
+ Перетаскивайте элементы на нужное место вверх или вниз для определения необходимого Вам порядка сортировки. Также можно использовать заголовки столбцов, чтобы отсортировать все элементы сразу. Не закрывайте это окно до окончания процесса сортировки.]]>
@@ -1330,6 +1383,7 @@
Генератор запросов
+ Построить запросэлементов в результате, заМне нужны
@@ -1367,34 +1421,42 @@
Шаблон
+ Добавить поле замены
+ Добавить значение по-умолчаниюАльтернативное поле
- Альтернативный текст
+ Текст по-умолчаниюРегистрВыбрать полеПреобразовать переводы строк
- Заменяет переводы строк на тэг html <br>
+ Заменяет переводы строк на тэг html 'br'ПользовательскиеТолько датаКодировка
+ Форматирование и кодировкаФорматировать как дату
+ Форматировать значение как дату, или как дату и время, в соответствии с текущей культуройКодировка HTMLЗаменяет спецсимволы эквивалентами в формате HTMLБудет добавлено после поляБудет вставлено перед полемВ нижнем регистре
+ Модификации при выводе-Не указано-
+ Пример результатаВставить после поляВставить перед полемРекурсивно
+ Да, использовать рекурсиюУдалить тэги параграфов
- Удаляются тэги <p> в начале и в конце абзацев
+ Удаляются тэги параграфа ('p') в начале и в конце абзацев
+ РазделительСтандартныеВ верхнем регистреКодирование URLФорматирование специальных символов в URLЭто значение будет использовано только если предыдущие поля пустыЭто значение будет использовано только если первичное поле пусто
- Дата и время. Разделитель:
+ Дата и времяЗадачи, назначенные Вам
@@ -1535,5 +1597,13 @@
Валидация по формату Url...или указать свои правила валидацииОбязательно к заполнению
+ Задайте регулярное выражение
+ Необходимо выбрать как минимум
+ Возможно выбрать максимум
+ элементов
+ элементов
+ Неверный формат даты
+ Не является числом
+ неверный формат email-адреса
diff --git a/src/Umbraco.Web/Editors/BackOfficeController.cs b/src/Umbraco.Web/Editors/BackOfficeController.cs
index b371142fcc..d7e9464c4a 100644
--- a/src/Umbraco.Web/Editors/BackOfficeController.cs
+++ b/src/Umbraco.Web/Editors/BackOfficeController.cs
@@ -767,11 +767,19 @@ namespace Umbraco.Web.Editors
return app;
}
-
+
+ ///
+ /// A lazy reference to all tree controller types
+ ///
+ ///
+ /// We are doing this because if we constantly resolve the tree controller types from the PluginManager it will re-scan and also re-log that
+ /// it's resolving which is unecessary and annoying.
+ ///
+ private static readonly Lazy> TreeControllerTypes = new Lazy>(() => PluginManager.Current.ResolveAttributedTreeControllers().ToArray());
private IEnumerable> GetTreePluginsMetaData()
{
- var treeTypes = PluginManager.Current.ResolveAttributedTreeControllers();
+ var treeTypes = TreeControllerTypes.Value;
//get all plugin trees with their attributes
var treesWithAttributes = treeTypes.Select(x => new
{
diff --git a/src/Umbraco.Web/Editors/ContentController.cs b/src/Umbraco.Web/Editors/ContentController.cs
index 8f8731bb66..b828bf420d 100644
--- a/src/Umbraco.Web/Editors/ContentController.cs
+++ b/src/Umbraco.Web/Editors/ContentController.cs
@@ -24,6 +24,7 @@ using Umbraco.Web.WebApi.Binders;
using Umbraco.Web.WebApi.Filters;
using umbraco.cms.businesslogic.web;
using umbraco.presentation.preview;
+using Umbraco.Core.Events;
using Constants = Umbraco.Core.Constants;
namespace Umbraco.Web.Editors
@@ -104,6 +105,36 @@ namespace Umbraco.Web.Editors
return display;
}
+ public ContentItemDisplay GetBlueprintById(int id)
+ {
+ var foundContent = Services.ContentService.GetBlueprintById(id);
+ if (foundContent == null)
+ {
+ HandleContentNotFound(id);
+ }
+
+ var content = Mapper.Map(foundContent);
+
+ SetupBlueprint(content, foundContent);
+
+ return content;
+ }
+
+ private static void SetupBlueprint(ContentItemDisplay content, IContent persistedContent)
+ {
+ content.AllowPreview = false;
+
+ //set a custom path since the tree that renders this has the content type id as the parent
+ content.Path = string.Format("-1,{0},{1}", persistedContent.ContentTypeId, content.Id);
+
+ content.AllowedActions = new[] {'A'};
+
+ var excludeProps = new[] {"_umb_urls", "_umb_releasedate", "_umb_expiredate", "_umb_template"};
+ var propsTab = content.Tabs.Last();
+ propsTab.Properties = propsTab.Properties
+ .Where(p => excludeProps.Contains(p.Alias) == false);
+ }
+
///
/// Gets the content json for the content id
///
@@ -163,6 +194,26 @@ namespace Umbraco.Web.Editors
return mapped;
}
+ [OutgoingEditorModelEvent]
+ public ContentItemDisplay GetEmpty(int blueprintId)
+ {
+ var blueprint = Services.ContentService.GetBlueprintById(blueprintId);
+ if (blueprint == null)
+ {
+ throw new HttpResponseException(HttpStatusCode.NotFound);
+ }
+
+ blueprint.Id = 0;
+ blueprint.Name = string.Empty;
+
+ var mapped = Mapper.Map(blueprint);
+
+ //remove this tab if it exists: umbContainerView
+ var containerTab = mapped.Tabs.FirstOrDefault(x => x.Alias == Constants.Conventions.PropertyGroups.ListViewGroupName);
+ mapped.Tabs = mapped.Tabs.Except(new[] { containerTab });
+ return mapped;
+ }
+
///
/// Gets the Url for a given node ID
///
@@ -275,6 +326,69 @@ namespace Umbraco.Web.Editors
return false;
}
+ ///
+ /// Creates a blueprint from a content item
+ ///
+ /// The content id to copy
+ /// The name of the blueprint
+ ///
+ [HttpPost]
+ public SimpleNotificationModel CreateBlueprintFromContent([FromUri]int contentId, [FromUri]string name)
+ {
+ if (string.IsNullOrWhiteSpace(name)) throw new ArgumentException("Value cannot be null or whitespace.", "name");
+
+ var content = Services.ContentService.GetById(contentId);
+ if (content == null)
+ throw new HttpResponseException(Request.CreateResponse(HttpStatusCode.NotFound));
+
+ EnsureUniqueName(name, content, "name");
+
+ var blueprint = Services.ContentService.CreateContentFromBlueprint(content, name, Security.GetUserId());
+
+ Services.ContentService.SaveBlueprint(blueprint, Security.GetUserId());
+
+ var notificationModel = new SimpleNotificationModel();
+ notificationModel.AddSuccessNotification(
+ Services.TextService.Localize("content/createdBlueprintHeading"),
+ Services.TextService.Localize("content/createdBlueprintMessage", new[]{ content.Name})
+ );
+
+ return notificationModel;
+ }
+
+ private void EnsureUniqueName(string name, IContent content, string modelName)
+ {
+ var existing = Services.ContentService.GetBlueprintsForContentTypes(content.ContentTypeId);
+ if (existing.Any(x => x.Name == name && x.Id != content.Id))
+ {
+ ModelState.AddModelError(modelName, Services.TextService.Localize("content/duplicateBlueprintMessage"));
+ throw new HttpResponseException(Request.CreateValidationErrorResponse(ModelState));
+ }
+ }
+
+ ///
+ /// Saves content
+ ///
+ ///
+ [FileUploadCleanupFilter]
+ [ContentPostValidate]
+ public ContentItemDisplay PostSaveBlueprint(
+ [ModelBinder(typeof(ContentItemBinder))] ContentItemSave contentItem)
+ {
+ var contentItemDisplay = PostSaveInternal(contentItem,
+ content =>
+ {
+ EnsureUniqueName(content.Name, content, "Name");
+
+ Services.ContentService.SaveBlueprint(contentItem.PersistedContent, Security.CurrentUser.Id);
+ //we need to reuse the underlying logic so return the result that it wants
+ return Attempt.Succeed(new OperationStatus(OperationStatusType.Success, new EventMessages()));
+ });
+ SetupBlueprint(contentItemDisplay, contentItemDisplay.PersistedContent);
+
+ return contentItemDisplay;
+ }
+
///
/// Saves content
///
@@ -284,6 +398,12 @@ namespace Umbraco.Web.Editors
public ContentItemDisplay PostSave(
[ModelBinder(typeof(ContentItemBinder))]
ContentItemSave contentItem)
+ {
+ return PostSaveInternal(contentItem,
+ content => Services.ContentService.WithResult().Save(contentItem.PersistedContent, Security.CurrentUser.Id));
+ }
+
+ private ContentItemDisplay PostSaveInternal(ContentItemSave contentItem, Func> saveMethod)
{
//If we've reached here it means:
// * Our model has been bound
@@ -291,7 +411,6 @@ namespace Umbraco.Web.Editors
// * any file attachments have been saved to their temporary location for us to use
// * we have a reference to the DTO object and the persisted object
// * Permissions are valid
-
MapPropertyValues(contentItem);
//We need to manually check the validation results here because:
@@ -331,7 +450,7 @@ namespace Umbraco.Web.Editors
if (contentItem.Action == ContentSaveAction.Save || contentItem.Action == ContentSaveAction.SaveNew)
{
//save the item
- var saveResult = Services.ContentService.WithResult().Save(contentItem.PersistedContent, Security.CurrentUser.Id);
+ var saveResult = saveMethod(contentItem.PersistedContent);
wasCancelled = saveResult.Success == false && saveResult.Result.StatusType == OperationStatusType.FailedCancelledByEvent;
}
@@ -361,8 +480,8 @@ namespace Umbraco.Web.Editors
if (wasCancelled == false)
{
display.AddSuccessNotification(
- Services.TextService.Localize("speechBubbles/editContentSavedHeader"),
- Services.TextService.Localize("speechBubbles/editContentSavedText"));
+ Services.TextService.Localize("speechBubbles/editContentSavedHeader"),
+ Services.TextService.Localize("speechBubbles/editContentSavedText"));
}
else
{
@@ -374,8 +493,8 @@ namespace Umbraco.Web.Editors
if (wasCancelled == false)
{
display.AddSuccessNotification(
- Services.TextService.Localize("speechBubbles/editContentSendToPublish"),
- Services.TextService.Localize("speechBubbles/editContentSendToPublishText"));
+ Services.TextService.Localize("speechBubbles/editContentSendToPublish"),
+ Services.TextService.Localize("speechBubbles/editContentSendToPublishText"));
}
else
{
@@ -398,8 +517,10 @@ namespace Umbraco.Web.Editors
throw new HttpResponseException(Request.CreateValidationErrorResponse(display));
}
+ display.PersistedContent = contentItem.PersistedContent;
+
return display;
- }
+ }
///
/// Publishes a document with a given ID
@@ -434,6 +555,22 @@ namespace Umbraco.Web.Editors
}
+ [HttpDelete]
+ [HttpPost]
+ public HttpResponseMessage DeleteBlueprint(int id)
+ {
+ var found = Services.ContentService.GetBlueprintById(id);
+
+ if (found == null)
+ {
+ return HandleContentNotFound(id, false);
+ }
+
+ Services.ContentService.DeleteBlueprint(found);
+
+ return Request.CreateResponse(HttpStatusCode.OK);
+ }
+
///
/// Moves an item to the recycle bin, if it is already there then it will permanently delete it
///
diff --git a/src/Umbraco.Web/Editors/ContentTypeController.cs b/src/Umbraco.Web/Editors/ContentTypeController.cs
index 720eca184b..f0e67ac14b 100644
--- a/src/Umbraco.Web/Editors/ContentTypeController.cs
+++ b/src/Umbraco.Web/Editors/ContentTypeController.cs
@@ -302,7 +302,18 @@ 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)
+ {
+ var docTypeBluePrints = blueprints.Where(x => x.ContentTypeId == (int) basic.Id).ToArray();
+ foreach (var blueprint in docTypeBluePrints)
+ {
+ basic.Blueprints[blueprint.Id] = blueprint.Name;
+ }
+ }
return basics;
}
diff --git a/src/Umbraco.Web/Editors/PackageInstallController.cs b/src/Umbraco.Web/Editors/PackageInstallController.cs
index d3771ce82c..6b5f460171 100644
--- a/src/Umbraco.Web/Editors/PackageInstallController.cs
+++ b/src/Umbraco.Web/Editors/PackageInstallController.cs
@@ -543,6 +543,26 @@ namespace Umbraco.Web.Editors
var ins = new global::umbraco.cms.businesslogic.packager.Installer(Security.CurrentUser.Id);
ins.LoadConfig(IOHelper.MapPath(model.TemporaryDirectoryPath));
ins.InstallFiles(model.Id, IOHelper.MapPath(model.TemporaryDirectoryPath));
+
+ //set a restarting marker and reset the app pool
+ ApplicationContext.RestartApplicationPool(Request.TryGetHttpContext().Result);
+
+ model.IsRestarting = true;
+
+ return model;
+ }
+
+ [HttpPost]
+ public PackageInstallModel CheckRestart(PackageInstallModel model)
+ {
+ if (model.IsRestarting == false) return model;
+
+ //check for the key, if it's not there we're are restarted
+ if (Request.TryGetHttpContext().Result.Application.AllKeys.Contains("AppPoolRestarting") == false)
+ {
+ //reset it
+ model.IsRestarting = false;
+ }
return model;
}
diff --git a/src/Umbraco.Web/Install/InstallHelper.cs b/src/Umbraco.Web/Install/InstallHelper.cs
index 8bc21a2334..6c088365a1 100644
--- a/src/Umbraco.Web/Install/InstallHelper.cs
+++ b/src/Umbraco.Web/Install/InstallHelper.cs
@@ -50,7 +50,7 @@ namespace Umbraco.Web.Install
new DatabaseConfigureStep(_umbContext.Application),
new DatabaseInstallStep(_umbContext.Application),
new DatabaseUpgradeStep(_umbContext.Application),
- new StarterKitDownloadStep(_umbContext.Application, _umbContext.Security),
+ new StarterKitDownloadStep(_umbContext.Application, _umbContext.Security, _umbContext.HttpContext),
new StarterKitInstallStep(_umbContext.Application, _umbContext.HttpContext),
new StarterKitCleanupStep(_umbContext.Application),
new SetUmbracoVersionStep(_umbContext.Application, _umbContext.HttpContext),
diff --git a/src/Umbraco.Web/Install/InstallSteps/StarterKitDownloadStep.cs b/src/Umbraco.Web/Install/InstallSteps/StarterKitDownloadStep.cs
index a8f55d3b2c..fd0c15bd61 100644
--- a/src/Umbraco.Web/Install/InstallSteps/StarterKitDownloadStep.cs
+++ b/src/Umbraco.Web/Install/InstallSteps/StarterKitDownloadStep.cs
@@ -11,16 +11,19 @@ using Umbraco.Web.Security;
namespace Umbraco.Web.Install.InstallSteps
{
[InstallSetupStep(InstallationType.NewInstall,
- "StarterKitDownload", "starterKit", 30, "Adding a simple website to Umbraco, will make it easier for you to get started")]
+ "StarterKitDownload", "starterKit", 30, "Adding a simple website to Umbraco, will make it easier for you to get started",
+ PerformsAppRestart = true)]
internal class StarterKitDownloadStep : InstallSetupStep
{
private readonly ApplicationContext _applicationContext;
private readonly WebSecurity _security;
+ private readonly HttpContextBase _httpContext;
- public StarterKitDownloadStep(ApplicationContext applicationContext, WebSecurity security)
+ public StarterKitDownloadStep(ApplicationContext applicationContext, WebSecurity security, HttpContextBase httpContext)
{
_applicationContext = applicationContext;
_security = security;
+ _httpContext = httpContext;
}
private const string RepoGuid = "65194810-1f85-11dd-bd0b-0800200c9a66";
@@ -46,6 +49,8 @@ namespace Umbraco.Web.Install.InstallSteps
var result = DownloadPackageFiles(starterKitId.Value);
+ _applicationContext.RestartApplicationPool(_httpContext);
+
return new InstallSetupResult(new Dictionary
{
{"manifestId", result.Item2},
diff --git a/src/Umbraco.Web/Models/ContentEditing/ContentTypeBasic.cs b/src/Umbraco.Web/Models/ContentEditing/ContentTypeBasic.cs
index 8dde1f1f97..938c7de657 100644
--- a/src/Umbraco.Web/Models/ContentEditing/ContentTypeBasic.cs
+++ b/src/Umbraco.Web/Models/ContentEditing/ContentTypeBasic.cs
@@ -1,4 +1,5 @@
using System;
+using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.Runtime.Serialization;
@@ -18,6 +19,11 @@ namespace Umbraco.Web.Models.ContentEditing
[DataContract(Name = "contentType", Namespace = "")]
public class ContentTypeBasic : EntityBasic
{
+ public ContentTypeBasic()
+ {
+ Blueprints = new Dictionary();
+ }
+
///
/// Overridden to apply our own validation attributes since this is not always required for other classes
///
@@ -105,5 +111,9 @@ namespace Umbraco.Web.Models.ContentEditing
: IOHelper.ResolveUrl("~/umbraco/images/thumbnails/" + Thumbnail);
}
}
+
+ [DataMember(Name = "blueprints")]
+ [ReadOnly(true)]
+ public IDictionary Blueprints { get; set; }
}
}
diff --git a/src/Umbraco.Web/Models/Mapping/ContentTypeModelMapper.cs b/src/Umbraco.Web/Models/Mapping/ContentTypeModelMapper.cs
index 24620509e9..1d9b4fedda 100644
--- a/src/Umbraco.Web/Models/Mapping/ContentTypeModelMapper.cs
+++ b/src/Umbraco.Web/Models/Mapping/ContentTypeModelMapper.cs
@@ -163,11 +163,14 @@ namespace Umbraco.Web.Models.Mapping
});
config.CreateMap()
- .ForMember(x => x.Udi, expression => expression.MapFrom(content => Udi.Create(Constants.UdiEntityType.MemberType, content.Key)));
+ .ForMember(x => x.Udi, expression => expression.MapFrom(content => Udi.Create(Constants.UdiEntityType.MemberType, content.Key)))
+ .ForMember(x => x.Blueprints, expression => expression.Ignore());
config.CreateMap()
- .ForMember(x => x.Udi, expression => expression.MapFrom(content => Udi.Create(Constants.UdiEntityType.MediaType, content.Key)));
+ .ForMember(x => x.Udi, expression => expression.MapFrom(content => Udi.Create(Constants.UdiEntityType.MediaType, content.Key)))
+ .ForMember(x => x.Blueprints, expression => expression.Ignore());
config.CreateMap()
- .ForMember(x => x.Udi, expression => expression.MapFrom(content => Udi.Create(Constants.UdiEntityType.DocumentType, content.Key)));
+ .ForMember(x => x.Udi, expression => expression.MapFrom(content => Udi.Create(Constants.UdiEntityType.DocumentType, content.Key)))
+ .ForMember(x => x.Blueprints, expression => expression.Ignore());
config.CreateMap()
diff --git a/src/Umbraco.Web/Models/Mapping/ContentTypeModelMapperExtensions.cs b/src/Umbraco.Web/Models/Mapping/ContentTypeModelMapperExtensions.cs
index 274771fead..00923c8655 100644
--- a/src/Umbraco.Web/Models/Mapping/ContentTypeModelMapperExtensions.cs
+++ b/src/Umbraco.Web/Models/Mapping/ContentTypeModelMapperExtensions.cs
@@ -129,6 +129,7 @@ namespace Umbraco.Web.Models.Mapping
return mapping
.ForMember(x => x.Udi, expression => expression.ResolveUsing(new ContentTypeUdiResolver()))
.ForMember(display => display.Notifications, expression => expression.Ignore())
+ .ForMember(display => display.Blueprints, expression => expression.Ignore())
.ForMember(display => display.Errors, expression => expression.Ignore())
.ForMember(display => display.AllowAsRoot, expression => expression.MapFrom(type => type.AllowedAsRoot))
.ForMember(display => display.ListViewEditorName, expression => expression.Ignore())
diff --git a/src/Umbraco.Web/Models/PackageInstallModel.cs b/src/Umbraco.Web/Models/PackageInstallModel.cs
index f903fc1880..7748129a40 100644
--- a/src/Umbraco.Web/Models/PackageInstallModel.cs
+++ b/src/Umbraco.Web/Models/PackageInstallModel.cs
@@ -24,6 +24,10 @@ namespace Umbraco.Web.Models
[DataMember(Name = "zipFilePath")]
public string ZipFilePath { get; set; }
-
+ ///
+ /// During installation this can be used to track any pending appdomain restarts
+ ///
+ [DataMember(Name = "isRestarting")]
+ public bool IsRestarting { get; set; }
}
}
diff --git a/src/Umbraco.Web/Trees/ContentBlueprintTreeController.cs b/src/Umbraco.Web/Trees/ContentBlueprintTreeController.cs
new file mode 100644
index 0000000000..ff029a020a
--- /dev/null
+++ b/src/Umbraco.Web/Trees/ContentBlueprintTreeController.cs
@@ -0,0 +1,114 @@
+using System;
+using System.Linq;
+using System.Collections.Generic;
+using System.Globalization;
+using System.Net;
+using System.Net.Http.Formatting;
+using System.Web.Http;
+using umbraco;
+using umbraco.businesslogic.Actions;
+using umbraco.BusinessLogic.Actions;
+using Umbraco.Core;
+using Umbraco.Core.Services;
+using Umbraco.Core.Models;
+using Umbraco.Core.Models.EntityBase;
+using Umbraco.Core.Persistence;
+using Umbraco.Web.Models.Trees;
+using Umbraco.Web.Mvc;
+using Umbraco.Web.WebApi.Filters;
+using Constants = Umbraco.Core.Constants;
+
+namespace Umbraco.Web.Trees
+{
+ ///
+ /// The content blueprint tree controller
+ ///
+ ///
+ /// This authorizes based on access to the content section even though it exists in the settings
+ ///
+ [UmbracoApplicationAuthorize(Constants.Applications.Content)]
+ [Tree(Constants.Applications.Settings, Constants.Trees.ContentBlueprints, null, sortOrder: 8)]
+ [PluginController("UmbracoTrees")]
+ [CoreTree]
+ public class ContentBlueprintTreeController : TreeController
+ {
+ protected override TreeNodeCollection GetTreeNodes(string id, FormDataCollection queryStrings)
+ {
+ var nodes = new TreeNodeCollection();
+
+ //get all blueprints
+ var entities = Services.EntityService.GetChildren(Constants.System.Root, UmbracoObjectTypes.DocumentBlueprint).ToArray();
+
+ //check if we're rendering the root in which case we'll render the content types that have blueprints
+ if (id == Constants.System.Root.ToInvariantString())
+ {
+ //get all blueprint content types
+ var contentTypeAliases = entities.Select(x => ((UmbracoEntity) x).ContentTypeAlias).Distinct();
+ //get the ids
+ var contentTypeIds = Services.ContentTypeService.GetAllContentTypeIds(contentTypeAliases.ToArray());
+ //now get the entities ... it's a bit round about but still smaller queries than getting all document types
+ var docTypeEntities = Services.EntityService.GetAll(UmbracoObjectTypes.DocumentType, contentTypeIds.ToArray()).ToArray();
+
+ nodes.AddRange(docTypeEntities
+ .Select(entity =>
+ {
+ var treeNode = CreateTreeNode(entity, Constants.ObjectTypes.DocumentBlueprintGuid, id, queryStrings, "icon-item-arrangement", true);
+ treeNode.Path = string.Format("-1,{0}", entity.Id);
+ treeNode.NodeType = "contentType";
+ //TODO: This isn't the best way to ensure a noop process for clicking a node but it works for now.
+ treeNode.AdditionalData["jsClickCallback"] = "javascript:void(0);";
+ return treeNode;
+ }));
+
+ return nodes;
+ }
+ else
+ {
+ var intId = id.TryConvertTo();
+ //Get the content type
+ var ct = Services.ContentTypeService.GetContentType(intId.Result);
+ if (ct == null) return nodes;
+
+ var blueprintsForDocType = entities.Where(x => ct.Alias == ((UmbracoEntity) x).ContentTypeAlias);
+ nodes.AddRange(blueprintsForDocType
+ .Select(entity =>
+ {
+ var treeNode = CreateTreeNode(entity, Constants.ObjectTypes.DocumentBlueprintGuid, id, queryStrings, "icon-blueprint", false);
+ treeNode.Path = string.Format("-1,{0},{1}", ct.Id, entity.Id);
+ return treeNode;
+ }));
+ }
+
+ return nodes;
+ }
+
+ protected override MenuItemCollection GetMenuForNode(string id, FormDataCollection queryStrings)
+ {
+ var menu = new MenuItemCollection();
+
+ if (id == Constants.System.Root.ToInvariantString())
+ {
+ // root actions
+ menu.Items.Add(Services.TextService.Localize(string.Format("actions/{0}", ActionRefresh.Instance.Alias)), true);
+ return menu;
+ }
+ var cte = Services.EntityService.Get(int.Parse(id), UmbracoObjectTypes.DocumentType);
+ //only refresh & create if it's a content type
+ if (cte != null)
+ {
+ var ct = Services.ContentTypeService.GetContentType(cte.Id);
+ var createItem = menu.Items.Add(Services.TextService.Localize(string.Format("actions/{0}", ActionCreateBlueprintFromContent.Instance.Alias)));
+ createItem.NavigateToRoute("/settings/contentBlueprints/edit/-1?create=true&doctype=" + ct.Alias);
+
+ menu.Items.Add(Services.TextService.Localize(string.Format("actions/{0}", ActionRefresh.Instance.Alias)), true);
+
+ return menu;
+ }
+
+ menu.Items.Add(Services.TextService.Localize(string.Format("actions/{0}", ActionDelete.Instance.Alias)));
+
+ return menu;
+ }
+
+ }
+}
\ No newline at end of file
diff --git a/src/Umbraco.Web/Trees/ContentTreeController.cs b/src/Umbraco.Web/Trees/ContentTreeController.cs
index b97f0d6bb0..9c15a8b462 100644
--- a/src/Umbraco.Web/Trees/ContentTreeController.cs
+++ b/src/Umbraco.Web/Trees/ContentTreeController.cs
@@ -16,6 +16,7 @@ using Umbraco.Web.WebApi.Filters;
using umbraco;
using umbraco.BusinessLogic.Actions;
using umbraco.businesslogic;
+using umbraco.businesslogic.Actions;
using umbraco.cms.businesslogic.web;
using umbraco.interfaces;
using Constants = Umbraco.Core.Constants;
@@ -227,7 +228,9 @@ namespace Umbraco.Web.Trees
var menu = new MenuItemCollection();
menu.Items.Add(ui.Text("actions", ActionNew.Instance.Alias));
menu.Items.Add(ui.Text("actions", ActionDelete.Instance.Alias));
-
+
+ menu.Items.Add(ui.Text("actions", ActionCreateBlueprintFromContent.Instance.Alias));
+
//need to ensure some of these are converted to the legacy system - until we upgrade them all to be angularized.
menu.Items.Add(ui.Text("actions", ActionMove.Instance.Alias), true);
menu.Items.Add(ui.Text("actions", ActionCopy.Instance.Alias));
diff --git a/src/Umbraco.Web/Umbraco.Web.csproj b/src/Umbraco.Web/Umbraco.Web.csproj
index 58df77c82d..51819e114f 100644
--- a/src/Umbraco.Web/Umbraco.Web.csproj
+++ b/src/Umbraco.Web/Umbraco.Web.csproj
@@ -473,6 +473,7 @@
+
diff --git a/src/Umbraco.Web/WebBootManager.cs b/src/Umbraco.Web/WebBootManager.cs
index 29565065e2..43d130529b 100644
--- a/src/Umbraco.Web/WebBootManager.cs
+++ b/src/Umbraco.Web/WebBootManager.cs
@@ -227,10 +227,12 @@ namespace Umbraco.Web
//Now ensure webapi is initialized after everything
GlobalConfiguration.Configuration.EnsureInitialized();
-
+
return this;
}
+
+
internal static void ConfigureGlobalFilters()
{
GlobalFilters.Filters.Add(new EnsurePartialViewMacroViewContextFilterAttribute());
diff --git a/src/umbraco.cms/Actions/ActionCreateBlueprintFromContent.cs b/src/umbraco.cms/Actions/ActionCreateBlueprintFromContent.cs
new file mode 100644
index 0000000000..43ce768b03
--- /dev/null
+++ b/src/umbraco.cms/Actions/ActionCreateBlueprintFromContent.cs
@@ -0,0 +1,35 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using umbraco.interfaces;
+
+namespace umbraco.businesslogic.Actions
+{
+ public class ActionCreateBlueprintFromContent : IAction
+ {
+ private static readonly ActionCreateBlueprintFromContent instance = new ActionCreateBlueprintFromContent();
+
+ public static ActionCreateBlueprintFromContent Instance
+ {
+ get { return instance; }
+ }
+
+ public char Letter { get; private set; }
+ public bool ShowInNotifier { get; private set; }
+ public bool CanBePermissionAssigned { get; private set; }
+ public string Icon { get; private set; }
+ public string Alias { get; private set; }
+ public string JsFunctionName { get; private set; }
+ public string JsSource { get; private set; }
+
+ public ActionCreateBlueprintFromContent()
+ {
+ Letter = 'ï';
+ CanBePermissionAssigned = true;
+ Icon = "blueprint";
+ Alias = "createblueprint";
+ }
+ }
+}
diff --git a/src/umbraco.cms/umbraco.cms.csproj b/src/umbraco.cms/umbraco.cms.csproj
index 921466498c..0972200b96 100644
--- a/src/umbraco.cms/umbraco.cms.csproj
+++ b/src/umbraco.cms/umbraco.cms.csproj
@@ -183,6 +183,7 @@
+
diff --git a/src/umbraco.providers/UsersMembershipProvider.cs b/src/umbraco.providers/UsersMembershipProvider.cs
index 39285449a9..dfa77edc21 100644
--- a/src/umbraco.providers/UsersMembershipProvider.cs
+++ b/src/umbraco.providers/UsersMembershipProvider.cs
@@ -378,6 +378,7 @@ namespace umbraco.providers
///
/// The user to reset the password for.
/// The password answer for the specified user.
+ ///
/// The new password for the specified user.
protected override string PerformResetPassword(string username, string answer, string generatedPassword)
{
@@ -385,7 +386,6 @@ namespace umbraco.providers
//if (answer == null && RequiresQuestionAndAnswer)
//{
// UpdateFailureCount(username, "passwordAnswer");
-
// throw new ProviderException("Password answer required for password reset.");
//}