Merge pull request #1736 from umbraco/temp-U4-9429
U4-9429 Make new create dialogs for code files (or rethink snippets)
This commit is contained in:
@@ -744,40 +744,9 @@ namespace Umbraco.Core.Services
|
||||
if (CreatingPartialView.IsRaisedEventCancelled(new NewEventArgs<IPartialView>(partialView, true, partialView.Alias, -1), this))
|
||||
return Attempt<IPartialView>.Fail();
|
||||
|
||||
string partialViewHeader;
|
||||
switch (partialViewType)
|
||||
{
|
||||
case PartialViewType.PartialView:
|
||||
partialViewHeader = PartialViewHeader;
|
||||
break;
|
||||
case PartialViewType.PartialViewMacro:
|
||||
partialViewHeader = PartialViewMacroHeader;
|
||||
break;
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException("partialViewType");
|
||||
}
|
||||
|
||||
if (snippetName.IsNullOrWhiteSpace() == false)
|
||||
{
|
||||
//create the file
|
||||
var snippetPathAttempt = TryGetSnippetPath(snippetName);
|
||||
if (snippetPathAttempt.Success == false)
|
||||
{
|
||||
throw new InvalidOperationException("Could not load snippet with name " + snippetName);
|
||||
}
|
||||
|
||||
using (var snippetFile = new StreamReader(System.IO.File.OpenRead(snippetPathAttempt.Result)))
|
||||
{
|
||||
var snippetContent = snippetFile.ReadToEnd().Trim();
|
||||
|
||||
//strip the @inherits if it's there
|
||||
snippetContent = StripPartialViewHeader(snippetContent);
|
||||
|
||||
var content = string.Format("{0}{1}{2}",
|
||||
partialViewHeader,
|
||||
Environment.NewLine, snippetContent);
|
||||
partialView.Content = content;
|
||||
}
|
||||
partialView.Content = GetPartialViewMacroSnippetContent(snippetName, partialViewType);
|
||||
}
|
||||
|
||||
var uow = _fileUowProvider.GetUnitOfWork();
|
||||
@@ -914,6 +883,55 @@ namespace Umbraco.Core.Services
|
||||
}
|
||||
}
|
||||
|
||||
public string GetPartialViewSnippetContent(string snippetName)
|
||||
{
|
||||
return GetPartialViewMacroSnippetContent(snippetName, PartialViewType.PartialView);
|
||||
}
|
||||
|
||||
public string GetPartialViewMacroSnippetContent(string snippetName)
|
||||
{
|
||||
return GetPartialViewMacroSnippetContent(snippetName, PartialViewType.PartialViewMacro);
|
||||
}
|
||||
|
||||
private string GetPartialViewMacroSnippetContent(string snippetName, PartialViewType partialViewType)
|
||||
{
|
||||
if (snippetName.IsNullOrWhiteSpace())
|
||||
throw new ArgumentNullException("snippetName");
|
||||
|
||||
string partialViewHeader;
|
||||
switch (partialViewType)
|
||||
{
|
||||
case PartialViewType.PartialView:
|
||||
partialViewHeader = PartialViewHeader;
|
||||
break;
|
||||
case PartialViewType.PartialViewMacro:
|
||||
partialViewHeader = PartialViewMacroHeader;
|
||||
break;
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException("partialViewType");
|
||||
}
|
||||
|
||||
// Try and get the snippet path
|
||||
var snippetPathAttempt = TryGetSnippetPath(snippetName);
|
||||
if (snippetPathAttempt.Success == false)
|
||||
{
|
||||
throw new InvalidOperationException("Could not load snippet with name " + snippetName);
|
||||
}
|
||||
|
||||
using (var snippetFile = new StreamReader(System.IO.File.OpenRead(snippetPathAttempt.Result)))
|
||||
{
|
||||
var snippetContent = snippetFile.ReadToEnd().Trim();
|
||||
|
||||
//strip the @inherits if it's there
|
||||
snippetContent = StripPartialViewHeader(snippetContent);
|
||||
|
||||
var content = string.Format("{0}{1}{2}",
|
||||
partialViewHeader,
|
||||
Environment.NewLine, snippetContent);
|
||||
return content;
|
||||
}
|
||||
}
|
||||
|
||||
public void SetPartialViewMacroFileContent(string filepath, Stream content)
|
||||
{
|
||||
using (var repository = GetPartialViewRepository(PartialViewType.PartialViewMacro, UowProvider.GetUnitOfWork()))
|
||||
|
||||
@@ -331,6 +331,13 @@ namespace Umbraco.Core.Services
|
||||
/// <returns>The content of the macro partial view.</returns>
|
||||
Stream GetPartialViewMacroFileContentStream(string filepath);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the content of a macro partial view snippet as a string
|
||||
/// </summary>
|
||||
/// <param name="snippetName">The name of the snippet</param>
|
||||
/// <returns></returns>
|
||||
string GetPartialViewMacroSnippetContent(string snippetName);
|
||||
|
||||
/// <summary>
|
||||
/// Sets the content of a macro partial view.
|
||||
/// </summary>
|
||||
@@ -352,6 +359,13 @@ namespace Umbraco.Core.Services
|
||||
/// <returns>The content of the partial view.</returns>
|
||||
Stream GetPartialViewFileContentStream(string filepath);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the content of a partial view snippet as a string.
|
||||
/// </summary>
|
||||
/// <param name="snippetName">The name of the snippet</param>
|
||||
/// <returns>The content of the partial view.</returns>
|
||||
string GetPartialViewSnippetContent(string snippetName);
|
||||
|
||||
/// <summary>
|
||||
/// Sets the content of a partial view.
|
||||
/// </summary>
|
||||
|
||||
@@ -77,39 +77,6 @@ function codefileResource($q, $http, umbDataFormatter, umbRequestHelper) {
|
||||
"Failed to retrieve data for template with alias: " + alias);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* @ngdoc method
|
||||
* @name umbraco.resources.codefileResource#getScaffold
|
||||
* @methodOf umbraco.resources.codefileResource
|
||||
*
|
||||
* @description
|
||||
* Returns a scaffold of an empty codefile item
|
||||
*
|
||||
* The scaffold is used to build editors for code file editors that has not yet been populated with data.
|
||||
*
|
||||
* ##usage
|
||||
* <pre>
|
||||
* codefileResource.getScaffold()
|
||||
* .then(function(template) {
|
||||
* alert('its here!');
|
||||
* });
|
||||
* </pre>
|
||||
*
|
||||
* @returns {Promise} resourcePromise object containing the codefile scaffold.
|
||||
*
|
||||
*/
|
||||
getScaffold: function (id) {
|
||||
|
||||
return umbRequestHelper.resourcePromise(
|
||||
$http.get(
|
||||
umbRequestHelper.getApiUrl(
|
||||
"templateApiBaseUrl",
|
||||
"GetScaffold",
|
||||
[{ id: id }])),
|
||||
"Failed to retrieve data for empty template");
|
||||
},
|
||||
|
||||
/**
|
||||
* @ngdoc method
|
||||
* @name umbraco.resources.codefileResource#deleteByPath
|
||||
@@ -176,7 +143,70 @@ function codefileResource($q, $http, umbDataFormatter, umbRequestHelper) {
|
||||
"PostSave"),
|
||||
codeFile),
|
||||
"Failed to save data for code file " + codeFile.virtualPath);
|
||||
},
|
||||
|
||||
/**
|
||||
* @ngdoc method
|
||||
* @name umbraco.resources.codefileResource#getSnippets
|
||||
* @methodOf umbraco.resources.codefileResource
|
||||
*
|
||||
* @description
|
||||
* Gets code snippets for a given file type
|
||||
*
|
||||
* ##usage
|
||||
* <pre>
|
||||
* codefileResource.getSnippets("partialViews")
|
||||
* .then(function(snippets) {
|
||||
* alert('its here!');
|
||||
* });
|
||||
* </pre>
|
||||
*
|
||||
* @param {string} file type: (partialViews, partialViewMacros)
|
||||
* @returns {Promise} resourcePromise object.
|
||||
*
|
||||
*/
|
||||
getSnippets: function (fileType) {
|
||||
return umbRequestHelper.resourcePromise(
|
||||
$http.get(
|
||||
umbRequestHelper.getApiUrl(
|
||||
"codeFileApiBaseUrl",
|
||||
"GetSnippets?type=" + fileType )),
|
||||
"Failed to get snippet for" + fileType);
|
||||
},
|
||||
|
||||
/**
|
||||
* @ngdoc method
|
||||
* @name umbraco.resources.codefileResource#getScaffold
|
||||
* @methodOf umbraco.resources.codefileResource
|
||||
*
|
||||
* @description
|
||||
* Returns a scaffold of an empty codefile item.
|
||||
*
|
||||
* The scaffold is used to build editors for code file editors that has not yet been populated with data.
|
||||
*
|
||||
* ##usage
|
||||
* <pre>
|
||||
* codefileResource.getScaffold("partialViews", "Breadcrumb")
|
||||
* .then(function(data) {
|
||||
* alert('its here!');
|
||||
* });
|
||||
* </pre>
|
||||
*
|
||||
* @param {string} File type: (scripts, partialViews, partialViewMacros).
|
||||
* @param {string} Snippet name (Ex. Breadcrumb).
|
||||
* @returns {Promise} resourcePromise object.
|
||||
*
|
||||
*/
|
||||
|
||||
getScaffold: function (type, id, snippetName) {
|
||||
return umbRequestHelper.resourcePromise(
|
||||
$http.get(
|
||||
umbRequestHelper.getApiUrl(
|
||||
"codeFileApiBaseUrl",
|
||||
"GetScaffold?type=" + type + "&id=" + id + "&snippetName=" + snippetName)),
|
||||
"Failed to get scaffold for" + type);
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
(function () {
|
||||
"use strict";
|
||||
|
||||
function PartialViewMacrosCreateController($scope, codefileResource, $location, navigationService) {
|
||||
|
||||
var vm = this;
|
||||
var node = $scope.dialogOptions.currentNode;
|
||||
|
||||
vm.snippets = [];
|
||||
vm.showSnippets = false;
|
||||
vm.creatingFolder = false;
|
||||
|
||||
vm.createPartialViewMacro = createPartialViewMacro;
|
||||
vm.showCreateFolder = showCreateFolder;
|
||||
vm.createFolder = createFolder;
|
||||
vm.showCreateFromSnippet = showCreateFromSnippet;
|
||||
|
||||
function onInit() {
|
||||
codefileResource.getSnippets('partialViewMacros')
|
||||
.then(function(snippets) {
|
||||
vm.snippets = snippets;
|
||||
});
|
||||
}
|
||||
|
||||
function createPartialViewMacro(selectedSnippet) {
|
||||
|
||||
var snippet = null;
|
||||
|
||||
if(selectedSnippet && selectedSnippet.fileName) {
|
||||
snippet = selectedSnippet.fileName;
|
||||
}
|
||||
|
||||
$location.path("/developer/partialviewmacros/edit/" + node.id).search("create", "true").search("snippet", snippet);
|
||||
navigationService.hideMenu();
|
||||
|
||||
}
|
||||
|
||||
function showCreateFolder() {
|
||||
vm.creatingFolder = true;
|
||||
}
|
||||
|
||||
function createFolder() {
|
||||
|
||||
}
|
||||
|
||||
function showCreateFromSnippet() {
|
||||
vm.showSnippets = true;
|
||||
}
|
||||
|
||||
onInit();
|
||||
|
||||
}
|
||||
|
||||
angular.module("umbraco").controller("Umbraco.Editors.PartialViewMacros.CreateController", PartialViewMacrosCreateController);
|
||||
})();
|
||||
@@ -0,0 +1,75 @@
|
||||
<div ng-controller="Umbraco.Editors.PartialViewMacros.CreateController as vm" ng-cloak>
|
||||
|
||||
<div class="umbracoDialog umb-dialog-body with-footer">
|
||||
|
||||
<div class="umb-pane" ng-if="!vm.creatingFolder">
|
||||
|
||||
<h5><localize key="create_createUnder">Create an item under</localize> {{currentNode.name}}</h5>
|
||||
|
||||
<!-- Main options -->
|
||||
<div ng-if="!vm.showSnippets">
|
||||
<ul class="umb-actions umb-actions-child">
|
||||
<li>
|
||||
<a href="" ng-click="vm.createPartialViewMacro()" umb-auto-focus>
|
||||
<i class="large icon-article"></i>
|
||||
<span class="menu-label"><localize key="create_newEmptyPartialViewMacro">New empty partial view macro</localize></span>
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="" ng-click="vm.showCreateFromSnippet()">
|
||||
<i class="large icon-article"></i>
|
||||
<span class="menu-label"><localize key="create_newPartialViewMacroFromSnippet">New partial view macro from snippet</localize></span>
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="" ng-click="vm.showCreateFolder()">
|
||||
<i class="large icon-folder"></i>
|
||||
<span class="menu-label"><localize key="general_folder"></localize></span>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<!-- Snippets list -->
|
||||
<div ng-if="vm.showSnippets">
|
||||
<ul class="umb-actions umb-actions-child">
|
||||
<li ng-repeat="snippet in vm.snippets">
|
||||
<a href="" ng-click="vm.createPartialViewMacro(snippet)" style="padding-top: 6px; padding-bottom: 6px;">
|
||||
<i class="icon-article" style="font-size: 20px;"></i>
|
||||
<span class="menu-label" style="margin-left: 0; padding-left: 5px;">{{ snippet.name }}</span>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- Create folder -->
|
||||
<div class="umb-pane" ng-if="vm.creatingFolder">
|
||||
<form novalidate name="createFolderForm"
|
||||
ng-submit="vm.createFolder()"
|
||||
val-form-manager>
|
||||
|
||||
<div ng-show="error">
|
||||
<h5 class="text-error">{{error.errorMsg}}</h5>
|
||||
<p class="text-error">{{error.data.message}}</p>
|
||||
</div>
|
||||
|
||||
<umb-control-group label="Enter a folder name" hide-label="false">
|
||||
<input type="text" name="folderName" ng-model="vm.folderName" class="umb-textstring textstring input-block-level" umb-auto-focus required />
|
||||
</umb-control-group>
|
||||
|
||||
<button type="submit" class="btn btn-primary"><localize key="general_create">Create</localize></button>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- Dialog footer -->
|
||||
<div class="umb-dialog-footer btn-toolbar umb-btn-toolbar">
|
||||
<button class="btn" ng-click="nav.hideDialog(true)">
|
||||
<localize key="buttons_somethingElse">Do something else</localize>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
@@ -227,10 +227,19 @@
|
||||
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) {
|
||||
|
||||
var snippet = "Empty";
|
||||
|
||||
if($routeParams.snippet) {
|
||||
snippet = $routeParams.snippet;
|
||||
}
|
||||
|
||||
codefileResource.getScaffold("partialViewMacros", $routeParams.id, snippet).then(function (partialViewMacro) {
|
||||
ready(partialViewMacro);
|
||||
});
|
||||
|
||||
} else {
|
||||
codefileResource.getByPath('partialViewMacros', $routeParams.id).then(function (partialViewMacro) {
|
||||
ready(partialViewMacro);
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
(function () {
|
||||
"use strict";
|
||||
|
||||
function PartialViewsCreateController($scope, codefileResource, $location, navigationService) {
|
||||
|
||||
var vm = this;
|
||||
var node = $scope.dialogOptions.currentNode;
|
||||
|
||||
vm.snippets = [];
|
||||
vm.showSnippets = false;
|
||||
vm.creatingFolder = false;
|
||||
|
||||
vm.createPartialView = createPartialView;
|
||||
vm.showCreateFolder = showCreateFolder;
|
||||
vm.createFolder = createFolder;
|
||||
vm.showCreateFromSnippet = showCreateFromSnippet;
|
||||
|
||||
function onInit() {
|
||||
codefileResource.getSnippets('partialViews')
|
||||
.then(function(snippets) {
|
||||
vm.snippets = snippets;
|
||||
});
|
||||
}
|
||||
|
||||
function createPartialView(selectedSnippet) {
|
||||
|
||||
var snippet = null;
|
||||
|
||||
if(selectedSnippet && selectedSnippet.fileName) {
|
||||
snippet = selectedSnippet.fileName;
|
||||
}
|
||||
|
||||
$location.path("/settings/partialviews/edit/" + node.id).search("create", "true").search("snippet", snippet);
|
||||
navigationService.hideMenu();
|
||||
|
||||
}
|
||||
|
||||
function showCreateFolder() {
|
||||
vm.creatingFolder = true;
|
||||
}
|
||||
|
||||
function createFolder() {
|
||||
|
||||
}
|
||||
|
||||
function showCreateFromSnippet() {
|
||||
vm.showSnippets = true;
|
||||
}
|
||||
|
||||
onInit();
|
||||
|
||||
}
|
||||
|
||||
angular.module("umbraco").controller("Umbraco.Editors.PartialViews.CreateController", PartialViewsCreateController);
|
||||
})();
|
||||
75
src/Umbraco.Web.UI.Client/src/views/partialviews/create.html
Normal file
75
src/Umbraco.Web.UI.Client/src/views/partialviews/create.html
Normal file
@@ -0,0 +1,75 @@
|
||||
<div ng-controller="Umbraco.Editors.PartialViews.CreateController as vm" ng-cloak>
|
||||
|
||||
<div class="umbracoDialog umb-dialog-body with-footer">
|
||||
|
||||
<div class="umb-pane" ng-if="!vm.creatingFolder">
|
||||
|
||||
<h5><localize key="create_createUnder">Create an item under</localize> {{currentNode.name}}</h5>
|
||||
|
||||
<!-- Main options -->
|
||||
<div ng-if="!vm.showSnippets">
|
||||
<ul class="umb-actions umb-actions-child">
|
||||
<li>
|
||||
<a href="" ng-click="vm.createPartialView()" umb-auto-focus>
|
||||
<i class="large icon-article"></i>
|
||||
<span class="menu-label"><localize key="create_newEmptyPartialView">New empty partial view</localize></span>
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="" ng-click="vm.showCreateFromSnippet()">
|
||||
<i class="large icon-article"></i>
|
||||
<span class="menu-label"><localize key="create_newPartialViewFromSnippet">New partial view from snippet</localize></span>
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="" ng-click="vm.showCreateFolder()">
|
||||
<i class="large icon-folder"></i>
|
||||
<span class="menu-label"><localize key="general_folder"></localize></span>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<!-- Snippets list -->
|
||||
<div ng-if="vm.showSnippets">
|
||||
<ul class="umb-actions umb-actions-child">
|
||||
<li ng-repeat="snippet in vm.snippets">
|
||||
<a href="" ng-click="vm.createPartialView(snippet)" style="padding-top: 6px; padding-bottom: 6px;">
|
||||
<i class="icon-article" style="font-size: 20px;"></i>
|
||||
<span class="menu-label" style="margin-left: 0; padding-left: 5px;">{{ snippet.name }}</span>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- Create folder -->
|
||||
<div class="umb-pane" ng-if="vm.creatingFolder">
|
||||
<form novalidate name="createFolderForm"
|
||||
ng-submit="vm.createFolder()"
|
||||
val-form-manager>
|
||||
|
||||
<div ng-show="error">
|
||||
<h5 class="text-error">{{error.errorMsg}}</h5>
|
||||
<p class="text-error">{{error.data.message}}</p>
|
||||
</div>
|
||||
|
||||
<umb-control-group label="Enter a folder name" hide-label="false">
|
||||
<input type="text" name="folderName" ng-model="vm.folderName" class="umb-textstring textstring input-block-level" umb-auto-focus required />
|
||||
</umb-control-group>
|
||||
|
||||
<button type="submit" class="btn btn-primary"><localize key="general_create">Create</localize></button>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- Dialog footer -->
|
||||
<div class="umb-dialog-footer btn-toolbar umb-btn-toolbar">
|
||||
<button class="btn" ng-click="nav.hideDialog(true)">
|
||||
<localize key="buttons_somethingElse">Do something else</localize>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
@@ -227,15 +227,25 @@
|
||||
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 (partialView) {
|
||||
|
||||
var snippet = "Empty";
|
||||
|
||||
if($routeParams.snippet) {
|
||||
snippet = $routeParams.snippet;
|
||||
}
|
||||
|
||||
codefileResource.getScaffold("partialViews", $routeParams.id, snippet).then(function (partialView) {
|
||||
ready(partialView);
|
||||
});
|
||||
|
||||
} else {
|
||||
codefileResource.getByPath('partialViews', $routeParams.id).then(function (partialView) {
|
||||
ready(partialView);
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function ready(partialView) {
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
(function () {
|
||||
"use strict";
|
||||
|
||||
function ScriptsCreateController($scope, $location, navigationService) {
|
||||
|
||||
var vm = this;
|
||||
var node = $scope.dialogOptions.currentNode;
|
||||
|
||||
vm.creatingFolder = false;
|
||||
vm.folderName = "";
|
||||
vm.fileExtension = "";
|
||||
|
||||
vm.createFile = createFile;
|
||||
vm.showCreateFolder = showCreateFolder;
|
||||
vm.createFolder = createFolder;
|
||||
|
||||
function createFile() {
|
||||
$location.path("/settings/scripts/edit/" + node.id).search("create", "true");
|
||||
navigationService.hideMenu();
|
||||
}
|
||||
|
||||
function showCreateFolder() {
|
||||
vm.creatingFolder = true;
|
||||
}
|
||||
|
||||
function createFolder() {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
angular.module("umbraco").controller("Umbraco.Editors.Scripts.CreateController", ScriptsCreateController);
|
||||
})();
|
||||
47
src/Umbraco.Web.UI.Client/src/views/scripts/create.html
Normal file
47
src/Umbraco.Web.UI.Client/src/views/scripts/create.html
Normal file
@@ -0,0 +1,47 @@
|
||||
<div class="umbracoDialog umb-dialog-body with-footer" ng-controller="Umbraco.Editors.Scripts.CreateController as vm" ng-cloak>
|
||||
|
||||
<div class="umb-pane" ng-if="!vm.creatingFolder">
|
||||
<h5><localize key="create_createUnder">Create an item under</localize> {{currentNode.name}}</h5>
|
||||
|
||||
<ul class="umb-actions umb-actions-child">
|
||||
<li>
|
||||
<a href="" umb-auto-focus ng-click="vm.createFile()">
|
||||
<i class="large icon-script"></i>
|
||||
<span class="menu-label"><localize key="create_newJavascriptFile">New javascript file</localize></span>
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="" ng-click="vm.showCreateFolder()">
|
||||
<i class="large icon-folder"></i>
|
||||
<span class="menu-label"><localize key="general_folder"></localize></span>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="umb-pane" ng-if="vm.creatingFolder">
|
||||
<form novalidate name="createFolderForm"
|
||||
ng-submit="vm.createFolder()"
|
||||
val-form-manager>
|
||||
|
||||
<div ng-show="error">
|
||||
<h5 class="text-error">{{error.errorMsg}}</h5>
|
||||
<p class="text-error">{{error.data.message}}</p>
|
||||
</div>
|
||||
|
||||
<umb-control-group label="Enter a folder name" hide-label="false">
|
||||
<input type="text" name="folderName" ng-model="vm.folderName" class="umb-textstring textstring input-block-level" umb-auto-focus required />
|
||||
</umb-control-group>
|
||||
|
||||
<button type="submit" class="btn btn-primary"><localize key="general_create">Create</localize></button>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="umb-dialog-footer btn-toolbar umb-btn-toolbar" ng-if="!vm.creatingFolder">
|
||||
<button class="btn" ng-click="nav.hideDialog(true)">
|
||||
<localize key="buttons_somethingElse">Do something else</localize>
|
||||
</button>
|
||||
</div>
|
||||
@@ -79,7 +79,7 @@
|
||||
assetsService.loadCss("lib/ace-razor-mode/theme/razor_chrome.css");
|
||||
|
||||
if ($routeParams.create) {
|
||||
codefileResource.getScaffold().then(function (script) {
|
||||
codefileResource.getScaffold("scripts", $routeParams.id).then(function (script) {
|
||||
ready(script);
|
||||
});
|
||||
} else {
|
||||
|
||||
@@ -197,6 +197,11 @@
|
||||
<key alias="documentTypeWithoutTemplate">Document Type without a template</key>
|
||||
<key alias="newFolder">New folder</key>
|
||||
<key alias="newDataType">New data type</key>
|
||||
<key alias="newJavascriptFile">New javascript file</key>
|
||||
<key alias="newEmptyPartialView">New empty partial view</key>
|
||||
<key alias="newPartialViewFromSnippet">New partial view from snippet</key>
|
||||
<key alias="newEmptyPartialViewMacro">New empty partial view macro</key>
|
||||
<key alias="newPartialViewMacroFromSnippet">New partial view macro from snippet</key>
|
||||
</area>
|
||||
<area alias="dashboard">
|
||||
<key alias="browser">Browse your website</key>
|
||||
|
||||
@@ -1,7 +1,12 @@
|
||||
using AutoMapper;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Web.Http;
|
||||
using ClientDependency.Core;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.IO;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Services;
|
||||
using Umbraco.Web.Models.ContentEditing;
|
||||
@@ -9,7 +14,6 @@ using Umbraco.Web.Mvc;
|
||||
using Umbraco.Web.WebApi;
|
||||
using Umbraco.Web.WebApi.Filters;
|
||||
using Umbraco.Web.Trees;
|
||||
using Umbraco.Core.IO;
|
||||
|
||||
namespace Umbraco.Web.Editors
|
||||
{
|
||||
@@ -32,11 +36,13 @@ namespace Umbraco.Web.Editors
|
||||
{
|
||||
case Core.Constants.Trees.PartialViews:
|
||||
var view = new PartialView(display.VirtualPath);
|
||||
view.Content = display.Content;
|
||||
var result = Services.FileService.CreatePartialView(view, display.Snippet, Security.CurrentUser.Id);
|
||||
return result.Success == true ? Request.CreateResponse(HttpStatusCode.OK) : Request.CreateNotificationValidationErrorResponse(result.Exception.Message);
|
||||
|
||||
case Core.Constants.Trees.PartialViewMacros:
|
||||
var viewMacro = new PartialView(display.VirtualPath);
|
||||
viewMacro.Content = display.Content;
|
||||
var resultMacro = Services.FileService.CreatePartialViewMacro(viewMacro, display.Snippet, Security.CurrentUser.Id);
|
||||
return resultMacro.Success == true ? Request.CreateResponse(HttpStatusCode.OK) : Request.CreateNotificationValidationErrorResponse(resultMacro.Exception.Message);
|
||||
|
||||
@@ -105,6 +111,95 @@ namespace Umbraco.Web.Editors
|
||||
throw new HttpResponseException(HttpStatusCode.NotFound);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Used to get a list of available templates/snippets to base a new Partial View og Partial View Macro from
|
||||
/// </summary>
|
||||
/// <param name="type">This is a string but will be 'partialViews', 'partialViewMacros'</param>
|
||||
/// <returns>Returns a list of <see cref="SnippetDisplay"/> if a correct type is sent</returns>
|
||||
public IEnumerable<SnippetDisplay> GetSnippets(string type)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(type))
|
||||
{
|
||||
throw new HttpResponseException(HttpStatusCode.BadRequest);
|
||||
}
|
||||
|
||||
IEnumerable<string> snippets;
|
||||
switch (type)
|
||||
{
|
||||
case Core.Constants.Trees.PartialViews:
|
||||
snippets = Services.FileService.GetPartialViewSnippetNames(
|
||||
//ignore these - (this is taken from the logic in "PartialView.ascx.cs")
|
||||
"Gallery",
|
||||
"ListChildPagesFromChangeableSource",
|
||||
"ListChildPagesOrderedByProperty",
|
||||
"ListImagesFromMediaFolder");
|
||||
break;
|
||||
case Core.Constants.Trees.PartialViewMacros:
|
||||
snippets = Services.FileService.GetPartialViewSnippetNames();
|
||||
break;
|
||||
default:
|
||||
throw new HttpResponseException(HttpStatusCode.NotFound);
|
||||
}
|
||||
|
||||
return snippets.Select(snippet => new SnippetDisplay() {Name = snippet.SplitPascalCasing().ToFirstUpperInvariant(), FileName = snippet});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Used to scaffold the json object for the editors for 'scripts', 'partialViews', 'partialViewMacros'
|
||||
/// </summary>
|
||||
/// <param name="type">This is a string but will be 'scripts' 'partialViews', 'partialViewMacros'</param>
|
||||
/// <param name="id"></param>
|
||||
/// <param name="snippetName"></param>
|
||||
/// <returns></returns>
|
||||
public CodeFileDisplay GetScaffold(string type, string id = null, string snippetName = null)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(type))
|
||||
{
|
||||
throw new HttpResponseException(HttpStatusCode.BadRequest);
|
||||
}
|
||||
|
||||
if (id.IsNullOrWhiteSpace())
|
||||
id = string.Empty;
|
||||
|
||||
CodeFileDisplay codeFileDisplay;
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case Core.Constants.Trees.PartialViews:
|
||||
codeFileDisplay = Mapper.Map<IPartialView, CodeFileDisplay>(new PartialView(string.Empty));
|
||||
codeFileDisplay.VirtualPath = SystemDirectories.PartialViews;
|
||||
if (snippetName.IsNullOrWhiteSpace() == false)
|
||||
codeFileDisplay.Content = Services.FileService.GetPartialViewSnippetContent(snippetName);
|
||||
break;
|
||||
case Core.Constants.Trees.PartialViewMacros:
|
||||
codeFileDisplay = Mapper.Map<IPartialView, CodeFileDisplay>(new PartialView(string.Empty));
|
||||
codeFileDisplay.VirtualPath = SystemDirectories.MacroPartials;
|
||||
if (snippetName.IsNullOrWhiteSpace() == false)
|
||||
codeFileDisplay.Content = Services.FileService.GetPartialViewMacroSnippetContent(snippetName);
|
||||
break;
|
||||
case Core.Constants.Trees.Scripts:
|
||||
codeFileDisplay = Mapper.Map<Script, CodeFileDisplay>(new Script(string.Empty));
|
||||
codeFileDisplay.VirtualPath = SystemDirectories.Scripts;
|
||||
break;
|
||||
default:
|
||||
throw new HttpResponseException(Request.CreateErrorResponse(HttpStatusCode.BadRequest, "Unsupported editortype"));
|
||||
}
|
||||
|
||||
// Make sure that the root virtual path ends with '/'
|
||||
codeFileDisplay.VirtualPath = codeFileDisplay.VirtualPath.EnsureEndsWith("/");
|
||||
|
||||
if (id.IsNullOrWhiteSpace() == false && id != Core.Constants.System.Root.ToInvariantString())
|
||||
{
|
||||
codeFileDisplay.VirtualPath += id.TrimStart("/").EnsureEndsWith("/");
|
||||
}
|
||||
|
||||
codeFileDisplay.VirtualPath = codeFileDisplay.VirtualPath.TrimStart("~");
|
||||
codeFileDisplay.Path = Url.GetTreePathFromFilePath(id);
|
||||
codeFileDisplay.FileType = type;
|
||||
|
||||
return codeFileDisplay;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Used to delete a specific file from disk via the FileService
|
||||
/// </summary>
|
||||
@@ -150,7 +245,7 @@ namespace Umbraco.Web.Editors
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Used to save/update an existing file after its initial creation
|
||||
/// Used to create or update a 'partialview', 'partialviewmacro' or 'script' file
|
||||
/// </summary>
|
||||
/// <param name="display"></param>
|
||||
/// <returns>The updated CodeFileDisplay model</returns>
|
||||
@@ -166,81 +261,56 @@ namespace Umbraco.Web.Editors
|
||||
throw new HttpResponseException(HttpStatusCode.NotFound);
|
||||
}
|
||||
|
||||
|
||||
switch (display.FileType)
|
||||
{
|
||||
case Core.Constants.Trees.PartialViews:
|
||||
var view = Services.FileService.GetPartialView(display.VirtualPath);
|
||||
if (view != null)
|
||||
var partialViewResult = CreateOrUpdatePartialView(display);
|
||||
if (partialViewResult.Success)
|
||||
{
|
||||
// might need to find the path
|
||||
var orgPath = view.OriginalPath.Substring(0, view.OriginalPath.IndexOf(view.Name));
|
||||
view.Path = orgPath + display.Name;
|
||||
view.Content = display.Content;
|
||||
|
||||
//Save the file and update the response to reflect any name and path changes
|
||||
var result = Services.FileService.SavePartialView(view, Security.CurrentUser.Id);
|
||||
if (result.Success == true)
|
||||
{
|
||||
display = Mapper.Map(result.Result, display);
|
||||
display.Path = Url.GetTreePathFromFilePath(view.Path);
|
||||
return display;
|
||||
}
|
||||
|
||||
display.AddErrorNotification(
|
||||
Services.TextService.Localize("speechBubbles/partialViewErrorHeader"),
|
||||
Services.TextService.Localize("speechBubbles/partialViewErrorText"));
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new HttpResponseException(HttpStatusCode.NotFound);
|
||||
display = Mapper.Map(partialViewResult.Result, display);
|
||||
display.Path = Url.GetTreePathFromFilePath(partialViewResult.Result.Path);
|
||||
return display;
|
||||
}
|
||||
|
||||
display.AddErrorNotification(
|
||||
Services.TextService.Localize("speechBubbles/partialViewErrorHeader"),
|
||||
Services.TextService.Localize("speechBubbles/partialViewErrorText"));
|
||||
break;
|
||||
|
||||
case Core.Constants.Trees.PartialViewMacros:
|
||||
var viewMacro = Services.FileService.GetPartialViewMacro(display.VirtualPath);
|
||||
if (viewMacro != null)
|
||||
var partialViewMacroResult = CreateOrUpdatePartialViewMacro(display);
|
||||
if (partialViewMacroResult.Success)
|
||||
{
|
||||
viewMacro.Content = display.Content;
|
||||
viewMacro.Path = display.Name;
|
||||
|
||||
//save the file and update the display to reflect any path and name changes
|
||||
var result = Services.FileService.SavePartialViewMacro(viewMacro, Security.CurrentUser.Id);
|
||||
if (result.Success == true)
|
||||
{
|
||||
display = Mapper.Map(result.Result, display);
|
||||
display.Path = Url.GetTreePathFromFilePath(result.Result.Path);
|
||||
return display;
|
||||
}
|
||||
|
||||
display.AddErrorNotification(
|
||||
Services.TextService.Localize("speechBubbles/partialViewErrorHeader"),
|
||||
Services.TextService.Localize("speechBubbles/partialViewErrorText"));
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new HttpResponseException(HttpStatusCode.NotFound);
|
||||
display = Mapper.Map(partialViewMacroResult.Result, display);
|
||||
display.Path = Url.GetTreePathFromFilePath(partialViewMacroResult.Result.Path);
|
||||
return display;
|
||||
}
|
||||
|
||||
display.AddErrorNotification(
|
||||
Services.TextService.Localize("speechBubbles/partialViewErrorHeader"),
|
||||
Services.TextService.Localize("speechBubbles/partialViewErrorText"));
|
||||
break;
|
||||
|
||||
case Core.Constants.Trees.Scripts:
|
||||
var virtualPath = display.VirtualPath;
|
||||
var script = Services.FileService.GetScriptByName(display.VirtualPath);
|
||||
if (script != null)
|
||||
{
|
||||
script.Content = display.Content;
|
||||
script.Path = display.Name;
|
||||
|
||||
Services.FileService.SaveScript(script, Security.CurrentUser.Id);
|
||||
display = Mapper.Map(script, display);
|
||||
display.Path = Url.GetTreePathFromFilePath(script.Path);
|
||||
return display;
|
||||
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new HttpResponseException(HttpStatusCode.NotFound);
|
||||
var fileName = EnsurePartialViewExtension(display.Name, ".js");
|
||||
script = new Script(virtualPath + fileName);
|
||||
}
|
||||
|
||||
script.Content = display.Content;
|
||||
|
||||
Services.FileService.SaveScript(script, Security.CurrentUser.Id);
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -249,5 +319,74 @@ namespace Umbraco.Web.Editors
|
||||
|
||||
return display;
|
||||
}
|
||||
|
||||
private Attempt<IPartialView> CreateOrUpdatePartialView(CodeFileDisplay display)
|
||||
{
|
||||
Attempt<IPartialView> partialViewResult;
|
||||
string virtualPath = NormalizeVirtualPath(display.VirtualPath, SystemDirectories.PartialViews);
|
||||
var view = Services.FileService.GetPartialView(virtualPath);
|
||||
if (view != null)
|
||||
{
|
||||
// might need to find the path
|
||||
var orgPath = view.OriginalPath.Substring(0, view.OriginalPath.IndexOf(view.Name));
|
||||
view.Path = orgPath + display.Name;
|
||||
|
||||
view.Content = display.Content;
|
||||
partialViewResult = Services.FileService.SavePartialView(view, Security.CurrentUser.Id);
|
||||
}
|
||||
else
|
||||
{
|
||||
var fileName = EnsurePartialViewExtension(display.Name, ".cshtml");
|
||||
view = new PartialView(virtualPath + fileName);
|
||||
view.Content = display.Content;
|
||||
partialViewResult = Services.FileService.CreatePartialView(view, display.Snippet, Security.CurrentUser.Id);
|
||||
}
|
||||
|
||||
return partialViewResult;
|
||||
}
|
||||
|
||||
private string NormalizeVirtualPath(string virtualPath, string systemDirectory)
|
||||
{
|
||||
if (virtualPath.IsNullOrWhiteSpace())
|
||||
return string.Empty;
|
||||
|
||||
systemDirectory = systemDirectory.TrimStart("~");
|
||||
systemDirectory = systemDirectory.Replace('\\', '/');
|
||||
virtualPath = virtualPath.TrimStart("~");
|
||||
virtualPath = virtualPath.Replace('\\', '/');
|
||||
virtualPath = virtualPath.ReplaceFirst(systemDirectory, string.Empty);
|
||||
|
||||
return virtualPath;
|
||||
}
|
||||
|
||||
private Attempt<IPartialView> CreateOrUpdatePartialViewMacro(CodeFileDisplay display)
|
||||
{
|
||||
Attempt<IPartialView> partialViewMacroResult;
|
||||
var virtualPath = display.VirtualPath ?? string.Empty;
|
||||
var viewMacro = Services.FileService.GetPartialViewMacro(virtualPath);
|
||||
if (viewMacro != null)
|
||||
{
|
||||
viewMacro.Content = display.Content;
|
||||
viewMacro.Path = display.Name;
|
||||
partialViewMacroResult = Services.FileService.SavePartialViewMacro(viewMacro, Security.CurrentUser.Id);
|
||||
}
|
||||
else
|
||||
{
|
||||
var fileName = EnsurePartialViewExtension(display.Name, ".cshtml");
|
||||
viewMacro = new PartialView(virtualPath + fileName);
|
||||
viewMacro.Content = display.Content;
|
||||
partialViewMacroResult = Services.FileService.CreatePartialViewMacro(viewMacro, display.Snippet, Security.CurrentUser.Id);
|
||||
}
|
||||
|
||||
return partialViewMacroResult;
|
||||
}
|
||||
|
||||
private string EnsurePartialViewExtension(string value, string extension)
|
||||
{
|
||||
if (value.EndsWith(extension) == false)
|
||||
value += extension;
|
||||
|
||||
return value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
14
src/Umbraco.Web/Models/ContentEditing/SnippetDisplay.cs
Normal file
14
src/Umbraco.Web/Models/ContentEditing/SnippetDisplay.cs
Normal file
@@ -0,0 +1,14 @@
|
||||
using System.Runtime.Serialization;
|
||||
|
||||
namespace Umbraco.Web.Models.ContentEditing
|
||||
{
|
||||
[DataContract(Name = "scriptFile", Namespace = "")]
|
||||
public class SnippetDisplay
|
||||
{
|
||||
[DataMember(Name = "name", IsRequired = true)]
|
||||
public string Name { get; set; }
|
||||
|
||||
[DataMember(Name = "fileName", IsRequired = true)]
|
||||
public string FileName { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -34,13 +34,26 @@ namespace Umbraco.Web.Trees
|
||||
|
||||
if (id == Constants.System.Root.ToInvariantString())
|
||||
{
|
||||
|
||||
//set the default to create
|
||||
menu.DefaultMenuAlias = ActionNew.Instance.Alias;
|
||||
//create action
|
||||
menu.Items.Add<ActionNew>(Services.TextService.Localize(string.Format("actions/{0}", ActionNew.Instance.Alias)));
|
||||
//refresh action
|
||||
menu.Items.Add<RefreshNode, ActionRefresh>(Services.TextService.Localize(string.Format("actions/{0}", ActionRefresh.Instance.Alias)), true);
|
||||
|
||||
return menu;
|
||||
}
|
||||
|
||||
if (id.EndsWith(FileSearchPattern.TrimStart("*")) == false)
|
||||
{
|
||||
//set the default to create
|
||||
menu.DefaultMenuAlias = ActionNew.Instance.Alias;
|
||||
//create action
|
||||
menu.Items.Add<ActionNew>(Services.TextService.Localize(string.Format("actions/{0}", ActionNew.Instance.Alias)));
|
||||
//refresh action
|
||||
menu.Items.Add<RefreshNode, ActionRefresh>(Services.TextService.Localize(string.Format("actions/{0}", ActionRefresh.Instance.Alias)), true);
|
||||
}
|
||||
|
||||
// TODO: Wire up new delete dialog
|
||||
menu.Items.Add<ActionDelete>(Services.TextService.Localize(string.Format("actions/{0}", ActionDelete.Instance.Alias)));
|
||||
return menu;
|
||||
|
||||
@@ -33,13 +33,26 @@ namespace Umbraco.Web.Trees
|
||||
|
||||
if (id == Constants.System.Root.ToInvariantString())
|
||||
{
|
||||
|
||||
//set the default to create
|
||||
menu.DefaultMenuAlias = ActionNew.Instance.Alias;
|
||||
//create action
|
||||
menu.Items.Add<ActionNew>(Services.TextService.Localize(string.Format("actions/{0}", ActionNew.Instance.Alias)));
|
||||
//refresh action
|
||||
menu.Items.Add<RefreshNode, ActionRefresh>(Services.TextService.Localize(string.Format("actions/{0}", ActionRefresh.Instance.Alias)), true);
|
||||
|
||||
return menu;
|
||||
}
|
||||
|
||||
if (id.EndsWith(FileSearchPattern.TrimStart("*")) == false)
|
||||
{
|
||||
//set the default to create
|
||||
menu.DefaultMenuAlias = ActionNew.Instance.Alias;
|
||||
//create action
|
||||
menu.Items.Add<ActionNew>(Services.TextService.Localize(string.Format("actions/{0}", ActionNew.Instance.Alias)));
|
||||
//refresh action
|
||||
menu.Items.Add<RefreshNode, ActionRefresh>(Services.TextService.Localize(string.Format("actions/{0}", ActionRefresh.Instance.Alias)), true);
|
||||
}
|
||||
|
||||
// TODO: Wire up new delete dialog
|
||||
menu.Items.Add<ActionDelete>(Services.TextService.Localize(string.Format("actions/{0}", ActionDelete.Instance.Alias)));
|
||||
return menu;
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using Umbraco.Core;
|
||||
using System.Linq;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.IO;
|
||||
using umbraco.BusinessLogic.Actions;
|
||||
using Umbraco.Web.Models.Trees;
|
||||
@@ -30,13 +31,26 @@ namespace Umbraco.Web.Trees
|
||||
|
||||
if (id == Constants.System.Root.ToInvariantString())
|
||||
{
|
||||
|
||||
//set the default to create
|
||||
menu.DefaultMenuAlias = ActionNew.Instance.Alias;
|
||||
//create action
|
||||
menu.Items.Add<ActionNew>(Services.TextService.Localize(string.Format("actions/{0}", ActionNew.Instance.Alias)));
|
||||
//refresh action
|
||||
menu.Items.Add<RefreshNode, ActionRefresh>(Services.TextService.Localize(string.Format("actions/{0}", ActionRefresh.Instance.Alias)), true);
|
||||
|
||||
return menu;
|
||||
}
|
||||
|
||||
if (id.EndsWith(FileSearchPattern.TrimStart("*")) == false)
|
||||
{
|
||||
//set the default to create
|
||||
menu.DefaultMenuAlias = ActionNew.Instance.Alias;
|
||||
//create action
|
||||
menu.Items.Add<ActionNew>(Services.TextService.Localize(string.Format("actions/{0}", ActionNew.Instance.Alias)));
|
||||
//refresh action
|
||||
menu.Items.Add<RefreshNode, ActionRefresh>(Services.TextService.Localize(string.Format("actions/{0}", ActionRefresh.Instance.Alias)), true);
|
||||
}
|
||||
|
||||
// TODO: Wire up new delete dialog
|
||||
menu.Items.Add<ActionDelete>(Services.TextService.Localize(string.Format("actions/{0}", ActionDelete.Instance.Alias)));
|
||||
return menu;
|
||||
|
||||
@@ -338,6 +338,7 @@
|
||||
<Compile Include="Models\ContentEditing\PropertyGroupBasic.cs" />
|
||||
<Compile Include="Models\ContentEditing\PropertyTypeBasic.cs" />
|
||||
<Compile Include="Models\ContentEditing\SimpleNotificationModel.cs" />
|
||||
<Compile Include="Models\ContentEditing\SnippetDisplay.cs" />
|
||||
<Compile Include="Models\ContentEditing\TemplateDisplay.cs" />
|
||||
<Compile Include="Models\LocalPackageInstallModel.cs" />
|
||||
<Compile Include="Models\Mapping\CodeFileDisplayMapper.cs" />
|
||||
|
||||
Reference in New Issue
Block a user