--HG--
branch : dev
This commit is contained in:
Renaud Paquay
2010-11-24 15:25:58 -08:00
12 changed files with 557 additions and 118 deletions

View File

@@ -0,0 +1,84 @@
Feature: Content Types
In order to add new types to my site
As an adminitrator
I want to create create content types
Scenario: I can create a new content type
Given I have installed Orchard
And I have installed "Orchard.ContentTypes"
When I go to "Admin/ContentTypes"
Then I should see "<a[^>]*>.*?Create new type</a>"
When I go to "Admin/ContentTypes/Create"
And I fill in
| name | value |
| DisplayName | Event |
| Name | Event |
And I hit "Create"
And I go to "Admin/ContentTypes/"
Then I should see "Event"
Scenario: I can't create a content type with an already existing name
Given I have installed Orchard
And I have installed "Orchard.ContentTypes"
When I go to "Admin/ContentTypes/Create"
And I fill in
| name | value |
| DisplayName | Event |
| Name | Event |
And I hit "Create"
And I go to "Admin/ContentTypes/"
Then I should see "Event"
When I go to "Admin/ContentTypes/Create"
And I fill in
| name | value |
| DisplayName | Event |
| Name | Event-2 |
And I hit "Create"
Then I should see "<h1[^>]*>.*?New Content Type.*?</h1>"
And I should see "validation-summary-errors"
Scenario: I can't create a content type with an already existing technical name
Given I have installed Orchard
And I have installed "Orchard.ContentTypes"
When I go to "Admin/ContentTypes/Create"
And I fill in
| name | value |
| DisplayName | Dinner |
| Name | Dinner |
And I hit "Create"
And I go to "Admin/ContentTypes/"
Then I should see "Dinner"
When I go to "Admin/ContentTypes/Create"
And I fill in
| name | value |
| DisplayName | Dinner2 |
| Name | Dinner |
And I hit "Create"
Then I should see "<h1[^>]*>.*?New Content Type.*?</h1>"
And I should see "validation-summary-errors"
Scenario: I can't rename a content type with an already existing name
Given I have installed Orchard
And I have installed "Orchard.ContentTypes"
When I go to "Admin/ContentTypes/Create"
And I fill in
| name | value |
| DisplayName | Dinner |
| Name | Dinner |
And I hit "Create"
And I go to "Admin/ContentTypes/"
Then I should see "Dinner"
When I go to "Admin/ContentTypes/Create"
And I fill in
| name | value |
| DisplayName | Event |
| Name | Event |
And I hit "Create"
And I go to "Admin/ContentTypes/"
Then I should see "Event"
When I go to "Admin/ContentTypes/Edit/Dinner"
And I fill in
| name | value |
| DisplayName | Event |
And I hit "Save"
Then I should see "validation-summary-errors"

276
src/Orchard.Specs/ContentTypes.feature.cs generated Normal file
View File

