add partial views macros editor

This commit is contained in:
Mads Rasmussen
2017-01-18 15:39:08 +01:00
parent ef9dd6d803
commit 49d24dada7
2 changed files with 432 additions and 0 deletions

View File

@@ -0,0 +1,309 @@
(function () {
"use strict";
function partialViewMacrosEditController($scope, $routeParams, codefileResource, assetsService, notificationsService, editorState, navigationService, appState, macroService, angularHelper, $timeout, contentEditingHelper, localizationService, templateHelper) {
var vm = this;
var localizeSaving = localizationService.localize("general_saving");
vm.page = {};
vm.page.loading = true;
vm.partialViewMacroFile = {};
//menu
vm.page.menu = {};
vm.page.menu.currentSection = appState.getSectionState("currentSection");
vm.page.menu.currentNode = null;
// bind functions to view model
vm.save = save;
vm.openPageFieldOverlay = openPageFieldOverlay;
vm.openDictionaryItemOverlay = openDictionaryItemOverlay;
vm.openQueryBuilderOverlay = openQueryBuilderOverlay;
vm.openMacroOverlay = openMacroOverlay;
vm.openInsertOverlay = openInsertOverlay;
/* Functions bound to view model */
function save() {
vm.page.saveButtonState = "busy";
vm.partialViewMacro.content = vm.editor.getValue();
contentEditingHelper.contentEditorPerformSave({
statusMessage: localizeSaving,
saveMethod: codefileResource.save,
scope: $scope,
content: vm.partialViewMacro,
// We do not redirect on failure for partial view macros - this is because it is not possible to actually save the partial view
// when server side validation fails - as opposed to content where we are capable of saving the content
// item if server side validation fails
redirectOnFailure: false,
rebindCallback: function (orignal, saved) {}
}).then(function (saved) {
notificationsService.success("Partial View Macro File saved");
vm.page.saveButtonState = "success";
vm.partialViewMacro = saved;
//sync state
editorState.set(vm.partialViewMacro);
// normal tree sync
navigationService.syncTree({ tree: "partialViewMacros", path: vm.partialViewMacro.path, forceReload: true }).then(function (syncArgs) {
vm.page.menu.currentNode = syncArgs.node;
});
// clear $dirty state on form
setFormState("pristine");
}, function (err) {
vm.page.saveButtonState = "error";
localizationService.localize("speechBubbles_validationFailedHeader").then(function (headerValue) {
localizationService.localize("speechBubbles_validationFailedMessage").then(function(msgValue) {
notificationsService.error(headerValue, msgValue);
});
});
});
}
function openInsertOverlay() {
vm.insertOverlay = {
view: "insert",
allowedTypes: {
macro: true,
dictionary: true,
umbracoField: true
},
hideSubmitButton: true,
show: true,
submit: function(model) {
switch(model.insert.type) {
case "macro":
var macroObject = macroService.collectValueData(model.insert.selectedMacro, model.insert.macroParams, "Mvc");
insert(macroObject.syntax);
break;
case "dictionary":
var code = templateHelper.getInsertDictionarySnippet(model.insert.node.name);
insert(code);
break;
case "umbracoField":
insert(model.insert.umbracoField);
break;
}
vm.insertOverlay.show = false;
vm.insertOverlay = null;
},
close: function(oldModel) {
// close the dialog
vm.insertOverlay.show = false;
vm.insertOverlay = null;
// focus editor
vm.editor.focus();
}
};
}
function openMacroOverlay() {
vm.macroPickerOverlay = {
view: "macropicker",
dialogData: {},
show: true,
title: "Insert macro",
submit: function (model) {
var macroObject = macroService.collectValueData(model.selectedMacro, model.macroParams, "Mvc");
insert(macroObject.syntax);
vm.macroPickerOverlay.show = false;
vm.macroPickerOverlay = null;
},
close: function(oldModel) {
// close the dialog
vm.macroPickerOverlay.show = false;
vm.macroPickerOverlay = null;
// focus editor
vm.editor.focus();
}
};
}
function openPageFieldOverlay() {
vm.pageFieldOverlay = {
submitButtonLabel: "Insert",
closeButtonlabel: "Cancel",
view: "insertfield",
show: true,
submit: function (model) {
insert(model.umbracoField);
vm.pageFieldOverlay.show = false;
vm.pageFieldOverlay = null;
},
close: function (model) {
// close the dialog
vm.pageFieldOverlay.show = false;
vm.pageFieldOverlay = null;
// focus editor
vm.editor.focus();
}
};
}
function openDictionaryItemOverlay() {
vm.dictionaryItemOverlay = {
view: "treepicker",
section: "settings",
treeAlias: "dictionary",
entityType: "dictionary",
multiPicker: false,
show: true,
title: "Insert dictionary item",
select: function(node){
var code = templateHelper.getInsertDictionarySnippet(node.name);
insert(code);
vm.dictionaryItemOverlay.show = false;
vm.dictionaryItemOverlay = null;
},
close: function (model) {
// close dialog
vm.dictionaryItemOverlay.show = false;
vm.dictionaryItemOverlay = null;
// focus editor
vm.editor.focus();
}
};
}
function openQueryBuilderOverlay() {
vm.queryBuilderOverlay = {
view: "querybuilder",
show: true,
title: "Query for content",
submit: function (model) {
var code = templateHelper.getQuerySnippet(model.result.queryExpression);
insert(code);
vm.queryBuilderOverlay.show = false;
vm.queryBuilderOverlay = null;
},
close: function (model) {
// close dialog
vm.queryBuilderOverlay.show = false;
vm.queryBuilderOverlay = null;
// focus editor
vm.editor.focus();
}
};
}
/* Local functions */
function init() {
//we need to load this somewhere, for now its here.
assetsService.loadCss("lib/ace-razor-mode/theme/razor_chrome.css");
if ($routeParams.create) {
codefileResource.getScaffold().then(function (partialViewMacro) {
ready(partialViewMacro);
});
} else {
codefileResource.getByPath('partialViewMacros', $routeParams.id).then(function (partialViewMacro) {
ready(partialViewMacro);
});
}
}
function ready(partialViewMacro) {
vm.page.loading = false;
vm.partialViewMacro = partialViewMacro;
//sync state
editorState.set(vm.partialViewMacro);
navigationService.syncTree({ tree: "partialViewMacros", path: vm.partialViewMacro.virtualPath, forceReload: true }).then(function (syncArgs) {
vm.page.menu.currentNode = syncArgs.node;
});
// ace configuration
vm.aceOption = {
mode: "razor",
theme: "chrome",
showPrintMargin: false,
advanced: {
fontSize: '14px'
},
onLoad: function(_editor) {
vm.editor = _editor;
// initial cursor placement
// Keep cursor in name field if we are create a new template
// else set the cursor at the bottom of the code editor
if(!$routeParams.create) {
$timeout(function(){
vm.editor.navigateFileEnd();
vm.editor.focus();
persistCurrentLocation();
});
}
//change on blur, focus
vm.editor.on("blur", persistCurrentLocation);
vm.editor.on("focus", persistCurrentLocation);
}
}
}
function insert(str) {
vm.editor.moveCursorToPosition(vm.currentPosition);
vm.editor.insert(str);
vm.editor.focus();
// set form state to $dirty
setFormState("dirty");
}
function persistCurrentLocation() {
vm.currentPosition = vm.editor.getCursorPosition();
}
function setFormState(state) {
// get the current form
var currentForm = angularHelper.getCurrentForm($scope);
// set state
if(state === "dirty") {
currentForm.$setDirty();
} else if(state === "pristine") {
currentForm.$setPristine();
}
}
init();
}
angular.module("umbraco").controller("Umbraco.Editors.PartialViewMacros.EditController", partialViewMacrosEditController);
})();

