Media dialog upload and folder creation

This commit is contained in:
perploug
2013-08-27 16:01:39 +02:00
parent 208453f364
commit 8b1fcf3e07
19 changed files with 359 additions and 190 deletions

View File

@@ -324,7 +324,7 @@
}
])
// Provide File Upload progress feedback:
/* Provide File Upload progress feedback:
.controller('FileUploadProgressController', [
'$scope', '$attrs', '$parse',
function ($scope, $attrs, $parse) {
@@ -360,14 +360,14 @@
$element.append(file.preview);
}
}
])
])*/
.directive('fileUpload', function () {
return {
controller: 'FileUploadController'
};
})
/*
.directive('fileUploadProgress', function () {
return {
controller: 'FileUploadProgressController'
@@ -378,7 +378,7 @@
return {
controller: 'FileUploadPreviewController'
};
})
})*/
// Enhance the HTML5 download attribute to
// allow drag&drop of files to the desktop:

View File

@@ -28,7 +28,7 @@ angular.module("umbraco.directives")
setTimeout(function () {
el.height(window.height() - (el.offset().top + totalOffset));
}, 300);
}, 500);
window.bind("resize", function () {
el.height(window.height() - (el.offset().top + totalOffset));

View File

@@ -11,6 +11,21 @@
* the entity only contains the basic node data, name, id and guid, whereas content
* nodes fetched through the entity service also contains additional meta data such
* as icon, document type, path and so on.
*
* ##Entity object types?
* As an optional parameter, you can pass in the specific type name. So if you know you
* are looking for a specific type, you should pass in the object name, to make lookup faster
* and to return more data.
*
* The core object types are:
*
* - Document
* - Media
* - Member
* - Template
* - DocumentType
* - MediaType
* - MemberType
**/
function entityResource($q, $http, umbRequestHelper) {
@@ -32,19 +47,27 @@ function entityResource($q, $http, umbRequestHelper) {
* var myDoc = ent;
* alert('its here!');
* });
*
* //Only return users
* entityResource.getEntityById(0, "User")
* .then(function(ent) {
* var myDoc = ent;
* alert('its here!');
* });
* </pre>
*
* @param {Int} id id of entity to return
* @param {Int} id id of entity to return
* @param {string} type optional Object type name
* @returns {Promise} resourcePromise object containing the entity.
*
*/
getEntityById: function (id) {
getById: function (id, type) {
return umbRequestHelper.resourcePromise(
$http.get(
umbRequestHelper.getApiUrl(
"entityApiBaseUrl",
"GetEntityById",
[{ id: id }])),
"GetById",
[{ id: id, type: type }])),
'Failed to retreive entity data for id ' + id);
},
@@ -63,13 +86,21 @@ function entityResource($q, $http, umbRequestHelper) {
* var myDoc = contentArray;
* alert('they are here!');
* });
*
* //Only return templates
* entityResource.getEntitiesByIds( [1234,2526,28262], "Template")
* .then(function(templateArray) {
* var myDoc = contentArray;
* alert('they are here!');
* });
* </pre>
*
* @param {Array} ids ids of entities to return as an array
* @param {Array} ids ids of entities to return as an array
* @param {string} type optional type name
* @returns {Promise} resourcePromise object containing the entity array.
*
*/
getEntitiesByIds: function (ids) {
getByIds: function (ids) {
var idQuery = "";
_.each(ids, function(item) {
@@ -80,11 +111,90 @@ function entityResource($q, $http, umbRequestHelper) {
$http.get(
umbRequestHelper.getApiUrl(
"entityApiBaseUrl",
"GetEntitiesByIds",
"GetByIds",
idQuery)),
'Failed to retreive entity data for ids ' + idQuery);
},
/**
* @ngdoc method
* @name umbraco.resources.entityResource#getEntityById
* @methodOf umbraco.resources.entityResource
*
* @description
* Gets an entity with a given id
*
* ##usage
* <pre>
* //returns all entities, you should NEVER do that
* entityResource.getAll()
* .then(function(ent) {
* var myDoc = ent;
* alert('its here!');
* });
*
* //Only return users
* entityResource.getAll("User")
* .then(function(ent) {
* var myDoc = ent;
* alert('its here!');
* });
* </pre>
*
* @param {string} type Object type name
* @returns {Promise} resourcePromise object containing the entity.
*
*/
getAll: function (type) {
return umbRequestHelper.resourcePromise(
$http.get(
umbRequestHelper.getApiUrl(
"entityApiBaseUrl",
"GetAll",
[{type: type }])),
'Failed to retreive entity data for id ' + id);
},
/**
* @ngdoc method
* @name umbraco.resources.entityResource#getEntityById
* @methodOf umbraco.resources.entityResource
*
* @description
* Gets an entity with a given id
*
* ##usage
* <pre>
* //returns all entities, you should NEVER do that
* entityResource.getAll()
* .then(function(ent) {
* var myDoc = ent;
* alert('its here!');
* });
*
* //Only return users
* entityResource.getAll("User")
* .then(function(ent) {
* var myDoc = ent;
* alert('its here!');
* });
* </pre>
*
* @param {string} type Object type name
* @returns {Promise} resourcePromise object containing the entity.
*
*/
getAncestors: function (id) {
return umbRequestHelper.resourcePromise(
$http.get(
umbRequestHelper.getApiUrl(
"entityApiBaseUrl",
"GetAncestors",
[{id: id}])),
'Failed to retreive entity data for id ' + id);
},
/**
* @ngdoc method
* @name umbraco.resources.entityResource#getDocumentById

View File

@@ -108,6 +108,18 @@ function mediaResource($q, $http, umbDataFormatter, umbRequestHelper) {
/** saves or updates a media object */
save: function (media, isNew, files) {
return saveMediaItem(media, "save" + (isNew ? "New" : ""), files);
},
//** shorthand for creating a new folder under a given parent **/
addFolder: function(name, parentId){
return umbRequestHelper.resourcePromise(
$http.post(umbRequestHelper
.getApiUrl("mediaApiBaseUrl", "PostAddFolder"),
{
name: name,
parentId: parentId
}),
'Failed to add folder');
}
};
}

View File

@@ -173,8 +173,11 @@ angular.module('umbraco.services')
};
scope.select = function(item) {
if (scope.dialogData.selection.indexOf(item) < 0) {
var i = scope.dialogData.selection.indexOf(item);
if (i < 0) {
scope.dialogData.selection.push(item);
}else{
scope.dialogData.selection.splice(i, 1);
}
};

View File

@@ -15,6 +15,13 @@
.hover-show{visibility: hidden;}
*:hover > .hover-show{visibility: visible;}
//breadcrumb modifications
.breadcrumb{height: 30px; display: block; margin-top: 10px;}
.breadcrumb li{height: 30px; vertical-align: middle;}
.breadcrumb li a{vertical-align: middle; height: 30px;}
.breadcrumb input{font-size: 11px !Important;}
/* SEACH FORM */

View File

@@ -313,7 +313,7 @@ height:1px;
overflow:hidden;
}
.umb-tree li div.l div{
.umb-tree li div.l div, div.umb-loader{
background-color: @blue;
margin-top:0;
margin-left:-100%;

View File

@@ -1,16 +1,41 @@
//used for the media picker dialog
angular.module("umbraco")
.controller("Umbraco.Dialogs.MediaPickerController",
function ($scope, mediaResource, $log, imageHelper) {
function ($scope, mediaResource, umbRequestHelper, entityResource, $log, imageHelper) {
$scope.options = {
url: "/umbraco/UmbracoApi/MediaUpload/Post",
url: umbRequestHelper.getApiUrl("mediaApiBaseUrl", "PostAddFile"),
autoUpload: true,
formData:{
currentFolder: -1
}
};
$scope.submitFolder = function(e){
if(e.keyCode === 13){
$scope.showFolderInput = false;
mediaResource
.addFolder($scope.newFolderName, $scope.options.formData.currentFolder)
.then(function(data){
$scope.gotoFolder(data.id);
});
}
};
$scope.gotoFolder = function(folderId){
if(folderId > 0){
entityResource.getAncestors(folderId)
.then(function(anc){
anc.splice(0,1);
$scope.path = anc;
});
}else{
$scope.path = [];
}
//mediaResource.rootMedia()
mediaResource.getChildren(folderId)
.then(function(data) {
@@ -20,33 +45,25 @@ angular.module("umbraco")
img.thumbnail = imageHelper.getThumbnail({ imageModel: img, scope: $scope });
});
});
}
$scope.$on('fileuploadadd', function(event, files){
$scope.submitFiles();
});
$scope.options.formData.currentFolder = folderId;
};
$scope.$on('fileuploadstop', function(event, files){
alert("done");
$scope.gotoFolder($scope.options.formData.currentFolder);
});
$scope.selectMediaItem = function(image) {
if (image.contentTypeAlias.toLowerCase() == 'folder') {
options.formData.currentFolder = image.id;
mediaResource.getChildren(image.id)
.then(function(data) {
$scope.images = data;
//update the thumbnail property
_.each($scope.images, function (img) {
img.thumbnail = imageHelper.getThumbnail({ imageModel: img, scope: $scope });
});
});
if (image.contentTypeAlias.toLowerCase() == 'folder') {
$scope.options.formData.currentFolder = image.id;
$scope.gotoFolder(image.id);
}
else if (image.contentTypeAlias.toLowerCase() == 'image') {
$scope.select(image);
}
};
$scope.gotoFolder(-1);
});

View File

@@ -1,5 +1,5 @@
<form ng-controller="Umbraco.Dialogs.MediaPickerController" id="fileupload" method="POST" enctype="multipart/form-data"
data-file-upload="options" data-ng-class="{'fileupload-processing': processing() || loadingFiles}">
data-file-upload="options" data-file-upload-progress="" data-ng-class="{'fileupload-processing': processing() || loadingFiles}">
<div class="umb-panel">
<div class="umb-panel-header">
@@ -17,9 +17,6 @@ data-file-upload="options" data-ng-class="{'fileupload-processing': processing()
</div>
<div class="pull-right umb-btn-toolbar">
{{progress | json}}
<span class="btn fileinput-button" ng-class="{disabled: disabled}">
<i class="icon-upload"></i>
<input type="file" name="files[]" multiple ng-disabled="disabled">
@@ -29,65 +26,56 @@ data-file-upload="options" data-ng-class="{'fileupload-processing': processing()
</div>
</div>
<div class="umb-panel-body umb-scrollable" auto-scale="70">
<div class="umb-pane">
<div class="umb-control-group">
<div class="control-group umb-control-group">
<ul class="breadcrumb">
<li><a href ng-click="gotoFolder(-1)" prevent-default>Media</a> /</li>
<li ng-repeat="item in path">
<a href ng-click="gotoFolder(item.id)" prevent-default>{{item.name}}</a>/
</li>
<ul class="breadcrumb">
<li><strong>You are here:</strong></li>
<li><a href ng-click="gotoFolder(-1)" prevent-default>Media</a></li>
</ul>
{{queue | json}}
<li>
<a href ng-hide="showFolderInput" ng-click="showFolderInput = true">
<i class="icon icon-expand-alt"></i>
</a>
<table class="table table-striped files ng-cloak">
<tr data-ng-repeat="file in queue">
<td>
<p class="name" data-ng-switch data-on="!!file.url">
<span data-ng-switch-when="true" data-ng-switch data-on="!!file.thumbnailUrl">
<a data-ng-switch-when="true" data-ng-href="{{file.url}}" title="{{file.name}}" download="{{file.name}}" data-gallery>{{file.name}}</a>
<a data-ng-switch-default data-ng-href="{{file.url}}" title="{{file.name}}" download="{{file.name}}">{{file.name}}</a>
</span>
<span data-ng-switch-default>{{file.name}}</span>
</p>
<div data-ng-show="file.error"><span class="label label-important">Error</span> {{file.error}}</div>
</td>
<td>
<p class="size">{{file.size | formatFileSize}}</p>
<div class="progress progress-striped active fade" data-ng-class="{pending: 'in'}[file.$state()]" data-file-upload-progress="file.$progress()"><div class="progress-bar progress-bar-success" data-ng-style="{width: num + '%'}"></div></div>
</td>
</tr>
</table>
<ul class="thumbnails">
<li class="span2 folder" ng-repeat="image in images">
<a href="#" class="thumbnail" ng-class="{selected: dialogData.selection.indexOf(image) > -1}"
ng-click="selectMediaItem(image)"
prevent-default>
<div ng-switch on="image.contentTypeAlias" >
<img ng-src="{{image.thumbnail}}" ng-switch-when="Image" alt="{{image.name}}"/>
<i ng-switch-default class="icon-folder-close"></i>
</div>
{{image.name}}
</a>
</li>
</ul>
</div>
<input type="text"
class="input-foldername input-mini inline"
ng-show="showFolderInput"
ng-model="newFolderName"
ng-keyup="submitFolder($event)"
ng-blur="showFolderInput = false"
>
</li>
</ul>
</div>
<div style="height: 10px; margin: 10px 0px 10px 0px" class="umb-loader" ng-hide="active() == 0"></div>
<ul class="thumbnails">
<li class="span2 folder" ng-repeat="image in images | orderBy:'contentTypeAlias'">
<a href="#" class="thumbnail" ng-class="{selected: dialogData.selection.indexOf(image) > -1}"
ng-click="selectMediaItem(image)"
prevent-default>
<div ng-switch on="image.contentTypeAlias" >
<img ng-src="{{image.thumbnail}}" ng-switch-when="Image" alt="{{image.name}}"/>
<i ng-switch-default class="icon-folder-close"></i>
</div>
{{image.name}}
</a>
</li>
</ul>
</div>
<div class="umb-panel-footer">
<div class="umb-el-wrap umb-panel-buttons">
<div class="pull-right umb-btn-toolbar">
<button type="button" ng-click="submit(dialogData)" class="btn btn-primary">Select ({{selectedItems}})</button>
<button ng-show="dialogData.selection.length > 0" type="button" ng-click="submit(dialogData)" class="btn btn-primary">Select ({{dialogData.selection.length}})</button>
</div>
</div>
</div>

View File

@@ -3,7 +3,7 @@
angular.module('umbraco').controller("Umbraco.Editors.MediaPickerController",
function($rootScope, $scope, dialogService, $log){
//
$( "#draggable" ).draggable();
//$( "#draggable" ).draggable();
$scope.openMediaPicker =function(value){
var d = dialogService.mediaPicker({scope: $scope, callback: populate});

View File

@@ -1,62 +1,32 @@
<div ng-controller="Umbraco.Editors.MediaPickerController">
<div class="umb-image-crop">
<div class="umb-image-mask">
<i class="icon-screenshot"></i>
<i class="icon-circle"></i>
<img src="/media/dummy/crop-large.png" alt="">
<div ng-show="currentImage" class="umb-image-crop">
<div class="umb-image-mask">
<i class="icon-screenshot"></i>
<i class="icon-circle"></i>
<img src="/media/dummy/crop-large.png" alt="">
</div>
<div class="umb-image-controls clearfix">
<i class="icon icon-minus"></i>
<input class="range" type="range" min="0" max="100" step="5" value="35">
<i class="icon icon-plus"></i>
</div>
</div>
<div class="umb-image-controls clearfix">
<i class="icon icon-minus"></i>
<input class="range" type="range" min="0" max="100" step="5" value="35">
<i class="icon icon-plus"></i>
</div>
</div>
<ul class="thumbnails umb-crop-preview">
<li class="umb-thumbnail">
<a href="#">
<img src="/media/dummy/crop-preview-horizontal.png" alt="">
<ul class="thumbnails umb-crop-preview">
<li class="umb-thumbnail" ng-repeat="image in images">
<a href ng-click="crop(image)">
<img ng-src="image.src" alt="">
</a>
</li>
<li class="umb-thumbnail">
<a href="#">
<img src="/media/dummy/crop-preview-square.png" alt="">
</a>
</li>
<li class="umb-thumbnail">
<a href="#">
<img src="/media/dummy/crop-preview-vertical.png" alt="">
</a>
</li>
</ul>
<ul class="thumbnails">
<li class="span4" ng-repeat="image in value">
<a href="#" class="thumbnail" prevent-default>
<img ng-src="{{image.thumbnail}}" />
</a>
</li>
<li class="umb-plus-btn">
<li class="umb-thumbnail span4">
<a href="#" ng-click="openMediaPicker(value)" prevent-default>
<i class="icon icon-plus"></i>
</a>
</li>
<li class="umb-thumbnail">
<a href="#" ng-click="openMediaPicker(value)" prevent-default>
<img src="/media/dummy/crop-horizontal.png" alt="">
</a>
</li>
<li class="umb-thumbnail">
<div class="umb-icons">
<i class="icon-crop"></i>
<i class="icon-remove"></i>
</div>
<a href="#" ng-click="openMediaPicker(value)" prevent-default>
<img src="/media/dummy/crop-vertival.png" alt="">
</a>
</li>
<li class="umb-thumbnail">
<a href="#" ng-click="openMediaPicker(value)" prevent-default>
<img src="/media/dummy/crop-square.png" alt="">
</a>
</li>
</ul>
</ul>
</div>

Binary file not shown.

After

Width:  |  Height:  |  Size: 817 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 441 KiB

View File

@@ -1,5 +1,5 @@
<form ng-controller="Umbraco.Dialogs.MediaPickerController" id="fileupload" method="POST" enctype="multipart/form-data"
data-file-upload="options" data-ng-class="{'fileupload-processing': processing() || loadingFiles}">
data-file-upload="options" data-file-upload-progress="" data-ng-class="{'fileupload-processing': processing() || loadingFiles}">
<div class="umb-panel">
<div class="umb-panel-header">
@@ -17,9 +17,6 @@ data-file-upload="options" data-ng-class="{'fileupload-processing': processing()
</div>
<div class="pull-right umb-btn-toolbar">
{{progress | json}}
<span class="btn fileinput-button" ng-class="{disabled: disabled}">
<i class="icon-upload"></i>
<input type="file" name="files[]" multiple ng-disabled="disabled">
@@ -29,65 +26,56 @@ data-file-upload="options" data-ng-class="{'fileupload-processing': processing()
</div>
</div>
<div class="umb-panel-body umb-scrollable" auto-scale="70">
<div class="umb-pane">
<div class="umb-control-group">
<div class="control-group umb-control-group">
<ul class="breadcrumb">
<li><a href ng-click="gotoFolder(-1)" prevent-default>Media</a> /</li>
<li ng-repeat="item in path">
<a href ng-click="gotoFolder(item.id)" prevent-default>{{item.name}}</a>/
</li>
<ul class="breadcrumb">
<li><strong>You are here:</strong></li>
<li><a href ng-click="gotoFolder(-1)" prevent-default>Media</a></li>
</ul>
{{queue | json}}
<li>
<a href ng-hide="showFolderInput" ng-click="showFolderInput = true">
<i class="icon icon-expand-alt"></i>
</a>
<table class="table table-striped files ng-cloak">
<tr data-ng-repeat="file in queue">
<td>
<p class="name" data-ng-switch data-on="!!file.url">
<span data-ng-switch-when="true" data-ng-switch data-on="!!file.thumbnailUrl">
<a data-ng-switch-when="true" data-ng-href="{{file.url}}" title="{{file.name}}" download="{{file.name}}" data-gallery>{{file.name}}</a>
<a data-ng-switch-default data-ng-href="{{file.url}}" title="{{file.name}}" download="{{file.name}}">{{file.name}}</a>
</span>
<span data-ng-switch-default>{{file.name}}</span>
</p>
<div data-ng-show="file.error"><span class="label label-important">Error</span> {{file.error}}</div>
</td>
<td>
<p class="size">{{file.size | formatFileSize}}</p>
<div class="progress progress-striped active fade" data-ng-class="{pending: 'in'}[file.$state()]" data-file-upload-progress="file.$progress()"><div class="progress-bar progress-bar-success" data-ng-style="{width: num + '%'}"></div></div>
</td>
</tr>
</table>
<ul class="thumbnails">
<li class="span2 folder" ng-repeat="image in images">
<a href="#" class="thumbnail" ng-class="{selected: dialogData.selection.indexOf(image) > -1}"
ng-click="selectMediaItem(image)"
prevent-default>
<div ng-switch on="image.contentTypeAlias" >
<img ng-src="{{image.thumbnail}}" ng-switch-when="Image" alt="{{image.name}}"/>
<i ng-switch-default class="icon-folder-close"></i>
</div>
{{image.name}}
</a>
</li>
</ul>
</div>
<input type="text"
class="input-foldername input-mini inline"
ng-show="showFolderInput"
ng-model="newFolderName"
ng-keyup="submitFolder($event)"
ng-blur="showFolderInput = false"
>
</li>
</ul>
</div>
<div style="height: 10px; margin: 10px 0px 10px 0px" class="umb-loader" ng-hide="active() == 0"></div>
<ul class="thumbnails">
<li class="span2 folder" ng-repeat="image in images | orderBy:'contentTypeAlias'">
<a href="#" class="thumbnail" ng-class="{selected: dialogData.selection.indexOf(image) > -1}"
ng-click="selectMediaItem(image)"
prevent-default>
<div ng-switch on="image.contentTypeAlias" >
<img ng-src="{{image.thumbnail}}" ng-switch-when="Image" alt="{{image.name}}"/>
<i ng-switch-default class="icon-folder-close"></i>
</div>
{{image.name}}
</a>
</li>
</ul>
</div>
<div class="umb-panel-footer">
<div class="umb-el-wrap umb-panel-buttons">
<div class="pull-right umb-btn-toolbar">
<button type="button" ng-click="submit(dialogData)" class="btn btn-primary">Select ({{selectedItems}})</button>
<button ng-show="dialogData.selection.length > 0" type="button" ng-click="submit(dialogData)" class="btn btn-primary">Select ({{dialogData.selection.length}})</button>
</div>
</div>
</div>

View File

@@ -207,6 +207,37 @@ namespace Umbraco.Web.Editors
}
}
//shorthand to use with the media dialog
public MediaItemDisplay PostAddFolder(MediaFolderSave folder)
{
var mediaService = base.ApplicationContext.Services.MediaService;
var f = mediaService.CreateMedia(folder.Name, folder.ParentId, "Folder");
mediaService.Save(f);
return Mapper.Map<IMedia, MediaItemDisplay>(f);
}
//short hand to use with the uploader in the media dialog
public HttpResponseMessage PostAddFile()
{
var context = UmbracoContext.HttpContext;
if(context.Request.Files.Count > 0){
var parentId = int.Parse(context.Request.Form[0]);
var file = context.Request.Files[0];
var name = file.FileName;
var mediaService = base.ApplicationContext.Services.MediaService;
var f = mediaService.CreateMedia(name, parentId, "Image");
f.SetValue("umbracoFile", file);
mediaService.Save(f);
return new HttpResponseMessage( HttpStatusCode.OK);
}
return new HttpResponseMessage(HttpStatusCode.InternalServerError);
}
/// <summary>
/// Performs a permissions check for the user to check if it has access to the node based on
/// start node and/or permissions for the node

View File

@@ -149,6 +149,9 @@ namespace Umbraco.Web.Editors
// Upload entire file
private void UploadWholeFile(HttpContext context, List<FilesStatus> statuses)
{
var folderId = context.Request.Form["currentFolder"];
for (int i = 0; i < context.Request.Files.Count; i++)
{
var file = context.Request.Files[i];

View File

@@ -0,0 +1,22 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Runtime.Serialization;
using System.Text;
using System.Threading.Tasks;
namespace Umbraco.Web.Models.ContentEditing
{
[DataContract(Name = "media", Namespace = "")]
public class MediaFolderSave
{
[DataMember(Name = "name", IsRequired = true)]
[Required]
public string Name { get; set; }
[DataMember(Name = "parentId", IsRequired = true)]
[Required]
public int ParentId { get; set; }
}
}

View File

@@ -0,0 +1,16 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Umbraco.Core;
using Umbraco.Core.PropertyEditors;
namespace Umbraco.Web.PropertyEditors
{
[PropertyEditor(Constants.PropertyEditors.MediaPicker, "Media Picker", "mediapicker")]
public class MediaPickerPropertyEditor : PropertyEditor
{
}
}

View File

@@ -307,6 +307,7 @@
<Compile Include="Models\ContentEditing\DataTypeDisplay.cs" />
<Compile Include="Models\ContentEditing\DataTypeSave.cs" />
<Compile Include="Models\ContentEditing\EntityBasic.cs" />
<Compile Include="Models\ContentEditing\MediaFolderSave.cs" />
<Compile Include="Models\ContentEditing\PreValueFieldDisplay.cs" />
<Compile Include="Models\ContentEditing\PreValueFieldSave.cs" />
<Compile Include="Models\ContentEditing\PropertyEditorBasic.cs" />
@@ -322,6 +323,7 @@
<Compile Include="PropertyEditors\DateTimePropertyEditor.cs" />
<Compile Include="PropertyEditors\DateTimeValidator.cs" />
<Compile Include="PropertyEditors\DropDownMultiplePropertyEditor.cs" />
<Compile Include="PropertyEditors\MediaPicker.cs" />
<Compile Include="PropertyEditors\PublishValuesMultipleValueEditor.cs" />
<Compile Include="PropertyEditors\DropDownMultipleWithKeysPropertyEditor.cs" />
<Compile Include="PropertyEditors\ValueListPreValueEditor.cs" />