more work with saving, publishing and validation for variants, fixes up a few old things too
This commit is contained in:
@@ -232,7 +232,7 @@ namespace Umbraco.Core.Migrations.Install
|
|||||||
|
|
||||||
private void CreateLanguageData()
|
private void CreateLanguageData()
|
||||||
{
|
{
|
||||||
_database.Insert(Constants.DatabaseSchema.Tables.Language, "id", false, new LanguageDto { Id = 1, IsoCode = "en-US", CultureName = "en-US" });
|
_database.Insert(Constants.DatabaseSchema.Tables.Language, "id", false, new LanguageDto { Id = 1, IsoCode = "en-US", CultureName = "English (United States)" });
|
||||||
}
|
}
|
||||||
|
|
||||||
private void CreateContentChildTypeData()
|
private void CreateContentChildTypeData()
|
||||||
|
|||||||
@@ -27,7 +27,11 @@ namespace Umbraco.Core.Persistence.Factories
|
|||||||
if (xdtos.TryGetValue(propertyType.Id, out var propDtos))
|
if (xdtos.TryGetValue(propertyType.Id, out var propDtos))
|
||||||
{
|
{
|
||||||
foreach (var propDto in propDtos)
|
foreach (var propDto in propDtos)
|
||||||
|
{
|
||||||
|
property.Id = propDto.Id;
|
||||||
property.FactorySetValue(languageRepository.GetIsoCodeById(propDto.LanguageId), propDto.Segment, propDto.VersionId == publishedVersionId, propDto.Value);
|
property.FactorySetValue(languageRepository.GetIsoCodeById(propDto.LanguageId), propDto.Segment, propDto.VersionId == publishedVersionId, propDto.Value);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
property.ResetDirtyProperties(false);
|
property.ResetDirtyProperties(false);
|
||||||
|
|||||||
@@ -306,7 +306,8 @@
|
|||||||
saveMethod: args.saveMethod,
|
saveMethod: args.saveMethod,
|
||||||
scope: $scope,
|
scope: $scope,
|
||||||
content: $scope.content,
|
content: $scope.content,
|
||||||
action: args.action
|
action: args.action,
|
||||||
|
showNotifications: args.showNotifications
|
||||||
}).then(function (data) {
|
}).then(function (data) {
|
||||||
//success
|
//success
|
||||||
init($scope.content);
|
init($scope.content);
|
||||||
@@ -441,7 +442,8 @@
|
|||||||
//we need to return this promise so that the dialog can handle the result and wire up the validation response
|
//we need to return this promise so that the dialog can handle the result and wire up the validation response
|
||||||
return performSave({
|
return performSave({
|
||||||
saveMethod: contentResource.publish,
|
saveMethod: contentResource.publish,
|
||||||
action: "publish"
|
action: "publish",
|
||||||
|
showNotifications: false
|
||||||
}).then(function (data) {
|
}).then(function (data) {
|
||||||
overlayService.close();
|
overlayService.close();
|
||||||
return $q.when(data);
|
return $q.when(data);
|
||||||
@@ -451,21 +453,6 @@
|
|||||||
//re-map the dialog model since we've re-bound the properties
|
//re-map the dialog model since we've re-bound the properties
|
||||||
dialog.variants = $scope.content.variants;
|
dialog.variants = $scope.content.variants;
|
||||||
|
|
||||||
//check the error list for specific variant errors, if none exist that means that only server side validation
|
|
||||||
//for the current variant's properties failed, in this case we want to close the publish dialog since the user
|
|
||||||
//will need to fix validation errors on the properties
|
|
||||||
if (err.data && err.data.ModelState) {
|
|
||||||
var keys = _.keys(err.data.ModelState);
|
|
||||||
var foundVariantError = _.find(keys,
|
|
||||||
function (k) {
|
|
||||||
return k.startsWith("_content_variant_");
|
|
||||||
});
|
|
||||||
if (!foundVariantError) {
|
|
||||||
//no variant errors, close the dialog
|
|
||||||
overlayService.close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return $q.reject(err);
|
return $q.reject(err);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
@@ -500,7 +487,8 @@
|
|||||||
//we need to return this promise so that the dialog can handle the result and wire up the validation response
|
//we need to return this promise so that the dialog can handle the result and wire up the validation response
|
||||||
return performSave({
|
return performSave({
|
||||||
saveMethod: $scope.saveMethod(),
|
saveMethod: $scope.saveMethod(),
|
||||||
action: "save"
|
action: "save",
|
||||||
|
showNotifications: false
|
||||||
}).then(function (data) {
|
}).then(function (data) {
|
||||||
overlayService.close();
|
overlayService.close();
|
||||||
return $q.when(data);
|
return $q.when(data);
|
||||||
@@ -509,22 +497,7 @@
|
|||||||
model.submitButtonState = "error";
|
model.submitButtonState = "error";
|
||||||
//re-map the dialog model since we've re-bound the properties
|
//re-map the dialog model since we've re-bound the properties
|
||||||
dialog.variants = $scope.content.variants;
|
dialog.variants = $scope.content.variants;
|
||||||
|
|
||||||
//check the error list for specific variant errors, if none exist that means that only server side validation
|
|
||||||
//for the current variant's properties failed, in this case we want to close the publish dialog since the user
|
|
||||||
//will need to fix validation errors on the properties
|
|
||||||
if (err.data && err.data.ModelState) {
|
|
||||||
var keys = _.keys(err.data.ModelState);
|
|
||||||
var foundVariantError = _.find(keys,
|
|
||||||
function (k) {
|
|
||||||
return k.startsWith("_content_variant_");
|
|
||||||
});
|
|
||||||
if (!foundVariantError) {
|
|
||||||
//no variant errors, close the dialog
|
|
||||||
overlayService.close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return $q.reject(err);
|
return $q.reject(err);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -7,19 +7,19 @@
|
|||||||
**/
|
**/
|
||||||
function contentEditingHelper(fileManager, $q, $location, $routeParams, notificationsService, navigationService, localizationService, serverValidationManager, dialogService, formHelper, appState) {
|
function contentEditingHelper(fileManager, $q, $location, $routeParams, notificationsService, navigationService, localizationService, serverValidationManager, dialogService, formHelper, appState) {
|
||||||
|
|
||||||
function isValidIdentifier(id){
|
function isValidIdentifier(id) {
|
||||||
//empty id <= 0
|
//empty id <= 0
|
||||||
if(angular.isNumber(id) && id > 0){
|
if (angular.isNumber(id) && id > 0) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
//empty guid
|
//empty guid
|
||||||
if(id === "00000000-0000-0000-0000-000000000000"){
|
if (id === "00000000-0000-0000-0000-000000000000") {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
//empty string / alias
|
//empty string / alias
|
||||||
if(id === ""){
|
if (id === "") {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -44,6 +44,9 @@ function contentEditingHelper(fileManager, $q, $location, $routeParams, notifica
|
|||||||
if (!args.saveMethod) {
|
if (!args.saveMethod) {
|
||||||
throw "args.saveMethod is not defined";
|
throw "args.saveMethod is not defined";
|
||||||
}
|
}
|
||||||
|
if (args.showNotifications === undefined) {
|
||||||
|
args.showNotifications = true;
|
||||||
|
}
|
||||||
|
|
||||||
var redirectOnSuccess = args.redirectOnSuccess !== undefined ? args.redirectOnSuccess : true;
|
var redirectOnSuccess = args.redirectOnSuccess !== undefined ? args.redirectOnSuccess : true;
|
||||||
var redirectOnFailure = args.redirectOnFailure !== undefined ? args.redirectOnFailure : true;
|
var redirectOnFailure = args.redirectOnFailure !== undefined ? args.redirectOnFailure : true;
|
||||||
@@ -66,7 +69,7 @@ function contentEditingHelper(fileManager, $q, $location, $routeParams, notifica
|
|||||||
scope: args.scope,
|
scope: args.scope,
|
||||||
savedContent: data,
|
savedContent: data,
|
||||||
redirectOnSuccess: redirectOnSuccess,
|
redirectOnSuccess: redirectOnSuccess,
|
||||||
rebindCallback: function() {
|
rebindCallback: function () {
|
||||||
rebindCallback.apply(self, [args.content, data]);
|
rebindCallback.apply(self, [args.content, data]);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -76,13 +79,14 @@ function contentEditingHelper(fileManager, $q, $location, $routeParams, notifica
|
|||||||
|
|
||||||
}, function (err) {
|
}, function (err) {
|
||||||
self.handleSaveError({
|
self.handleSaveError({
|
||||||
|
showNotifications: args.showNotifications,
|
||||||
redirectOnFailure: redirectOnFailure,
|
redirectOnFailure: redirectOnFailure,
|
||||||
err: err,
|
err: err,
|
||||||
rebindCallback: function() {
|
rebindCallback: function () {
|
||||||
rebindCallback.apply(self, [args.content, err.data]);
|
rebindCallback.apply(self, [args.content, err.data]);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
args.scope.busy = false;
|
args.scope.busy = false;
|
||||||
return $q.reject(err);
|
return $q.reject(err);
|
||||||
});
|
});
|
||||||
@@ -90,9 +94,9 @@ function contentEditingHelper(fileManager, $q, $location, $routeParams, notifica
|
|||||||
else {
|
else {
|
||||||
return $q.reject();
|
return $q.reject();
|
||||||
}
|
}
|
||||||
|
|
||||||
},
|
},
|
||||||
|
|
||||||
/** Used by the content editor and media editor to add an info tab to the tabs array (normally known as the properties tab) */
|
/** Used by the content editor and media editor to add an info tab to the tabs array (normally known as the properties tab) */
|
||||||
addInfoTab: function (tabs) {
|
addInfoTab: function (tabs) {
|
||||||
|
|
||||||
@@ -165,7 +169,7 @@ function contentEditingHelper(fileManager, $q, $location, $routeParams, notifica
|
|||||||
handler: args.methods.sendToPublish,
|
handler: args.methods.sendToPublish,
|
||||||
hotKey: "ctrl+p",
|
hotKey: "ctrl+p",
|
||||||
hotKeyWhenHidden: true,
|
hotKeyWhenHidden: true,
|
||||||
alias: "sendToPublish"
|
alias: "sendToPublish"
|
||||||
};
|
};
|
||||||
case "A":
|
case "A":
|
||||||
//save
|
//save
|
||||||
@@ -175,7 +179,7 @@ function contentEditingHelper(fileManager, $q, $location, $routeParams, notifica
|
|||||||
handler: args.methods.save,
|
handler: args.methods.save,
|
||||||
hotKey: "ctrl+s",
|
hotKey: "ctrl+s",
|
||||||
hotKeyWhenHidden: true,
|
hotKeyWhenHidden: true,
|
||||||
alias: "save"
|
alias: "save"
|
||||||
};
|
};
|
||||||
case "Z":
|
case "Z":
|
||||||
//unpublish
|
//unpublish
|
||||||
@@ -185,7 +189,7 @@ function contentEditingHelper(fileManager, $q, $location, $routeParams, notifica
|
|||||||
handler: args.methods.unPublish,
|
handler: args.methods.unPublish,
|
||||||
hotKey: "ctrl+u",
|
hotKey: "ctrl+u",
|
||||||
hotKeyWhenHidden: true,
|
hotKeyWhenHidden: true,
|
||||||
alias: "unpublish"
|
alias: "unpublish"
|
||||||
};
|
};
|
||||||
default:
|
default:
|
||||||
return null;
|
return null;
|
||||||
@@ -247,15 +251,15 @@ function contentEditingHelper(fileManager, $q, $location, $routeParams, notifica
|
|||||||
|
|
||||||
// If we have a scheduled publish or unpublish date change the default button to
|
// If we have a scheduled publish or unpublish date change the default button to
|
||||||
// "save" and update the label to "save and schedule
|
// "save" and update the label to "save and schedule
|
||||||
if(args.content.releaseDate || args.content.removeDate) {
|
if (args.content.releaseDate || args.content.removeDate) {
|
||||||
|
|
||||||
// if save button is alread the default don't change it just update the label
|
// if save button is alread the default don't change it just update the label
|
||||||
if (buttons.defaultButton && buttons.defaultButton.letter === "A") {
|
if (buttons.defaultButton && buttons.defaultButton.letter === "A") {
|
||||||
buttons.defaultButton.labelKey = "buttons_saveAndSchedule";
|
buttons.defaultButton.labelKey = "buttons_saveAndSchedule";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(buttons.defaultButton && buttons.subButtons && buttons.subButtons.length > 0) {
|
if (buttons.defaultButton && buttons.subButtons && buttons.subButtons.length > 0) {
|
||||||
// save a copy of the default so we can push it to the sub buttons later
|
// save a copy of the default so we can push it to the sub buttons later
|
||||||
var defaultButtonCopy = angular.copy(buttons.defaultButton);
|
var defaultButtonCopy = angular.copy(buttons.defaultButton);
|
||||||
var newSubButtons = [];
|
var newSubButtons = [];
|
||||||
@@ -313,66 +317,66 @@ function contentEditingHelper(fileManager, $q, $location, $routeParams, notifica
|
|||||||
* @description
|
* @description
|
||||||
* Returns a letter array for buttons, with the primary one first based on content model, permissions and editor state
|
* Returns a letter array for buttons, with the primary one first based on content model, permissions and editor state
|
||||||
*/
|
*/
|
||||||
getAllowedActions : function(content, creating){
|
getAllowedActions: function (content, creating) {
|
||||||
|
|
||||||
//This is the ideal button order but depends on circumstance, we'll use this array to create the button list
|
//This is the ideal button order but depends on circumstance, we'll use this array to create the button list
|
||||||
// Publish, SendToPublish, Save
|
// Publish, SendToPublish, Save
|
||||||
var actionOrder = ["U", "H", "A"];
|
var actionOrder = ["U", "H", "A"];
|
||||||
var defaultActions;
|
var defaultActions;
|
||||||
var actions = [];
|
var actions = [];
|
||||||
|
|
||||||
//Create the first button (primary button)
|
//Create the first button (primary button)
|
||||||
//We cannot have the Save or SaveAndPublish buttons if they don't have create permissions when we are creating a new item.
|
//We cannot have the Save or SaveAndPublish buttons if they don't have create permissions when we are creating a new item.
|
||||||
if (!creating || _.contains(content.allowedActions, "C")) {
|
if (!creating || _.contains(content.allowedActions, "C")) {
|
||||||
for (var b in actionOrder) {
|
for (var b in actionOrder) {
|
||||||
if (_.contains(content.allowedActions, actionOrder[b])) {
|
if (_.contains(content.allowedActions, actionOrder[b])) {
|
||||||
defaultAction = actionOrder[b];
|
defaultAction = actionOrder[b];
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
actions.push(defaultAction);
|
||||||
|
|
||||||
|
//Now we need to make the drop down button list, this is also slightly tricky because:
|
||||||
|
//We cannot have any buttons if there's no default button above.
|
||||||
|
//We cannot have the unpublish button (Z) when there's no publish permission.
|
||||||
|
//We cannot have the unpublish button (Z) when the item is not published.
|
||||||
|
if (defaultAction) {
|
||||||
|
//get the last index of the button order
|
||||||
|
var lastIndex = _.indexOf(actionOrder, defaultAction);
|
||||||
|
|
||||||
|
//add the remaining
|
||||||
|
for (var i = lastIndex + 1; i < actionOrder.length; i++) {
|
||||||
|
if (_.contains(content.allowedActions, actionOrder[i])) {
|
||||||
|
actions.push(actionOrder[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
actions.push(defaultAction);
|
//if we are not creating, then we should add unpublish too,
|
||||||
|
// so long as it's already published and if the user has access to publish
|
||||||
//Now we need to make the drop down button list, this is also slightly tricky because:
|
if (!creating) {
|
||||||
//We cannot have any buttons if there's no default button above.
|
if (content.publishDate && _.contains(content.allowedActions, "U")) {
|
||||||
//We cannot have the unpublish button (Z) when there's no publish permission.
|
actions.push("Z");
|
||||||
//We cannot have the unpublish button (Z) when the item is not published.
|
|
||||||
if (defaultAction) {
|
|
||||||
//get the last index of the button order
|
|
||||||
var lastIndex = _.indexOf(actionOrder, defaultAction);
|
|
||||||
|
|
||||||
//add the remaining
|
|
||||||
for (var i = lastIndex + 1; i < actionOrder.length; i++) {
|
|
||||||
if (_.contains(content.allowedActions, actionOrder[i])) {
|
|
||||||
actions.push(actionOrder[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//if we are not creating, then we should add unpublish too,
|
|
||||||
// so long as it's already published and if the user has access to publish
|
|
||||||
if (!creating) {
|
|
||||||
if (content.publishDate && _.contains(content.allowedActions,"U")) {
|
|
||||||
actions.push("Z");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return actions;
|
return actions;
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @ngdoc method
|
* @ngdoc method
|
||||||
* @name umbraco.services.contentEditingHelper#getButtonFromAction
|
* @name umbraco.services.contentEditingHelper#getButtonFromAction
|
||||||
* @methodOf umbraco.services.contentEditingHelper
|
* @methodOf umbraco.services.contentEditingHelper
|
||||||
* @function
|
* @function
|
||||||
*
|
*
|
||||||
* @description
|
* @description
|
||||||
* Returns a button object to render a button for the tabbed editor
|
* Returns a button object to render a button for the tabbed editor
|
||||||
* currently only returns built in system buttons for content and media actions
|
* currently only returns built in system buttons for content and media actions
|
||||||
* returns label, alias, action char and hot-key
|
* returns label, alias, action char and hot-key
|
||||||
*/
|
*/
|
||||||
getButtonFromAction : function(ch){
|
getButtonFromAction: function (ch) {
|
||||||
switch (ch) {
|
switch (ch) {
|
||||||
case "U":
|
case "U":
|
||||||
return {
|
return {
|
||||||
@@ -407,7 +411,8 @@ function contentEditingHelper(fileManager, $q, $location, $routeParams, notifica
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @ngdoc method
|
* @ngdoc method
|
||||||
* @name umbraco.services.contentEditingHelper#reBindChangedProperties
|
* @name umbraco.services.contentEditingHelper#reBindChangedProperties
|
||||||
@@ -421,11 +426,11 @@ function contentEditingHelper(fileManager, $q, $location, $routeParams, notifica
|
|||||||
* This returns the list of changed content properties (does not include standard object property changes).
|
* This returns the list of changed content properties (does not include standard object property changes).
|
||||||
*/
|
*/
|
||||||
reBindChangedProperties: function (origContent, savedContent) {
|
reBindChangedProperties: function (origContent, savedContent) {
|
||||||
|
|
||||||
//TODO: We should probably split out this logic to deal with media/members seperately to content
|
//TODO: We should probably split out this logic to deal with media/members seperately to content
|
||||||
|
|
||||||
//a method to ignore built-in prop changes
|
//a method to ignore built-in prop changes
|
||||||
var shouldIgnore = function(propName) {
|
var shouldIgnore = function (propName) {
|
||||||
return _.some([
|
return _.some([
|
||||||
"variants",
|
"variants",
|
||||||
"notifications",
|
"notifications",
|
||||||
@@ -465,9 +470,12 @@ function contentEditingHelper(fileManager, $q, $location, $routeParams, notifica
|
|||||||
//Now re-bind content properties. Since content has variants and media/members doesn't,
|
//Now re-bind content properties. Since content has variants and media/members doesn't,
|
||||||
//we'll detect the variants property for content to distinguish if it's content vs media/members.
|
//we'll detect the variants property for content to distinguish if it's content vs media/members.
|
||||||
|
|
||||||
|
var isContent = false;
|
||||||
|
|
||||||
var origVariants = [];
|
var origVariants = [];
|
||||||
var savedVariants = [];
|
var savedVariants = [];
|
||||||
if (origContent.variants) {
|
if (origContent.variants) {
|
||||||
|
isContent = true;
|
||||||
//it's contnet so assign the variants as they exist
|
//it's contnet so assign the variants as they exist
|
||||||
origVariants = origContent.variants;
|
origVariants = origContent.variants;
|
||||||
savedVariants = savedContent.variants;
|
savedVariants = savedContent.variants;
|
||||||
@@ -492,6 +500,12 @@ function contentEditingHelper(fileManager, $q, $location, $routeParams, notifica
|
|||||||
var origVariant = origVariants[j];
|
var origVariant = origVariants[j];
|
||||||
var savedVariant = savedVariants[j];
|
var savedVariant = savedVariants[j];
|
||||||
|
|
||||||
|
//special case for content, don't sync this variant if it wasn't tagged
|
||||||
|
//for saving in the first place
|
||||||
|
if (!savedVariant.save) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
//if it's content (not media/members), then we need to sync the variant specific data
|
//if it's content (not media/members), then we need to sync the variant specific data
|
||||||
if (origContent.variants) {
|
if (origContent.variants) {
|
||||||
|
|
||||||
@@ -501,7 +515,7 @@ function contentEditingHelper(fileManager, $q, $location, $routeParams, notifica
|
|||||||
//loop through the properties returned on the server object
|
//loop through the properties returned on the server object
|
||||||
for (var b in savedVariant) {
|
for (var b in savedVariant) {
|
||||||
|
|
||||||
var shouldCompare = _.some(variantPropertiesSync, function(e) {
|
var shouldCompare = _.some(variantPropertiesSync, function (e) {
|
||||||
return e === b;
|
return e === b;
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -528,7 +542,7 @@ function contentEditingHelper(fileManager, $q, $location, $routeParams, notifica
|
|||||||
|
|
||||||
//they have changed so set the origContent prop to the new one
|
//they have changed so set the origContent prop to the new one
|
||||||
var origVal = origProp.value;
|
var origVal = origProp.value;
|
||||||
|
|
||||||
origProp.value = newProp.value;
|
origProp.value = newProp.value;
|
||||||
|
|
||||||
//instead of having a property editor $watch their expression to check if it has
|
//instead of having a property editor $watch their expression to check if it has
|
||||||
@@ -539,7 +553,7 @@ function contentEditingHelper(fileManager, $q, $location, $routeParams, notifica
|
|||||||
origProp.onValueChanged(origProp.value, origVal);
|
origProp.onValueChanged(origProp.value, origVal);
|
||||||
}
|
}
|
||||||
|
|
||||||
changed.push(origProp);
|
changed.push(origProp);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -577,6 +591,13 @@ function contentEditingHelper(fileManager, $q, $location, $routeParams, notifica
|
|||||||
//wire up the server validation errs
|
//wire up the server validation errs
|
||||||
formHelper.handleServerValidation(args.err.data.ModelState);
|
formHelper.handleServerValidation(args.err.data.ModelState);
|
||||||
|
|
||||||
|
//add model state errors to notifications
|
||||||
|
if (args.showNotifications) {
|
||||||
|
for (var e in modelState) {
|
||||||
|
notificationsService.error("Validation", modelState[e][0]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!args.redirectOnFailure || !this.redirectToCreatedContent(args.err.data.id, args.err.data.ModelState)) {
|
if (!args.redirectOnFailure || !this.redirectToCreatedContent(args.err.data.id, args.err.data.ModelState)) {
|
||||||
//we are not redirecting because this is not new content, it is existing content. In this case
|
//we are not redirecting because this is not new content, it is existing content. In this case
|
||||||
// we need to detect what properties have changed and re-bind them with the server data. Then we need
|
// we need to detect what properties have changed and re-bind them with the server data. Then we need
|
||||||
@@ -621,7 +642,7 @@ function contentEditingHelper(fileManager, $q, $location, $routeParams, notifica
|
|||||||
|
|
||||||
// the default behaviour is to redirect on success. This adds option to prevent when false
|
// the default behaviour is to redirect on success. This adds option to prevent when false
|
||||||
args.redirectOnSuccess = args.redirectOnSuccess !== undefined ? args.redirectOnSuccess : true;
|
args.redirectOnSuccess = args.redirectOnSuccess !== undefined ? args.redirectOnSuccess : true;
|
||||||
|
|
||||||
if (!args.redirectOnSuccess || !this.redirectToCreatedContent(args.redirectId ? args.redirectId : args.savedContent.id)) {
|
if (!args.redirectOnSuccess || !this.redirectToCreatedContent(args.redirectId ? args.redirectId : args.savedContent.id)) {
|
||||||
|
|
||||||
//we are not redirecting because this is not new content, it is existing content. In this case
|
//we are not redirecting because this is not new content, it is existing content. In this case
|
||||||
@@ -646,9 +667,8 @@ function contentEditingHelper(fileManager, $q, $location, $routeParams, notifica
|
|||||||
*/
|
*/
|
||||||
redirectToCreatedContent: function (id, modelState) {
|
redirectToCreatedContent: function (id, modelState) {
|
||||||
|
|
||||||
//only continue if we are currently in create mode and not in infinite mode and if there is no 'Name' modelstate errors
|
//only continue if we are currently in create mode and not in infinite mode and if the resulting ID is valid
|
||||||
// since we need at least a name to create content.
|
if ($routeParams.create && (isValidIdentifier(id))) {
|
||||||
if ($routeParams.create && (isValidIdentifier(id) && (!modelState || !modelState["Name"]))) {
|
|
||||||
|
|
||||||
//need to change the location to not be in 'create' mode. Currently the route will be something like:
|
//need to change the location to not be in 'create' mode. Currently the route will be something like:
|
||||||
// /belle/#/content/edit/1234?doctype=newsArticle&create=true
|
// /belle/#/content/edit/1234?doctype=newsArticle&create=true
|
||||||
@@ -659,7 +679,7 @@ function contentEditingHelper(fileManager, $q, $location, $routeParams, notifica
|
|||||||
navigationService.clearSearch();
|
navigationService.clearSearch();
|
||||||
|
|
||||||
//change to new path
|
//change to new path
|
||||||
$location.path("/" + $routeParams.section + "/" + $routeParams.tree + "/" + $routeParams.method + "/" + id);
|
$location.path("/" + $routeParams.section + "/" + $routeParams.tree + "/" + $routeParams.method + "/" + id);
|
||||||
//don't add a browser history for this
|
//don't add a browser history for this
|
||||||
$location.replace();
|
$location.replace();
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -190,9 +190,6 @@ function formHelper(angularHelper, serverValidationManager, $timeout, notificati
|
|||||||
serverValidationManager.addFieldError(e, modelState[e][0]);
|
serverValidationManager.addFieldError(e, modelState[e][0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
//add to notifications
|
|
||||||
notificationsService.error("Validation", modelState[e][0]);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -4,32 +4,13 @@
|
|||||||
function PublishController($scope, localizationService) {
|
function PublishController($scope, localizationService) {
|
||||||
|
|
||||||
var vm = this;
|
var vm = this;
|
||||||
vm.variants = $scope.model.variants;
|
|
||||||
vm.changeSelection = changeSelection;
|
|
||||||
vm.loading = true;
|
vm.loading = true;
|
||||||
vm.dirtyVariantFilter = dirtyVariantFilter;
|
|
||||||
vm.pristineVariantFilter = pristineVariantFilter;
|
|
||||||
vm.hasPristineVariants = false;
|
vm.hasPristineVariants = false;
|
||||||
|
|
||||||
//watch this model, if it's reset, then re init
|
vm.changeSelection = changeSelection;
|
||||||
$scope.$watch("model.variants",
|
vm.dirtyVariantFilter = dirtyVariantFilter;
|
||||||
function (newVal, oldVal) {
|
vm.pristineVariantFilter = pristineVariantFilter;
|
||||||
vm.variants = newVal;
|
|
||||||
if (oldVal && oldVal.length) {
|
|
||||||
//re-bind the selections
|
|
||||||
for (var i = 0; i < oldVal.length; i++) {
|
|
||||||
var found = _.find(vm.variants, function (v) {
|
|
||||||
return v.language.id === oldVal[i].language.id;
|
|
||||||
});
|
|
||||||
if (found) {
|
|
||||||
found.publish = oldVal[i].publish;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
onInit();
|
|
||||||
});
|
|
||||||
|
|
||||||
/** Returns true if publishing is possible based on if there are un-published mandatory languages */
|
/** Returns true if publishing is possible based on if there are un-published mandatory languages */
|
||||||
function canPublish() {
|
function canPublish() {
|
||||||
var selected = [];
|
var selected = [];
|
||||||
@@ -57,6 +38,8 @@
|
|||||||
|
|
||||||
function changeSelection(variant) {
|
function changeSelection(variant) {
|
||||||
$scope.model.disableSubmitButton = !canPublish();
|
$scope.model.disableSubmitButton = !canPublish();
|
||||||
|
//need to set the Save state to true if publish is true
|
||||||
|
variant.save = variant.publish;
|
||||||
}
|
}
|
||||||
|
|
||||||
function dirtyVariantFilter(variant) {
|
function dirtyVariantFilter(variant) {
|
||||||
@@ -75,6 +58,8 @@
|
|||||||
|
|
||||||
function onInit() {
|
function onInit() {
|
||||||
|
|
||||||
|
vm.variants = $scope.model.variants;
|
||||||
|
|
||||||
if (!$scope.model.title) {
|
if (!$scope.model.title) {
|
||||||
localizationService.localize("content_readyToPublish").then(function (value) {
|
localizationService.localize("content_readyToPublish").then(function (value) {
|
||||||
$scope.model.title = value;
|
$scope.model.title = value;
|
||||||
@@ -107,6 +92,7 @@
|
|||||||
if (active) {
|
if (active) {
|
||||||
//ensure that the current one is selected
|
//ensure that the current one is selected
|
||||||
active.publish = true;
|
active.publish = true;
|
||||||
|
active.save = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
$scope.model.disableSubmitButton = !canPublish();
|
$scope.model.disableSubmitButton = !canPublish();
|
||||||
@@ -120,10 +106,13 @@
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onInit();
|
||||||
|
|
||||||
//when this dialog is closed, reset all 'publish' flags
|
//when this dialog is closed, reset all 'publish' flags
|
||||||
$scope.$on('$destroy', function () {
|
$scope.$on('$destroy', function () {
|
||||||
for (var i = 0; i < vm.variants.length; i++) {
|
for (var i = 0; i < vm.variants.length; i++) {
|
||||||
vm.variants[i].publish = false;
|
vm.variants[i].publish = false;
|
||||||
|
vm.variants[i].save = false;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,31 +4,13 @@
|
|||||||
function SaveContentController($scope, localizationService) {
|
function SaveContentController($scope, localizationService) {
|
||||||
|
|
||||||
var vm = this;
|
var vm = this;
|
||||||
vm.variants = $scope.model.variants;
|
|
||||||
vm.changeSelection = changeSelection;
|
|
||||||
vm.loading = true;
|
vm.loading = true;
|
||||||
vm.dirtyVariantFilter = dirtyVariantFilter;
|
|
||||||
vm.pristineVariantFilter = pristineVariantFilter;
|
|
||||||
vm.hasPristineVariants = false;
|
vm.hasPristineVariants = false;
|
||||||
|
|
||||||
//watch this model, if it's reset, then re init
|
vm.changeSelection = changeSelection;
|
||||||
$scope.$watch("model.variants",
|
vm.dirtyVariantFilter = dirtyVariantFilter;
|
||||||
function (newVal, oldVal) {
|
vm.pristineVariantFilter = pristineVariantFilter;
|
||||||
vm.variants = newVal;
|
|
||||||
if (oldVal && oldVal.length) {
|
|
||||||
//re-bind the selections
|
|
||||||
for (var i = 0; i < oldVal.length; i++) {
|
|
||||||
var found = _.find(vm.variants, function (v) {
|
|
||||||
return v.language.id === oldVal[i].language.id;
|
|
||||||
});
|
|
||||||
if (found) {
|
|
||||||
found.save = oldVal[i].save;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
onInit();
|
|
||||||
});
|
|
||||||
|
|
||||||
function changeSelection(variant) {
|
function changeSelection(variant) {
|
||||||
var firstSelected = _.find(vm.variants, function (v) {
|
var firstSelected = _.find(vm.variants, function (v) {
|
||||||
return v.save;
|
return v.save;
|
||||||
@@ -50,6 +32,8 @@
|
|||||||
|
|
||||||
function onInit() {
|
function onInit() {
|
||||||
|
|
||||||
|
vm.variants = $scope.model.variants;
|
||||||
|
|
||||||
if(!$scope.model.title) {
|
if(!$scope.model.title) {
|
||||||
localizationService.localize("content_readyToSave").then(function(value){
|
localizationService.localize("content_readyToSave").then(function(value){
|
||||||
$scope.model.title = value;
|
$scope.model.title = value;
|
||||||
@@ -92,6 +76,8 @@
|
|||||||
vm.loading = false;
|
vm.loading = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onInit();
|
||||||
|
|
||||||
//when this dialog is closed, reset all 'save' flags
|
//when this dialog is closed, reset all 'save' flags
|
||||||
$scope.$on('$destroy', function () {
|
$scope.$on('$destroy', function () {
|
||||||
for (var i = 0; i < vm.variants.length; i++) {
|
for (var i = 0; i < vm.variants.length; i++) {
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ using System.Net;
|
|||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
using System.Web.Http.Controllers;
|
using System.Web.Http.Controllers;
|
||||||
using System.Web.Http.ModelBinding;
|
using System.Web.Http.ModelBinding;
|
||||||
|
using Umbraco.Core;
|
||||||
using Umbraco.Core.Logging;
|
using Umbraco.Core.Logging;
|
||||||
using Umbraco.Core.Models;
|
using Umbraco.Core.Models;
|
||||||
using Umbraco.Web.Models.ContentEditing;
|
using Umbraco.Web.Models.ContentEditing;
|
||||||
@@ -148,7 +149,16 @@ namespace Umbraco.Web.Editors.Filters
|
|||||||
// validate
|
// validate
|
||||||
var valueEditor = editor.GetValueEditor(p.DataType.Configuration);
|
var valueEditor = editor.GetValueEditor(p.DataType.Configuration);
|
||||||
foreach (var r in valueEditor.Validate(postedValue, p.IsRequired, p.ValidationRegExp))
|
foreach (var r in valueEditor.Validate(postedValue, p.IsRequired, p.ValidationRegExp))
|
||||||
|
{
|
||||||
|
//this could be a thing, but it does make the errors seem very verbose
|
||||||
|
////update the error message to include the property name and culture if available
|
||||||
|
//r.ErrorMessage = p.Culture.IsNullOrWhiteSpace()
|
||||||
|
// ? $"'{p.Label}' - {r.ErrorMessage}"
|
||||||
|
// : $"'{p.Label}' ({p.Culture}) - {r.ErrorMessage}";
|
||||||
|
|
||||||
modelState.AddPropertyError(r, p.Alias, p.Culture);
|
modelState.AddPropertyError(r, p.Alias, p.Culture);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return modelState.IsValid;
|
return modelState.IsValid;
|
||||||
|
|||||||
Reference in New Issue
Block a user