View File

@@ -0,0 +1,123 @@
<div ng-controller="Umbraco.Editors.PartialViewMacros.EditController as vm">
<umb-load-indicator ng-if="vm.page.loading"></umb-load-indicator>
<form name="contentForm"
ng-submit="vm.save()"
novalidate
val-form-manager>
<umb-editor-view ng-if="!vm.page.loading">
<umb-editor-header
name="vm.partialViewMacro.name"
hide-alias="true"
description="vm.partialViewMacro.virtualPath"
menu="vm.page.menu"
description-locked="true"
hide-icon="true">
</umb-editor-header>
<umb-editor-container>
<div class="flex" style="margin-bottom: 30px;">
<div class="flex" style="margin-left: auto;">
<div class="btn-group umb-era-button-group dropdown" style="margin-right: 10px;">
<button
type="button"
class="umb-era-button umb-button--s"
ng-click="vm.openInsertOverlay()">
<i class="icon icon-add"></i> Insert
</button>
<a class="umb-era-button umb-button--s dropdown-toggle umb-button-group__toggle" data-toggle="dropdown">
<span class="caret"></span>
</a>
<ul aria-labelledby="dLabel" class="dropdown-menu bottom-up umb-button-group__sub-buttons" role="menu">
<li><a href="" ng-click="vm.openPageFieldOverlay()">Value</a></li>
<li><a href="" ng-click="vm.openMacroOverlay()">Macro</a></li>
<li><a href="" ng-click="vm.openDictionaryItemOverlay()">Dictionary</a></li>
</ul>
</div>
<button
type="button"
style="margin-right: 10px;"
class="umb-era-button umb-button--s"
ng-click="vm.openQueryBuilderOverlay()">
<i class="icon icon-wand"></i> Query builder
</button>
</div>
</div>
<div
auto-scale="85"
umb-ace-editor="vm.aceOption"
model="vm.partialViewMacro.content">
</div>
</umb-editor-container>
<umb-editor-footer>
<umb-editor-footer-content-right>
<umb-button
type="submit"
button-style="success"
state="vm.page.saveButtonState"
shortcut="ctrl+s"
label="Save"
label-key="buttons_save">
</umb-button>
</umb-editor-footer-content-right>
</umb-editor-footer>
</umb-editor-view>
</form>
<umb-overlay
ng-if="vm.insertOverlay.show"
model="vm.insertOverlay"
view="vm.insertOverlay.view"
position="right">
</umb-overlay>
<umb-overlay
ng-if="vm.macroPickerOverlay.show"
model="vm.macroPickerOverlay"
view="vm.macroPickerOverlay.view"
position="right">
</umb-overlay>
<umb-overlay
ng-if="vm.pageFieldOverlay.show"
model="vm.pageFieldOverlay"
position="right"
view="vm.pageFieldOverlay.view">
</umb-overlay>
<umb-overlay
ng-if="vm.dictionaryItemOverlay.show"
model="vm.dictionaryItemOverlay"
position="right"
view="vm.dictionaryItemOverlay.view">
</umb-overlay>
<umb-overlay
ng-if="vm.queryBuilderOverlay.show"
model="vm.queryBuilderOverlay"
position="right"
view="vm.queryBuilderOverlay.view">
</umb-overlay>
</div>