Files
Umbraco-CMS/src/Umbraco.Web.UI.Client/src/common/directives/components/content/edit.controller.js
Robert 68662e271d Merge remote-tracking branch 'origin/temp8' into temp8-ui-listview-as-infinity-editing-v2
# Conflicts:
#	src/Umbraco.Web.UI.Client/src/views/components/content/edit.html
2019-02-15 10:28:04 +01:00

934 lines
40 KiB
JavaScript

(function () {
'use strict';
function ContentEditController($rootScope, $scope, $routeParams, $q, $window,
appState, contentResource, entityResource, navigationService, notificationsService,
serverValidationManager, contentEditingHelper, treeService, formHelper, umbRequestHelper,
editorState, $http, eventsService, relationResource, overlayService, $location) {
var evts = [];
var infiniteMode = $scope.infiniteModel && $scope.infiniteModel.infiniteMode;
//setup scope vars
$scope.defaultButton = null;
$scope.subButtons = [];
$scope.page = {};
$scope.page.loading = false;
$scope.page.menu = {};
$scope.page.menu.currentNode = null;
$scope.page.menu.currentSection = appState.getSectionState("currentSection");
$scope.page.listViewPath = null;
$scope.page.isNew = $scope.isNew ? true : false;
$scope.page.buttonGroupState = "init";
$scope.page.hideActionsMenu = infiniteMode ? true : false;
$scope.page.hideChangeVariant = false;
$scope.allowOpen = true;
$scope.app = null;
function init() {
var content = $scope.content;
// we need to check wether an app is present in the current data, if not we will present the default app.
var isAppPresent = false;
// on first init, we dont have any apps. but if we are re-initializing, we do, but ...
if ($scope.app) {
// lets check if it still exists as part of our apps array. (if not we have made a change to our docType, even just a re-save of the docType it will turn into new Apps.)
_.forEach(content.apps, function(app) {
if (app === $scope.app) {
isAppPresent = true;
}
});
// if we did reload our DocType, but still have the same app we will try to find it by the alias.
if (isAppPresent === false) {
_.forEach(content.apps, function(app) {
if (app.alias === $scope.app.alias) {
isAppPresent = true;
app.active = true;
$scope.appChanged(app);
}
});
}
}
// if we still dont have a app, lets show the first one:
if (isAppPresent === false) {
content.apps[0].active = true;
$scope.appChanged(content.apps[0]);
}
editorState.set(content);
//We fetch all ancestors of the node to generate the footer breadcrumb navigation
if (!$scope.page.isNew) {
if (content.parentId && content.parentId !== -1) {
entityResource.getAncestors(content.id, "document", $scope.culture)
.then(function (anc) {
$scope.ancestors = anc;
});
$scope.$watch('culture',
function (value, oldValue) {
entityResource.getAncestors(content.id, "document", value)
.then(function (anc) {
$scope.ancestors = anc;
});
});
}
}
bindEvents();
resetVariantFlags();
}
/**
* This will reset isDirty flags if save is true.
* When working with multiple variants, this will set the save/publish flags of each one to false.
* When working with a single variant, this will set the publish flag to false and the save flag to true.
*/
function resetVariantFlags() {
if ($scope.content.variants.length > 1) {
for (var i = 0; i < $scope.content.variants.length; i++) {
var v = $scope.content.variants[i];
if (v.save) {
v.isDirty = false;
}
v.save = false;
v.publish = false;
}
}
else {
if ($scope.content.variants[0].save) {
$scope.content.variants[0].isDirty = false;
}
$scope.content.variants[0].save = true;
$scope.content.variants[0].publish = false;
}
}
/** Returns true if the content item varies by culture */
function isContentCultureVariant() {
return $scope.content.variants.length > 1;
}
function bindEvents() {
//bindEvents can be called more than once and we don't want to have multiple bound events
for (var e in evts) {
eventsService.unsubscribe(evts[e]);
}
evts.push(eventsService.on("editors.content.reload", function (name, args) {
// if this content item uses the updated doc type we need to reload the content item
if(args && args.node && args.node.key === $scope.content.key) {
$scope.page.loading = true;
loadContent().then(function() {
$scope.page.loading = false;
});
}
}));
}
/**
* This does the content loading and initializes everything, called on first load
*/
function loadContent() {
//we are editing so get the content item from the server
return $scope.getMethod()($scope.contentId)
.then(function (data) {
$scope.content = data;
if (data.isChildOfListView && data.trashed === false) {
$scope.page.listViewPath = ($routeParams.page) ?
"/content/content/edit/" + data.parentId + "?page=" + $routeParams.page :
"/content/content/edit/" + data.parentId;
}
init();
syncTreeNode($scope.content, $scope.content.path, true);
resetLastListPageNumber($scope.content);
eventsService.emit("content.loaded", { content: $scope.content });
return $q.resolve($scope.content);
});
}
/**
* Create the save/publish/preview buttons for the view
* @param {any} content the content node
* @param {any} app the active content app
*/
function createButtons(content) {
// for trashed and element type items, the save button is the primary action - otherwise it's a secondary action
$scope.page.saveButtonStyle = content.trashed || content.isElement ? "primary" : "info";
// only create the save/publish/preview buttons if the
// content app is "Conent"
if ($scope.app && $scope.app.alias !== "umbContent" && $scope.app.alias !== "umbInfo") {
$scope.defaultButton = null;
$scope.subButtons = null;
$scope.page.showSaveButton = false;
$scope.page.showPreviewButton = false;
return;
}
// create the save button
if (_.contains($scope.content.allowedActions, "A")) {
$scope.page.showSaveButton = true;
// add ellipsis to the save button if it opens the variant overlay
$scope.page.saveButtonEllipsis = content.variants && content.variants.length > 1 ? "true" : "false";
}
// create the pubish combo button
$scope.page.buttonGroupState = "init";
var buttons = contentEditingHelper.configureContentEditorButtons({
create: $scope.page.isNew,
content: content,
methods: {
saveAndPublish: $scope.saveAndPublish,
sendToPublish: $scope.sendToPublish,
unpublish: $scope.unpublish,
schedulePublish: $scope.schedule,
publishDescendants: $scope.publishDescendants
}
});
$scope.defaultButton = buttons.defaultButton;
$scope.subButtons = buttons.subButtons;
$scope.page.showPreviewButton = true;
}
/** Syncs the content item to it's tree node - this occurs on first load and after saving */
function syncTreeNode(content, path, initialLoad) {
if (infiniteMode || !path) {
return;
}
if (!$scope.content.isChildOfListView) {
navigationService.syncTree({ tree: $scope.treeAlias, path: path.split(","), forceReload: initialLoad !== true }).then(function (syncArgs) {
$scope.page.menu.currentNode = syncArgs.node;
});
}
else if (initialLoad === true) {
//it's a child item, just sync the ui node to the parent
navigationService.syncTree({ tree: $scope.treeAlias, path: path.substring(0, path.lastIndexOf(",")).split(","), forceReload: initialLoad !== true });
//if this is a child of a list view and it's the initial load of the editor, we need to get the tree node
// from the server so that we can load in the actions menu.
umbRequestHelper.resourcePromise(
$http.get(content.treeNodeUrl),
'Failed to retrieve data for child node ' + content.id).then(function (node) {
$scope.page.menu.currentNode = node;
});
}
}
function checkValidility() {
//Get all controls from the 'contentForm'
var allControls = $scope.contentForm.$getControls();
//An array to store items in when we find child form fields (no matter how many deep nested forms)
var childFieldsToMarkAsValid = [];
//Exclude known formControls 'contentHeaderForm' and 'tabbedContentForm'
//Check property - $name === "contentHeaderForm"
allControls = _.filter(allControls, function (obj) {
return obj.$name !== 'contentHeaderForm' && obj.$name !== 'tabbedContentForm' && obj.hasOwnProperty('$submitted');
});
for (var i = 0; i < allControls.length; i++) {
var nestedForm = allControls[i];
//Get Nested Controls of this form in the loop
var nestedFormControls = nestedForm.$getControls();
//Need to recurse through controls (could be more nested forms)
childFieldsToMarkAsValid = recurseFormControls(nestedFormControls, childFieldsToMarkAsValid);
}
return childFieldsToMarkAsValid;
}
//Controls is the
function recurseFormControls(controls, array) {
//Loop over the controls
for (var i = 0; i < controls.length; i++) {
var controlItem = controls[i];
//Check if the controlItem has a property ''
if (controlItem.hasOwnProperty('$submitted')) {
//This item is a form - so lets get the child controls of it & recurse again
var childFormControls = controlItem.$getControls();
recurseFormControls(childFormControls, array);
}
else {
//We can assume its a field on a form
if (controlItem.hasOwnProperty('$error')) {
//Set the validlity of the error/s to be valid
//String of keys of error invalid messages
var errorKeys = [];
for (var key in controlItem.$error) {
errorKeys.push(key);
controlItem.$setValidity(key, true);
}
//Create a basic obj - storing the control item & the error keys
var obj = { 'control': controlItem, 'errorKeys': errorKeys };
//Push the updated control into the array - so we can set them back
array.push(obj);
}
}
}
return array;
}
function resetNestedFieldValiation(array) {
for (var i = 0; i < array.length; i++) {
var item = array[i];
//Item is an object containing two props
//'control' (obj) & 'errorKeys' (string array)
var fieldControl = item.control;
var fieldErrorKeys = item.errorKeys;
for (var j = 0; j < fieldErrorKeys.length; j++) {
fieldControl.$setValidity(fieldErrorKeys[j], false);
}
}
}
function ensureDirtyIsSetIfAnyVariantIsDirty() {
$scope.contentForm.$dirty = false;
for (var i = 0; i < $scope.content.variants.length; i++) {
if($scope.content.variants[i].isDirty){
$scope.contentForm.$dirty = true;
return;
}
}
}
// This is a helper method to reduce the amount of code repitition for actions: Save, Publish, SendToPublish
function performSave(args) {
//Used to check validility of nested form - coming from Content Apps mostly
//Set them all to be invalid
var fieldsToRollback = checkValidility();
eventsService.emit("content.saving", { content: $scope.content, action: args.action });
return contentEditingHelper.contentEditorPerformSave({
saveMethod: args.saveMethod,
scope: $scope,
content: $scope.content,
action: args.action,
showNotifications: args.showNotifications
}).then(function (data) {
//success
init();
syncTreeNode($scope.content, data.path);
eventsService.emit("content.saved", { content: $scope.content, action: args.action });
resetNestedFieldValiation(fieldsToRollback);
ensureDirtyIsSetIfAnyVariantIsDirty();
return $q.when(data);
},
function (err) {
syncTreeNode($scope.content, $scope.content.path);
//error
if (err) {
editorState.set($scope.content);
}
resetNestedFieldValiation(fieldsToRollback);
return $q.reject(err);
});
}
function clearNotifications(content) {
if (content.notifications) {
content.notifications = [];
}
if (content.variants) {
for (var i = 0; i < content.variants.length; i++) {
if (content.variants[i].notifications) {
content.variants[i].notifications = [];
}
}
}
}
function resetLastListPageNumber(content) {
// We're using rootScope to store the page number for list views, so if returning to the list
// we can restore the page. If we've moved on to edit a piece of content that's not the list or it's children
// we should remove this so as not to confuse if navigating to a different list
if (!content.isChildOfListView && !content.isContainer) {
$rootScope.lastListViewPageViewed = null;
}
}
/**
* Used to clear the dirty state for successfully saved variants when not all variant saving was successful
* @param {any} variants
*/
function clearDirtyState(variants) {
for (var i = 0; i < variants.length; i++) {
var v = variants[i];
if (v.notifications) {
var isSuccess = _.find(v.notifications, function (n) {
return n.type === 3; //this is a success notification
});
if (isSuccess) {
v.isDirty = false;
}
}
}
}
if ($scope.page.isNew) {
$scope.page.loading = true;
//we are creating so get an empty content item
$scope.getScaffoldMethod()()
.then(function (data) {
$scope.content = data;
init();
resetLastListPageNumber($scope.content);
eventsService.emit("content.newReady", { content: $scope.content });
$scope.page.loading = false;
});
}
else {
$scope.page.loading = true;
loadContent().then(function () {
$scope.page.loading = false;
});
}
$scope.unpublish = function () {
clearNotifications($scope.content);
if (formHelper.submitForm({ scope: $scope, action: "unpublish", skipValidation: true })) {
var dialog = {
parentScope: $scope,
view: "views/content/overlays/unpublish.html",
variants: $scope.content.variants, //set a model property for the dialog
skipFormValidation: true, //when submitting the overlay form, skip any client side validation
submitButtonLabelKey: "content_unpublish",
submitButtonStyle: "warning",
submit: function (model) {
model.submitButtonState = "busy";
var selectedVariants = _.filter(model.variants, v => v.save && v.language); //ignore invariant
var culturesForUnpublishing = _.map(selectedVariants, v => v.language.culture);
contentResource.unpublish($scope.content.id, culturesForUnpublishing)
.then(function (data) {
formHelper.resetForm({ scope: $scope });
contentEditingHelper.reBindChangedProperties($scope.content, data);
init();
syncTreeNode($scope.content, data.path);
$scope.page.buttonGroupState = "success";
eventsService.emit("content.unpublished", { content: $scope.content });
overlayService.close();
}, function (err) {
$scope.page.buttonGroupState = 'error';
});
},
close: function () {
overlayService.close();
}
};
overlayService.open(dialog);
}
};
$scope.sendToPublish = function () {
clearNotifications($scope.content);
if (isContentCultureVariant()) {
//before we launch the dialog we want to execute all client side validations first
if (formHelper.submitForm({ scope: $scope, action: "publish" })) {
var dialog = {
parentScope: $scope,
view: "views/content/overlays/sendtopublish.html",
variants: $scope.content.variants, //set a model property for the dialog
skipFormValidation: true, //when submitting the overlay form, skip any client side validation
submitButtonLabelKey: "buttons_saveToPublish",
submit: function (model) {
model.submitButtonState = "busy";
clearNotifications($scope.content);
//we need to return this promise so that the dialog can handle the result and wire up the validation response
return performSave({
saveMethod: contentResource.sendToPublish,
action: "sendToPublish",
showNotifications: false
}).then(function (data) {
//show all notifications manually here since we disabled showing them automatically in the save method
formHelper.showNotifications(data);
clearNotifications($scope.content);
overlayService.close();
return $q.when(data);
}, function (err) {
clearDirtyState($scope.content.variants);
model.submitButtonState = "error";
//re-map the dialog model since we've re-bound the properties
dialog.variants = $scope.content.variants;
//don't reject, we've handled the error
return $q.when(err);
});
},
close: function () {
overlayService.close();
}
};
overlayService.open(dialog);
}
}
else {
$scope.page.buttonGroupState = "busy";
return performSave({
saveMethod: contentResource.sendToPublish,
action: "sendToPublish"
}).then(function () {
$scope.page.buttonGroupState = "success";
}, function () {
$scope.page.buttonGroupState = "error";
});;
}
};
$scope.saveAndPublish = function () {
clearNotifications($scope.content);
if (isContentCultureVariant()) {
//before we launch the dialog we want to execute all client side validations first
if (formHelper.submitForm({ scope: $scope, action: "publish" })) {
var dialog = {
parentScope: $scope,
view: "views/content/overlays/publish.html",
variants: $scope.content.variants, //set a model property for the dialog
skipFormValidation: true, //when submitting the overlay form, skip any client side validation
submitButtonLabelKey: "buttons_saveAndPublish",
submit: function (model) {
model.submitButtonState = "busy";
clearNotifications($scope.content);
//we need to return this promise so that the dialog can handle the result and wire up the validation response
return performSave({
saveMethod: contentResource.publish,
action: "publish",
showNotifications: false
}).then(function (data) {
//show all notifications manually here since we disabled showing them automatically in the save method
formHelper.showNotifications(data);
clearNotifications($scope.content);
overlayService.close();
return $q.when(data);
},
function (err) {
clearDirtyState($scope.content.variants);
model.submitButtonState = "error";
//re-map the dialog model since we've re-bound the properties
dialog.variants = $scope.content.variants;
//don't reject, we've handled the error
return $q.when(err);
});
},
close: function () {
overlayService.close();
}
};
overlayService.open(dialog);
}
}
else {
//ensure the flags are set
$scope.content.variants[0].save = true;
$scope.content.variants[0].publish = true;
$scope.page.buttonGroupState = "busy";
return performSave({
saveMethod: contentResource.publish,
action: "publish"
}).then(function () {
$scope.page.buttonGroupState = "success";
}, function () {
$scope.page.buttonGroupState = "error";
});;
}
};
$scope.save = function () {
clearNotifications($scope.content);
// TODO: Add "..." to save button label if there are more than one variant to publish - currently it just adds the elipses if there's more than 1 variant
if (isContentCultureVariant()) {
//before we launch the dialog we want to execute all client side validations first
if (formHelper.submitForm({ scope: $scope, action: "openSaveDialog" })) {
var dialog = {
parentScope: $scope,
view: "views/content/overlays/save.html",
variants: $scope.content.variants, //set a model property for the dialog
skipFormValidation: true, //when submitting the overlay form, skip any client side validation
submitButtonLabelKey: "buttons_save",
submit: function (model) {
model.submitButtonState = "busy";
clearNotifications($scope.content);
//we need to return this promise so that the dialog can handle the result and wire up the validation response
return performSave({
saveMethod: $scope.saveMethod(),
action: "save",
showNotifications: false
}).then(function (data) {
//show all notifications manually here since we disabled showing them automatically in the save method
formHelper.showNotifications(data);
clearNotifications($scope.content);
overlayService.close();
return $q.when(data);
}, function (err) {
clearDirtyState($scope.content.variants);
model.submitButtonState = "error";
//re-map the dialog model since we've re-bound the properties
dialog.variants = $scope.content.variants;
//don't reject, we've handled the error
return $q.when(err);
});
},
close: function (oldModel) {
overlayService.close();
}
};
overlayService.open(dialog);
}
}
else {
//ensure the flags are set
$scope.content.variants[0].save = true;
$scope.page.saveButtonState = "busy";
return performSave({
saveMethod: $scope.saveMethod(),
action: "save"
}).then(function () {
$scope.page.saveButtonState = "success";
}, function () {
$scope.page.saveButtonState = "error";
});
}
};
$scope.schedule = function() {
clearNotifications($scope.content);
//before we launch the dialog we want to execute all client side validations first
if (formHelper.submitForm({ scope: $scope, action: "schedule" })) {
//used to track the original values so if the user doesn't save the schedule and they close the dialog we reset the dates back to what they were.
let origDates = [];
for (let i = 0; i < $scope.content.variants.length; i++) {
origDates.push({
releaseDate: $scope.content.variants[i].releaseDate,
expireDate: $scope.content.variants[i].expireDate
});
}
if (!isContentCultureVariant()) {
//ensure the flags are set
$scope.content.variants[0].save = true;
}
var dialog = {
parentScope: $scope,
view: "views/content/overlays/schedule.html",
variants: $scope.content.variants, //set a model property for the dialog
skipFormValidation: true, //when submitting the overlay form, skip any client side validation
submitButtonLabelKey: "buttons_schedulePublish",
submit: function (model) {
model.submitButtonState = "busy";
clearNotifications($scope.content);
//we need to return this promise so that the dialog can handle the result and wire up the validation response
return performSave({
saveMethod: contentResource.saveSchedule,
action: "schedule",
showNotifications: false
}).then(function (data) {
//show all notifications manually here since we disabled showing them automatically in the save method
formHelper.showNotifications(data);
clearNotifications($scope.content);
overlayService.close();
return $q.when(data);
}, function (err) {
clearDirtyState($scope.content.variants);
//if this is invariant, show the notification errors, else they'll be shown inline with the variant
if (!isContentCultureVariant()) {
formHelper.showNotifications(err.data);
}
model.submitButtonState = "error";
//re-map the dialog model since we've re-bound the properties
dialog.variants = $scope.content.variants;
//don't reject, we've handled the error
return $q.when(err);
});
},
close: function () {
overlayService.close();
//restore the dates
for (let i = 0; i < $scope.content.variants.length; i++) {
$scope.content.variants[i].releaseDate = origDates[i].releaseDate;
$scope.content.variants[i].expireDate = origDates[i].expireDate;
}
}
};
overlayService.open(dialog);
}
};
$scope.publishDescendants = function() {
clearNotifications($scope.content);
//before we launch the dialog we want to execute all client side validations first
if (formHelper.submitForm({ scope: $scope, action: "publishDescendants" })) {
if (!isContentCultureVariant()) {
//ensure the flags are set
$scope.content.variants[0].save = true;
$scope.content.variants[0].publish = true;
}
var dialog = {
parentScope: $scope,
view: "views/content/overlays/publishdescendants.html",
variants: $scope.content.variants, //set a model property for the dialog
skipFormValidation: true, //when submitting the overlay form, skip any client side validation
submitButtonLabelKey: "buttons_publishDescendants",
submit: function (model) {
model.submitButtonState = "busy";
clearNotifications($scope.content);
//we need to return this promise so that the dialog can handle the result and wire up the validation response
return performSave({
saveMethod: function (content, create, files, showNotifications) {
return contentResource.publishWithDescendants(content, create, model.includeUnpublished, files, showNotifications);
},
action: "publishDescendants",
showNotifications: false
}).then(function (data) {
//show all notifications manually here since we disabled showing them automatically in the save method
formHelper.showNotifications(data);
clearNotifications($scope.content);
overlayService.close();
return $q.when(data);
}, function (err) {
clearDirtyState($scope.content.variants);
//if this is invariant, show the notification errors, else they'll be shown inline with the variant
if (!isContentCultureVariant()) {
formHelper.showNotifications(err.data);
}
model.submitButtonState = "error";
//re-map the dialog model since we've re-bound the properties
dialog.variants = $scope.content.variants;
//don't reject, we've handled the error
return $q.when(err);
});
},
close: function () {
overlayService.close();
}
};
overlayService.open(dialog);
}
};
$scope.preview = function (content) {
if (!$scope.busy) {
// Chromes popup blocker will kick in if a window is opened
// without the initial scoped request. This trick will fix that.
//
var previewWindow = $window.open('preview/?init=true', 'umbpreview');
// Build the correct path so both /#/ and #/ work.
var query = 'id=' + content.id;
if ($scope.culture) {
query += "#?culture=" + $scope.culture;
}
var redirect = Umbraco.Sys.ServerVariables.umbracoSettings.umbracoPath + '/preview/?' + query;
//The user cannot save if they don't have access to do that, in which case we just want to preview
//and that's it otherwise they'll get an unauthorized access message
if (!_.contains(content.allowedActions, "A")) {
previewWindow.location.href = redirect;
}
else {
var selectedVariant = $scope.content.variants[0];
if ($scope.culture) {
var found = _.find($scope.content.variants, function (v) {
return (v.language && v.language.culture === $scope.culture);
});
if(found){
selectedVariant = found;
}
}
//ensure the save flag is set
selectedVariant.save = true;
performSave({ saveMethod: $scope.saveMethod(), action: "save" }).then(function (data) {
previewWindow.location.href = redirect;
}, function (err) {
//validation issues ....
});
}
}
};
/* publish method used in infinite editing */
$scope.publishAndClose = function (content) {
$scope.publishAndCloseButtonState = "busy";
performSave({ saveMethod: contentResource.publish, action: "publish" }).then(function () {
if ($scope.infiniteModel.submit) {
$scope.infiniteModel.contentNode = content;
$scope.infiniteModel.submit($scope.infiniteModel);
}
$scope.publishAndCloseButtonState = "success";
});
};
/* save method used in infinite editing */
$scope.saveAndClose = function (content) {
$scope.saveAndCloseButtonState = "busy";
performSave({ saveMethod: $scope.saveMethod(), action: "save" }).then(function () {
if ($scope.infiniteModel.submit) {
$scope.infiniteModel.contentNode = content;
$scope.infiniteModel.submit($scope.infiniteModel);
}
$scope.saveAndCloseButtonState = "success";
});
};
/**
* Call back when a content app changes
* @param {any} app
*/
$scope.appChanged = function (app) {
$scope.app = app;
$scope.$broadcast("editors.apps.appChanged", { app: app });
createButtons($scope.content);
};
/**
* Call back when a content app changes
* @param {any} app
*/
$scope.appAnchorChanged = function (app, anchor) {
//send an event downwards
$scope.$broadcast("editors.apps.appAnchorChanged", { app: app, anchor: anchor });
};
// methods for infinite editing
$scope.close = function () {
if ($scope.infiniteModel.close) {
$scope.infiniteModel.close($scope.infiniteModel);
}
};
/**
* Call back when user click the back-icon
*/
$scope.onBack = function() {
if ($scope.infiniteModel && $scope.infiniteModel.close) {
$scope.infiniteModel.close($scope.infiniteModel);
} else {
// navigate backwards if content has a parent.
$location.path('/' + $routeParams.section + '/' + $routeParams.tree + '/' + $routeParams.method + '/' + $scope.content.parentId);
}
};
//ensure to unregister from all events!
$scope.$on('$destroy', function () {
for (var e in evts) {
eventsService.unsubscribe(evts[e]);
}
//since we are not notifying and clearing server validation messages when they are received due to how the variant
//switching works, we need to ensure they are cleared when this editor is destroyed
if (!$scope.page.isNew) {
serverValidationManager.clear();
}
});
}
function createDirective() {
var directive = {
restrict: 'E',
replace: true,
templateUrl: 'views/components/content/edit.html',
controller: 'Umbraco.Editors.Content.EditorDirectiveController',
scope: {
contentId: "=",
isNew: "=?",
treeAlias: "@",
page: "=?",
saveMethod: "&",
getMethod: "&",
getScaffoldMethod: "&?",
culture: "=?",
infiniteModel: "=?"
}
};
return directive;
}
angular.module('umbraco.directives').controller('Umbraco.Editors.Content.EditorDirectiveController', ContentEditController);
angular.module('umbraco.directives').directive('contentEditor', createDirective);
})();