@@ -0,0 +1,276 @@
// ------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by SpecFlow (http://www.specflow.org/).
// SpecFlow Version:1.3.0.0
// Runtime Version:4.0.30319.1
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
// ------------------------------------------------------------------------------
#region Designer generated code
namespace Orchard.Specs
{
using TechTalk.SpecFlow;
[System.CodeDom.Compiler.GeneratedCodeAttribute("TechTalk.SpecFlow", "1.3.0.0")]
[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
[NUnit.Framework.TestFixtureAttribute()]
[NUnit.Framework.DescriptionAttribute("Content Types")]
public partial class ContentTypesFeature
{
private static TechTalk.SpecFlow.ITestRunner testRunner;
#line 1 "ContentTypes.feature"
#line hidden
[NUnit.Framework.TestFixtureSetUpAttribute()]
public virtual void FeatureSetup()
{
testRunner = TechTalk.SpecFlow.TestRunnerManager.GetTestRunner();
TechTalk.SpecFlow.FeatureInfo featureInfo = new TechTalk.SpecFlow.FeatureInfo(new System.Globalization.CultureInfo("en-US"), "Content Types", "In order to add new types to my site\r\nAs an adminitrator\r\nI want to create create" +
" content types", ((string[])(null)));
testRunner.OnFeatureStart(featureInfo);
}
[NUnit.Framework.TestFixtureTearDownAttribute()]
public virtual void FeatureTearDown()
{
testRunner.OnFeatureEnd();
testRunner = null;
}
public virtual void ScenarioSetup(TechTalk.SpecFlow.ScenarioInfo scenarioInfo)
{
testRunner.OnScenarioStart(scenarioInfo);
}
[NUnit.Framework.TearDownAttribute()]
public virtual void ScenarioTearDown()
{
testRunner.OnScenarioEnd();
}
[NUnit.Framework.TestAttribute()]
[NUnit.Framework.DescriptionAttribute("I can create a new content type")]
public virtual void ICanCreateANewContentType()
{
TechTalk.SpecFlow.ScenarioInfo scenarioInfo = new TechTalk.SpecFlow.ScenarioInfo("I can create a new content type", ((string[])(null)));
#line 6
this.ScenarioSetup(scenarioInfo);
#line 7
testRunner.Given("I have installed Orchard");
#line 8
testRunner.And("I have installed \"Orchard.ContentTypes\"");
#line 9
testRunner.When("I go to \"Admin/ContentTypes\"");
#line 10
testRunner.Then("I should see \"<a[^>]*>.*?Create new type</a>\"");
#line 11
testRunner.When("I go to \"Admin/ContentTypes/Create\"");
#line hidden
TechTalk.SpecFlow.Table table1 = new TechTalk.SpecFlow.Table(new string[] {
"name",
"value"});
table1.AddRow(new string[] {
"DisplayName",
"Event"});
table1.AddRow(new string[] {
"Name",
"Event"});
#line 12
testRunner.And("I fill in", ((string)(null)), table1);
#line 16
testRunner.And("I hit \"Create\"");
#line 17
testRunner.And("I go to \"Admin/ContentTypes/\"");
#line 18
testRunner.Then("I should see \"Event\"");
#line hidden
testRunner.CollectScenarioErrors();
}
[NUnit.Framework.TestAttribute()]
[NUnit.Framework.DescriptionAttribute("I can\'t create a content type with an already existing name")]
public virtual void ICanTCreateAContentTypeWithAnAlreadyExistingName()
{
TechTalk.SpecFlow.ScenarioInfo scenarioInfo = new TechTalk.SpecFlow.ScenarioInfo("I can\'t create a content type with an already existing name", ((string[])(null)));
#line 20
this.ScenarioSetup(scenarioInfo);
#line 21
testRunner.Given("I have installed Orchard");
#line 22
testRunner.And("I have installed \"Orchard.ContentTypes\"");
#line 23
testRunner.When("I go to \"Admin/ContentTypes/Create\"");
#line hidden
TechTalk.SpecFlow.Table table2 = new TechTalk.SpecFlow.Table(new string[] {
"name",
"value"});
table2.AddRow(new string[] {
"DisplayName",
"Event"});
table2.AddRow(new string[] {
"Name",
"Event"});
#line 24
testRunner.And("I fill in", ((string)(null)), table2);
#line 28
testRunner.And("I hit \"Create\"");
#line 29
testRunner.And("I go to \"Admin/ContentTypes/\"");
#line 30
testRunner.Then("I should see \"Event\"");
#line 31
testRunner.When("I go to \"Admin/ContentTypes/Create\"");
#line hidden
TechTalk.SpecFlow.Table table3 = new TechTalk.SpecFlow.Table(new string[] {
"name",
"value"});
table3.AddRow(new string[] {
"DisplayName",
"Event"});
table3.AddRow(new string[] {
"Name",
"Event-2"});
#line 32
testRunner.And("I fill in", ((string)(null)), table3);
#line 36
testRunner.And("I hit \"Create\"");
#line 37
testRunner.Then("I should see \"<h1[^>]*>.*?New Content Type.*?</h1>\"");
#line 38
testRunner.And("I should see \"validation-summary-errors\"");
#line hidden
testRunner.CollectScenarioErrors();
}
[NUnit.Framework.TestAttribute()]
[NUnit.Framework.DescriptionAttribute("I can\'t create a content type with an already existing technical name")]
public virtual void ICanTCreateAContentTypeWithAnAlreadyExistingTechnicalName()
{
TechTalk.SpecFlow.ScenarioInfo scenarioInfo = new TechTalk.SpecFlow.ScenarioInfo("I can\'t create a content type with an already existing technical name", ((string[])(null)));
#line 40
this.ScenarioSetup(scenarioInfo);
#line 41
testRunner.Given("I have installed Orchard");
#line 42
testRunner.And("I have installed \"Orchard.ContentTypes\"");
#line 43
testRunner.When("I go to \"Admin/ContentTypes/Create\"");
#line hidden
TechTalk.SpecFlow.Table table4 = new TechTalk.SpecFlow.Table(new string[] {
"name",
"value"});
table4.AddRow(new string[] {
"DisplayName",
"Dinner"});
table4.AddRow(new string[] {
"Name",
"Dinner"});
#line 44
testRunner.And("I fill in", ((string)(null)), table4);
#line 48
testRunner.And("I hit \"Create\"");
#line 49
testRunner.And("I go to \"Admin/ContentTypes/\"");
#line 50
testRunner.Then("I should see \"Dinner\"");
#line 51
testRunner.When("I go to \"Admin/ContentTypes/Create\"");
#line hidden
TechTalk.SpecFlow.Table table5 = new TechTalk.SpecFlow.Table(new string[] {
"name",
"value"});
table5.AddRow(new string[] {
"DisplayName",
"Dinner2"});
table5.AddRow(new string[] {
"Name",
"Dinner"});
#line 52
testRunner.And("I fill in", ((string)(null)), table5);
#line 56
testRunner.And("I hit \"Create\"");
#line 57
testRunner.Then("I should see \"<h1[^>]*>.*?New Content Type.*?</h1>\"");
#line 58
testRunner.And("I should see \"validation-summary-errors\"");
#line hidden
testRunner.CollectScenarioErrors();
}
[NUnit.Framework.TestAttribute()]
[NUnit.Framework.DescriptionAttribute("I can\'t rename a content type with an already existing name")]
public virtual void ICanTRenameAContentTypeWithAnAlreadyExistingName()
{
TechTalk.SpecFlow.ScenarioInfo scenarioInfo = new TechTalk.SpecFlow.ScenarioInfo("I can\'t rename a content type with an already existing name", ((string[])(null)));
#line 60
this.ScenarioSetup(scenarioInfo);
#line 61
testRunner.Given("I have installed Orchard");
#line 62
testRunner.And("I have installed \"Orchard.ContentTypes\"");
#line 63
testRunner.When("I go to \"Admin/ContentTypes/Create\"");
#line hidden
TechTalk.SpecFlow.Table table6 = new TechTalk.SpecFlow.Table(new string[] {
"name",
"value"});
table6.AddRow(new string[] {
"DisplayName",
"Dinner"});
table6.AddRow(new string[] {
"Name",
"Dinner"});
#line 64
testRunner.And("I fill in", ((string)(null)), table6);
#line 68
testRunner.And("I hit \"Create\"");
#line 69
testRunner.And("I go to \"Admin/ContentTypes/\"");
#line 70
testRunner.Then("I should see \"Dinner\"");
#line 71
testRunner.When("I go to \"Admin/ContentTypes/Create\"");
#line hidden
TechTalk.SpecFlow.Table table7 = new TechTalk.SpecFlow.Table(new string[] {
"name",
"value"});
table7.AddRow(new string[] {
"DisplayName",
"Event"});
table7.AddRow(new string[] {
"Name",
"Event"});
#line 72
testRunner.And("I fill in", ((string)(null)), table7);
#line 76
testRunner.And("I hit \"Create\"");
#line 77
testRunner.And("I go to \"Admin/ContentTypes/\"");
#line 78
testRunner.Then("I should see \"Event\"");
#line 79
testRunner.When("I go to \"Admin/ContentTypes/Edit/Dinner\"");
#line hidden
TechTalk.SpecFlow.Table table8 = new TechTalk.SpecFlow.Table(new string[] {
"name",
"value"});
table8.AddRow(new string[] {
"DisplayName",
"Event"});
#line 80
testRunner.And("I fill in", ((string)(null)), table8);
#line 83
testRunner.And("I hit \"Save\"");
#line 84
testRunner.Then("I should see \"validation-summary-errors\"");
#line hidden
testRunner.CollectScenarioErrors();
}
}
}
#endregion

View File

@@ -142,6 +142,11 @@
<AutoGen>True</AutoGen>
<DesignTime>True</DesignTime>
</Compile>
<Compile Include="ContentTypes.feature.cs">
<DependentUpon>ContentTypes.feature</DependentUpon>
<AutoGen>True</AutoGen>
<DesignTime>True</DesignTime>
</Compile>
<Compile Include="Hosting\ExtensionDeploymentOptions.cs" />
<Compile Include="SiteCompilation.feature.cs">
<DependentUpon>SiteCompilation.feature</DependentUpon>
@@ -228,6 +233,10 @@
<Generator>SpecFlowSingleFileGenerator</Generator>
<LastGenOutput>ContentRights.feature.cs</LastGenOutput>
</None>
<None Include="ContentTypes.feature">
<Generator>SpecFlowSingleFileGenerator</Generator>
<LastGenOutput>ContentTypes.feature.cs</LastGenOutput>
</None>
<None Include="SiteCompilation.feature">
<Generator>SpecFlowSingleFileGenerator</Generator>
<LastGenOutput>SiteCompilation.feature.cs</LastGenOutput>

View File

@@ -47,8 +47,12 @@ namespace Orchard.ContentTypes.Controllers {
if(String.IsNullOrWhiteSpace(viewModel.DisplayName)) {
ModelState.AddModelError("DisplayName", T("The Content Type name can't be empty.").ToString());
}
if ( _contentDefinitionService.GetTypes().Any(t => String.Equals(t.Name.Trim(), viewModel.Name.Trim(), StringComparison.OrdinalIgnoreCase)) ) {
ModelState.AddModelError("Name", T("A type with the same technical name already exists.").ToString());
}
if(_contentDefinitionService.GetTypes().Any(t => t.DisplayName == viewModel.DisplayName)) {
if ( _contentDefinitionService.GetTypes().Any(t => String.Equals(t.DisplayName.Trim(), viewModel.DisplayName.Trim(), StringComparison.OrdinalIgnoreCase)) ) {
ModelState.AddModelError("DisplayName", T("A type with the same name already exists.").ToString());
}
@@ -57,13 +61,19 @@ namespace Orchard.ContentTypes.Controllers {
return View(viewModel);
}
var typeViewModel = _contentDefinitionService.AddType(viewModel);
var contentTypeDefinition = _contentDefinitionService.AddType(viewModel.Name, viewModel.DisplayName);
var typeViewModel = new EditTypeViewModel(contentTypeDefinition);
Services.Notifier.Information(T("The \"{0}\" content type has been created.", typeViewModel.DisplayName));
return RedirectToAction("Edit", new { id = typeViewModel.Name });
}
public ActionResult ContentTypeName(string displayName) {
return Json(_contentDefinitionService.GenerateName(displayName));
}
public ActionResult Edit(string id) {
if (!Services.Authorizer.Authorize(Permissions.CreateContentTypes, T("Not allowed to edit a content type.")))
return new HttpUnauthorizedResult();
@@ -90,9 +100,18 @@ namespace Orchard.ContentTypes.Controllers {
TryUpdateModel(edited);
typeViewModel.DisplayName = edited.DisplayName;
if ( String.IsNullOrWhiteSpace(typeViewModel.DisplayName) ) {
ModelState.AddModelError("DisplayName", T("The Content Type name can't be empty.").ToString());
}
if ( _contentDefinitionService.GetTypes().Any(t => String.Equals(t.DisplayName.Trim(), typeViewModel.DisplayName.Trim(), StringComparison.OrdinalIgnoreCase) && !String.Equals(t.Name, id)) ) {
ModelState.AddModelError("DisplayName", T("A type with the same name already exists.").ToString());
}
if (!ModelState.IsValid)
return View(typeViewModel);
_contentDefinitionService.AlterType(typeViewModel, this);
if (!ModelState.IsValid) {

View File

@@ -65,18 +65,24 @@ namespace Orchard.ContentTypes.Services {
return viewModel;
}
public EditTypeViewModel AddType(CreateTypeViewModel typeViewModel) {
var name = GenerateName(typeViewModel.DisplayName);
public ContentTypeDefinition AddType(string name, string displayName) {
if(String.IsNullOrWhiteSpace(displayName)) {
throw new ArgumentException("displayName");
}
while (_contentDefinitionManager.GetTypeDefinition(name) != null)
if(String.IsNullOrWhiteSpace(name)) {
name = GenerateName(displayName);
}
while ( _contentDefinitionManager.GetTypeDefinition(name) != null )
name = VersionName(name);
var contentTypeDefinition = new ContentTypeDefinition(name, typeViewModel.DisplayName);
var contentTypeDefinition = new ContentTypeDefinition(name, displayName);
_contentDefinitionManager.StoreTypeDefinition(contentTypeDefinition);
_contentDefinitionManager.AlterTypeDefinition(name,
cfg => cfg.Creatable().Draftable());
return new EditTypeViewModel(contentTypeDefinition);
return contentTypeDefinition;
}
public void AlterType(EditTypeViewModel typeViewModel, IUpdateModel updateModel) {
@@ -210,20 +216,21 @@ namespace Orchard.ContentTypes.Services {
}
//gratuitously stolen from the RoutableService
private static string GenerateName(string displayName) {
if (string.IsNullOrWhiteSpace(displayName))
return "";
public string GenerateName(string name) {
if ( string.IsNullOrWhiteSpace(name) )
return String.Empty;
var name = displayName;
//todo: might need to be made more restrictive depending on how name is used (like as an XML node name, for instance)
var dissallowed = new Regex(@"[/:?#\[\]@!$&'()*+,;=\s]+");
var dissallowed = new Regex(@"[/:?#\[\]@!$&'()*+,;=\s\""<>]+");
name = dissallowed.Replace(name, "-");
name = name.Trim('-');
name = dissallowed.Replace(name, String.Empty);
name = name.Trim();
if (name.Length > 128)
name = name.Substring(0, 128);
while ( _contentDefinitionManager.GetTypeDefinition(name) != null )
name = VersionName(name);
return name;
}

View File

@@ -1,17 +1,19 @@
using System.Collections.Generic;
using Orchard.ContentManagement;
using Orchard.ContentManagement.MetaData;
using Orchard.ContentManagement.MetaData.Models;
using Orchard.ContentTypes.ViewModels;
namespace Orchard.ContentTypes.Services {
public interface IContentDefinitionService : IDependency {
IEnumerable<EditTypeViewModel> GetTypes();
EditTypeViewModel GetType(string name);
EditTypeViewModel AddType(CreateTypeViewModel typeViewModel);
ContentTypeDefinition AddType(string name, string displayName);
void AlterType(EditTypeViewModel typeViewModel, IUpdateModel updater);
void RemoveType(string name);
void AddPartToType(string partName, string typeName);
void RemovePartFromType(string partName, string typeName);
string GenerateName(string displayName);
IEnumerable<EditPartViewModel> GetParts();
EditPartViewModel GetPart(string name);

View File

@@ -1,5 +1,6 @@
namespace Orchard.ContentTypes.ViewModels {
public class CreateTypeViewModel {
public string DisplayName { get; set; }
public string Name { get; set; }
}
}

View File

@@ -1,10 +1,40 @@
@model Orchard.ContentTypes.ViewModels.CreateTypeViewModel
<h1>@Html.TitleForPage(T("New Content Type").ToString())</h1>@using (Html.BeginFormAntiForgeryPost()) {
@Html.ValidationSummary()
<fieldset>
<label for="DisplayName">@T("Display Name")</label>
@Html.TextBoxFor(m => m.DisplayName, new {@class = "textMedium", autofocus = "autofocus"})
<label for="Name">@T("Technical Name")</label>
@Html.TextBoxFor(m => m.Name, new {@class = "text"})
</fieldset>
<fieldset>
<button class="primaryAction" type="submit">@T("Create")</button>
</fieldset>}
</fieldset>}
@using(Script.Foot()){
<script type="text/javascript">
//<![CDATA[
$(function(){
//pull slug input from tab order
$("#@Html.FieldIdFor(m=>m.Name)").attr("tabindex",-1);
$("#@Html.FieldIdFor(m=>m.DisplayName)").blur(function(){
var name = $("#@Html.FieldIdFor(m=>m.Name)");
if (name.val()) { return true; }
var displayName = $("#@Html.FieldIdFor(m=>m.DisplayName)").val();
jQuery.post(
"@Url.Action("ContentTypeName","Admin",new RouteValueDictionary{{"Area","Orchard.ContentTypes"}})",
{
displayName: $("#@Html.FieldIdFor(m=>m.DisplayName)").val(),
__RequestVerificationToken: $("input[name=__RequestVerificationToken]").val()
},
function(data) {
name.val(data);
},
"json"
);
})
})
//]]>
</script>
}

View File

@@ -12,7 +12,7 @@
@Html.ValidationSummary()
<fieldset>
<label for="DisplayName">@T("Display Name")</label>
@Html.TextBoxFor(m => m.DisplayName, new { @class = "textMedium" })
@Html.TextBoxFor(m => m.DisplayName, new { @class = "textMedium" }) @T("Technical name: {0}", Model.Name)
@* todo: if we continue to go down the midrodata route, some helpers would be nice *@
<meta itemprop="DisplayName" content="@Model.DisplayName" />
@* has unintended consequences (renamging the type) - changing the name creates a new type of that name *@

View File

@@ -3,15 +3,12 @@ using System.Collections.Generic;
using System.IO;
using System.Web;
using System.Web.Mvc;
using JetBrains.Annotations;
using Orchard.ContentManagement;
using Orchard.Core.Contents.Controllers;
using Orchard.Localization;
using Orchard.Media.Models;
using Orchard.Media.Services;
using Orchard.Media.ViewModels;
using Orchard.Settings;
using Orchard.UI.Notify;
using Orchard.Utility.Extensions;
namespace Orchard.Media.Controllers {
[ValidateInput(false)]
@@ -56,11 +53,13 @@ namespace Orchard.Media.Controllers {
[HttpPost]
public ActionResult Create() {
if (!Services.Authorizer.Authorize(Permissions.ManageMediaFiles, T("Couldn't create media folder")))
return new HttpUnauthorizedResult();
var viewModel = new MediaFolderCreateViewModel();
try {
UpdateModel(viewModel);
if (!Services.Authorizer.Authorize(Permissions.ManageMediaFiles, T("Couldn't create media folder")))
return new HttpUnauthorizedResult();
_mediaService.CreateFolder(viewModel.MediaPath, viewModel.Name);
return RedirectToAction("Index");
}
@@ -109,24 +108,17 @@ namespace Orchard.Media.Controllers {
return View(model);
}
[HttpPost]
public ActionResult EditProperties() {
[HttpPost, ActionName("EditProperties")]
[FormValueRequired("submit.Delete")]
public ActionResult EditPropertiesDeletePOST() {
if (!Services.Authorizer.Authorize(Permissions.ManageMediaFiles, T("Couldn't delete media folder")))
return new HttpUnauthorizedResult();
var viewModel = new MediaFolderEditPropertiesViewModel();
try {
UpdateModel(viewModel);
//TODO: There may be better ways to do this.
// Delete
if (!String.IsNullOrEmpty(HttpContext.Request.Form["submit.Delete"])) {
if (!Services.Authorizer.Authorize(Permissions.ManageMediaFiles, T("Couldn't delete media folder")))
return new HttpUnauthorizedResult();
_mediaService.DeleteFolder(viewModel.MediaPath);
}
// Save
else {
if (!Services.Authorizer.Authorize(Permissions.ManageMediaFiles, T("Couldn't rename media folder")))
return new HttpUnauthorizedResult();
_mediaService.RenameFolder(viewModel.MediaPath, viewModel.Name);
}
_mediaService.DeleteFolder(viewModel.MediaPath);
return RedirectToAction("Index");
}
@@ -136,6 +128,25 @@ namespace Orchard.Media.Controllers {
}
}
[HttpPost, ActionName("EditProperties")]
[FormValueRequired("submit.Save")]
public ActionResult EditProperties() {
if (!Services.Authorizer.Authorize(Permissions.ManageMediaFiles, T("Couldn't rename media folder")))
return new HttpUnauthorizedResult();
var viewModel = new MediaFolderEditPropertiesViewModel();
try {
UpdateModel(viewModel);
_mediaService.RenameFolder(viewModel.MediaPath, viewModel.Name);
return RedirectToAction("Index");
} catch (Exception exception) {
Services.Notifier.Error(T("Modifying Folder Properties failed: {0}", exception.Message));
return View(viewModel);
}
}
public ActionResult Add(string folderName, string mediaPath) {
var model = new MediaItemAddViewModel { FolderName = folderName, MediaPath = mediaPath };
return View(model);
@@ -143,11 +154,12 @@ namespace Orchard.Media.Controllers {
[HttpPost]
public ActionResult Add() {
if (!Services.Authorizer.Authorize(Permissions.UploadMediaFiles, T("Couldn't upload media file")))
return new HttpUnauthorizedResult();
var viewModel = new MediaItemAddViewModel();
try {
UpdateModel(viewModel);
if (!Services.Authorizer.Authorize(Permissions.UploadMediaFiles, T("Couldn't upload media file")))
return new HttpUnauthorizedResult();
if(String.IsNullOrWhiteSpace(Request.Files[0].FileName)) {
ModelState.AddModelError("File", T("Select a file to upload").ToString());
@@ -180,11 +192,12 @@ namespace Orchard.Media.Controllers {
[HttpPost]
public ContentResult AddFromClient() {
if (!Services.Authorizer.Authorize(Permissions.UploadMediaFiles))
return Content(string.Format("<script type=\"text/javascript\">var result = {{ error: \"{0}\" }};</script>", T("ERROR: You don't have permission to upload media files")));
var viewModel = new MediaItemAddViewModel();
try {
UpdateModel(viewModel);
if (!Services.Authorizer.Authorize(Permissions.UploadMediaFiles))
return Content(string.Format("<script type=\"text/javascript\">var result = {{ error: \"{0}\" }};</script>", T("ERROR: You don't have permission to upload media files")));
if (Request.Files.Count < 1 || Request.Files[0].ContentLength == 0)
return Content(string.Format("<script type=\"text/javascript\">var result = {{ error: \"{0}\" }};</script>", T("HEY: You didn't give me a file to upload")));
@@ -220,32 +233,42 @@ namespace Orchard.Media.Controllers {
return View(model);
}
[HttpPost]
public ActionResult EditMedia(FormCollection input) {
[HttpPost, ActionName("EditMedia")]
[FormValueRequired("submit.Delete")]
public ActionResult EditMediaDeletePOST(FormCollection input) {
if (!Services.Authorizer.Authorize(Permissions.ManageMediaFiles, T("Couldn't delete media file")))
return new HttpUnauthorizedResult();
var viewModel = new MediaItemEditViewModel();
try {
UpdateModel(viewModel);
if (!Services.Authorizer.Authorize(Permissions.ManageMediaFiles, T("Couldn't modify media file")))
return new HttpUnauthorizedResult();
// Delete
if (!String.IsNullOrEmpty(HttpContext.Request.Form["submit.Delete"])) {
if (!Services.Authorizer.Authorize(Permissions.ManageMediaFiles, T("Couldn't delete media file")))
return new HttpUnauthorizedResult();
_mediaService.DeleteFile(viewModel.Name, viewModel.MediaPath);
return RedirectToAction("Edit", new { name = viewModel.FolderName, mediaPath = viewModel.MediaPath });
}
// Save and Rename
_mediaService.DeleteFile(viewModel.Name, viewModel.MediaPath);
return RedirectToAction("Edit", new { name = viewModel.FolderName, mediaPath = viewModel.MediaPath });
} catch (Exception exception) {
Services.Notifier.Error(T("Removing media file failed: {0}", exception.Message));
return View(viewModel);
}
}
[HttpPost, ActionName("EditMedia")]
[FormValueRequired("submit.Save")]
public ActionResult EditMedia(FormCollection input) {
if (!Services.Authorizer.Authorize(Permissions.ManageMediaFiles, T("Couldn't modify media file")))
return new HttpUnauthorizedResult();
var viewModel = new MediaItemEditViewModel();
try {
UpdateModel(viewModel);
string viewModelName = viewModel.Name;
// Rename
if (!String.Equals(viewModel.Name, input["NewName"], StringComparison.OrdinalIgnoreCase)) {
_mediaService.RenameFile(viewModel.Name, input["NewName"], viewModel.MediaPath);
return RedirectToAction("EditMedia", new { name = input["NewName"],
caption = viewModel.Caption,
lastUpdated = viewModel.LastUpdated,
size = viewModel.Size,
folderName = viewModel.FolderName,
mediaPath = viewModel.MediaPath });
viewModelName = input["NewName"];
}
// Save
return RedirectToAction("EditMedia", new { name = viewModel.Name,
return RedirectToAction("EditMedia", new { name = viewModelName,
caption = viewModel.Caption,
lastUpdated = viewModel.LastUpdated,
size = viewModel.Size,
@@ -258,4 +281,4 @@ namespace Orchard.Media.Controllers {
}
}
}
}
}

View File

@@ -83,9 +83,11 @@ namespace Orchard.Media.Services {
}
public void RenameFile(string name, string newName, string folderName) {
if (FileAllowed(newName, false)) {
_storageProvider.RenameFile(_storageProvider.Combine(folderName, name), _storageProvider.Combine(folderName, newName));
if (!FileAllowed(newName, false)) {
throw new ArgumentException("New file name " + newName + " not allowed.");
}
_storageProvider.RenameFile(_storageProvider.Combine(folderName, name), _storageProvider.Combine(folderName, newName));
}
public string UploadMediaFile(string folderName, HttpPostedFileBase postedFile) {

View File

@@ -13,62 +13,48 @@
new {name = navigation.FolderName, mediaPath = navigation.FolderPath}) <text>&#62; </text>
}
@T("Edit Media")</p>
</div>
</div>
<div class="sections clearBoth">
@using (Html.BeginFormAntiForgeryPost()) {
@Html.ValidationSummary()
<div class="primary">
<div>
<img src="@Model.PublicUrl" class="previewImage"/>
</div>
<fieldset>
@* todo: make these real (including markup) *@
<div>
@* <label>@T("Dimensions: <span>500 x 375 pixels</span>")</label> *@
<label>@T("Size: <span>{0}</span>", Model.Size.ToFriendlySizeString())</label>
<label>@T("Added on: <span>{0}</span>", Model.LastUpdated)</label>
</div>
<div>
<label for="embedPath">@T("Embed:")</label>
<input id="embedPath" class="textMedium" name="embedPath" type="text" readonly="readonly" value="&lt;img src=&quot;@Model.PublicUrl&quot; @* width=&quot;500&quot; height=&quot;375&quot; *@ /&gt;" />
<span class="hint">@T("Copy this html to add this image to your site.")</span>
</div>
<div class="primary">
<div>
<img src="@Model.PublicUrl" class="previewImage"/>
</div>
@* todo: make these real (including markup) *@
<div>
@* <label>@T("Dimensions: <span>500 x 375 pixels</span>")</label> *@
<label>@T("Size: <span>{0}</span>", Model.Size.ToFriendlySizeString())</label>
<label>@T("Added on: <span>{0}</span>", Model.LastUpdated)</label>
</div>
<div>
<label for="embedPath">@T("Embed:")</label>
<input id="embedPath" class="textMedium" name="embedPath" type="text" readonly="readonly" value="&lt;img src=&quot;@Model.PublicUrl&quot; @* width=&quot;500&quot; height=&quot;375&quot; *@ /&gt;" />
<span class="hint">@T("Copy this html to add this image to your site.")</span>
</div>
@using (Html.BeginFormAntiForgeryPost()) {
@Html.ValidationSummary()
<fieldset>
<div>
<label for="Name">@T("Name")</label>
<input id="Name" name="Name" type="hidden" value="@Model.Name"/>
<input id="NewName" class="textMedium" name="NewName" type="text" value="@Model.Name"/>
</div>
<input id="Name" name="Name" type="hidden" value="@Model.Name"/>
<input id="NewName" class="textMedium" name="NewName" type="text" value="@Model.Name"/>
</div>
<div>
<input type="hidden" id="LastUpdated" name="LastUpdated" value="@Model.LastUpdated"/>
<input type="hidden" id="Size" name="Size" value="@Model.Size"/>
<input type="hidden" id="FolderName" name="FolderName" value="@Model.FolderName"/>
<input type="hidden" id="MediaPath" name="MediaPath" value="@Model.MediaPath" />
</div>
</fieldset>
<fieldset>
<input type="hidden" id="LastUpdated" name="LastUpdated" value="@Model.LastUpdated"/>
<input type="hidden" id="Size" name="Size" value="@Model.Size"/>
<input type="hidden" id="FolderName" name="FolderName" value="@Model.FolderName"/>
<input type="hidden" id="MediaPath" name="MediaPath" value="@Model.MediaPath" />
</div>
</fieldset>
<fieldset>
<button class="primaryAction" type="submit" name="submit.Save" value="@T("Save")">@T("Save")</button>
</fieldset>
</div>
@*
<div class="secondary" style="border:1px solid #ff0000;">
<h2>@T("Preview")</h2>
<div><img src="@Href("~/Media/" + Html.Encode(Model.RelativePath + "/" + Model.Name))" class="previewImage" /></div>
<ul>
@// todo: make these real (including markup)
<li><label>@T("Dimensions: <span>500 x 375 pixels</span>")</label></li>
<li><label>@T("Size: <span>{0}</span>", Model.Size)</label></li>
<li><label>@T("Added on: <span>{0} by Orchard User</span>", Model.LastUpdated)</label></li>
<li>
<label for="embedPath">@T("Embed:")</label>
<input id="embedPath" class="text" name="embedPath" type="text" readonly="readonly" value="@T("<img src=\"{0}\" width=\"{1}\" height=\"{2}\" />", ResolveUrl("~/Media/" + Model.RelativePath + "/" + Model.Name), 500, 375)" />
<span class="hint">@T("Copy this html to add this image to your site.")</p>
</li>
</ul>
</div>
*@
}
}
</div>
</div>