--HG--
branch : dev
This commit is contained in:
Sebastien Ros
2010-11-08 13:22:07 -08:00
318 changed files with 3546 additions and 3190 deletions

View File

@@ -48,7 +48,8 @@
<MSBuild
Projects="$(SrcFolder)\Orchard.Azure\Orchard.Azure.CloudService.sln"
Targets="Build"
Properties="Configuration=Release;OutputPath=$(CompileFolder);PlatformTarget=x64" />
Properties="Configuration=Release;OutputPath=$(CompileFolder);PlatformTarget=x64;DefineConstants=AZURE"
/>
<MSBuild
Projects="$(SrcFolder)\Orchard.Azure.sln"

Binary file not shown.

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

View File

@@ -50,7 +50,7 @@ namespace Orchard.Azure.Tests.FileSystems.Media {
Assert.AreEqual(".txt", storageFile.GetFileType());
Assert.AreEqual("foo.txt", storageFile.GetName());
Assert.That(storageFile.GetPath().EndsWith("/default/foo.txt"), Is.True);
Assert.AreEqual("foo.txt", storageFile.GetPath());
Assert.AreEqual(0, storageFile.GetSize());
}
@@ -71,7 +71,8 @@ namespace Orchard.Azure.Tests.FileSystems.Media {
var files = _azureBlobStorageProvider.ListFiles("");
Assert.AreEqual(1, files.Count());
Assert.That(files.First().GetPath().EndsWith("foo2.txt"), Is.True);
Assert.That(files.First().GetPath().Equals("foo2.txt"), Is.True);
Assert.That(files.First().GetName().Equals("foo2.txt"), Is.True);
}
[Test]
@@ -82,17 +83,28 @@ namespace Orchard.Azure.Tests.FileSystems.Media {
Assert.AreEqual(1, _azureBlobStorageProvider.ListFiles("").Count());
Assert.AreEqual(1, _azureBlobStorageProvider.ListFiles("folder").Count());
Assert.AreEqual("folder/foo.txt", _azureBlobStorageProvider.ListFiles("folder").First().GetPath());
Assert.AreEqual("foo.txt", _azureBlobStorageProvider.ListFiles("folder").First().GetName());
Assert.AreEqual(1, _azureBlobStorageProvider.ListFiles("folder/folder").Count());
Assert.AreEqual("folder/folder/foo.txt", _azureBlobStorageProvider.ListFiles("folder/folder").First().GetPath());
Assert.AreEqual("foo.txt", _azureBlobStorageProvider.ListFiles("folder/folder").First().GetName());
}
[Test]
[ExpectedException(typeof(ArgumentException))]
public void CreateFolderThatExistsShouldThrow() {
// sebros: In Azure, the folder concept is just about checking files prefix. So until a file exists, a folder is nothing
_azureBlobStorageProvider.CreateFile("folder/foo.txt");
_azureBlobStorageProvider.CreateFolder("folder");
}
[Test]
public void ListFolderShouldAcceptNullPath() {
_azureBlobStorageProvider.CreateFolder("folder");
Assert.AreEqual(1, _azureBlobStorageProvider.ListFolders(null).Count());
Assert.AreEqual("folder", _azureBlobStorageProvider.ListFolders(null).First().GetName());
Assert.AreEqual("folder", _azureBlobStorageProvider.ListFolders(null).First().GetPath());
}
[Test]
public void DeleteFolderShouldDeleteFilesAlso() {
_azureBlobStorageProvider.CreateFile("folder/foo1.txt");

View File

@@ -8,11 +8,15 @@ using Microsoft.WindowsAzure.StorageClient;
using Orchard.FileSystems.Media;
namespace Orchard.Azure {
public class AzureFileSystem {
public class AzureFileSystem
{
private const string FolderEntry = "$$$ORCHARD$$$.$$$";
public string ContainerName { get; protected set; }
private readonly CloudStorageAccount _storageAccount;
private readonly string _root;
private readonly string _absoluteRoot;
public CloudBlobClient BlobClient { get; private set; }
public CloudBlobContainer Container { get; private set; }
@@ -25,6 +29,7 @@ namespace Orchard.Azure {
_storageAccount = storageAccount;
ContainerName = containerName;
_root = String.IsNullOrEmpty(root) || root == "/" ? String.Empty : root + "/";
_absoluteRoot = _storageAccount.BlobEndpoint.AbsoluteUri + containerName + "/" + root + "/";
using ( new HttpContextWeaver() ) {
@@ -46,66 +51,65 @@ namespace Orchard.Azure {
}
private static void EnsurePathIsRelative(string path) {
if ( path.StartsWith("/") || path.StartsWith("http://"))
if (path.StartsWith("/") || path.StartsWith("http://"))
throw new ArgumentException("Path must be relative");
}
public IStorageFile GetFile(string path) {
EnsurePathIsRelative(path);
path = String.Concat(_root, path);
using ( new HttpContextWeaver() )
{
Container.EnsureBlobExists(path);
return new AzureBlobFileStorage(Container.GetBlockBlobReference(path));
using ( new HttpContextWeaver() ) {
Container.EnsureBlobExists(String.Concat(_root, path));
return new AzureBlobFileStorage(Container.GetBlockBlobReference(path), _absoluteRoot);
}
}
public bool FileExists(string path) {
using ( new HttpContextWeaver() )
{
path = String.Concat(_root, path);
return Container.BlobExists(path);
using ( new HttpContextWeaver() ) {
return Container.BlobExists(String.Concat(_root, path));
}
}
public IEnumerable<IStorageFile> ListFiles(string path) {
path = path ?? String.Empty;
EnsurePathIsRelative(path);
string prefix = String.Concat(Container.Name, "/", _root, path);
if ( !prefix.EndsWith("/") )
prefix += "/";
using ( new HttpContextWeaver() )
{
foreach (var blobItem in BlobClient.ListBlobsWithPrefix(prefix).OfType<CloudBlockBlob>())
{
yield return new AzureBlobFileStorage(blobItem);
using ( new HttpContextWeaver() ) {
foreach (var blobItem in BlobClient.ListBlobsWithPrefix(prefix).OfType<CloudBlockBlob>()) {
// ignore directory entries
if(blobItem.Uri.AbsoluteUri.EndsWith(FolderEntry))
continue;
yield return new AzureBlobFileStorage(blobItem, _absoluteRoot);
}
}
}
public IEnumerable<IStorageFolder> ListFolders(string path) {
path = path ?? String.Empty;
EnsurePathIsRelative(path);
path = String.Concat(_root, path);
using ( new HttpContextWeaver() )
{
if (!Container.DirectoryExists(path))
{
try
{
CreateFolder(path);
using ( new HttpContextWeaver() ) {
if ( !Container.DirectoryExists(String.Concat(_root, path)) ) {
try {
CreateFolder(String.Concat(_root, path));
}
catch (Exception ex)
{
catch ( Exception ex ) {
throw new ArgumentException(string.Format("The folder could not be created at path: {0}. {1}",
path, ex));
}
}
return Container.GetDirectoryReference(path)
return Container.GetDirectoryReference(String.Concat(_root, path))
.ListBlobs()
.OfType<CloudBlobDirectory>()
.Select<CloudBlobDirectory, IStorageFolder>(d => new AzureBlobFolderStorage(d))
.Select<CloudBlobDirectory, IStorageFolder>(d => new AzureBlobFolderStorage(d, _absoluteRoot))
.ToList();
}
}
@@ -113,23 +117,20 @@ namespace Orchard.Azure {
public void CreateFolder(string path)
{
EnsurePathIsRelative(path);
path = String.Concat(_root, path);
using (new HttpContextWeaver())
{
Container.EnsureDirectoryDoesNotExist(path);
Container.GetDirectoryReference(path);
using (new HttpContextWeaver()) {
Container.EnsureDirectoryDoesNotExist(String.Concat(_root, path));
// Creating a virtually hidden file to make the directory an existing concept
CreateFile(path + "/" + FolderEntry);
}
}
public void DeleteFolder(string path) {
EnsurePathIsRelative(path);
path = String.Concat(_root, path);
using ( new HttpContextWeaver() )
{
Container.EnsureDirectoryExists(path);
foreach (var blob in Container.GetDirectoryReference(path).ListBlobs())
{
using ( new HttpContextWeaver() ) {
Container.EnsureDirectoryExists(String.Concat(_root, path));
foreach ( var blob in Container.GetDirectoryReference(String.Concat(_root, path)).ListBlobs() ) {
if (blob is CloudBlob)
((CloudBlob) blob).Delete();
@@ -141,7 +142,6 @@ namespace Orchard.Azure {
public void RenameFolder(string path, string newPath) {
EnsurePathIsRelative(path);
EnsurePathIsRelative(newPath);
if ( !path.EndsWith("/") )
@@ -149,20 +149,16 @@ namespace Orchard.Azure {
if ( !newPath.EndsWith("/") )
newPath += "/";
using ( new HttpContextWeaver() )
{
foreach (var blob in Container.GetDirectoryReference(_root + path).ListBlobs())
{
if (blob is CloudBlob)
{
using ( new HttpContextWeaver() ) {
foreach (var blob in Container.GetDirectoryReference(_root + path).ListBlobs()) {
if (blob is CloudBlob) {
string filename = Path.GetFileName(blob.Uri.ToString());
string source = String.Concat(path, filename);
string destination = String.Concat(newPath, filename);
RenameFile(source, destination);
}
if (blob is CloudBlobDirectory)
{
if (blob is CloudBlobDirectory) {
string foldername = blob.Uri.Segments.Last();
string source = String.Concat(path, foldername);
string destination = String.Concat(newPath, foldername);
@@ -174,29 +170,24 @@ namespace Orchard.Azure {
public void DeleteFile(string path) {
EnsurePathIsRelative(path);
path = String.Concat(_root, path);
using ( new HttpContextWeaver() )
{
using ( new HttpContextWeaver() ) {
Container.EnsureBlobExists(path);
var blob = Container.GetBlockBlobReference(path);
var blob = Container.GetBlockBlobReference(String.Concat(_root, path));
blob.Delete();
}
}
public void RenameFile(string path, string newPath) {
EnsurePathIsRelative(path);
path = String.Concat(_root, path);
EnsurePathIsRelative(newPath);
newPath = String.Concat(_root, newPath);
using ( new HttpContextWeaver() )
{
Container.EnsureBlobExists(path);
Container.EnsureBlobDoesNotExist(newPath);
var blob = Container.GetBlockBlobReference(path);
var newBlob = Container.GetBlockBlobReference(newPath);
using ( new HttpContextWeaver() ) {
Container.EnsureBlobExists(String.Concat(_root, path));
Container.EnsureBlobDoesNotExist(String.Concat(_root, newPath));
var blob = Container.GetBlockBlobReference(String.Concat(_root, path));
var newBlob = Container.GetBlockBlobReference(String.Concat(_root, newPath));
newBlob.CopyFromBlob(blob);
blob.Delete();
}
@@ -204,36 +195,36 @@ namespace Orchard.Azure {
public IStorageFile CreateFile(string path) {
EnsurePathIsRelative(path);
path = String.Concat(_root, path);
if ( Container.BlobExists(path) ) {
if ( Container.BlobExists(String.Concat(_root, path)) ) {
throw new ArgumentException("File " + path + " already exists");
}
var blob = Container.GetBlockBlobReference(path);
var blob = Container.GetBlockBlobReference(String.Concat(_root, path));
blob.OpenWrite().Dispose(); // force file creation
return new AzureBlobFileStorage(blob);
return new AzureBlobFileStorage(blob, _absoluteRoot);
}
public string GetPublicUrl(string path) {
EnsurePathIsRelative(path);
path = String.Concat(_root, path);
using ( new HttpContextWeaver() )
{
Container.EnsureBlobExists(path);
return Container.GetBlockBlobReference(path).Uri.ToString();
using ( new HttpContextWeaver() ) {
Container.EnsureBlobExists(String.Concat(_root, path));
return Container.GetBlockBlobReference(String.Concat(_root, path)).Uri.ToString();
}
}
private class AzureBlobFileStorage : IStorageFile {
private readonly CloudBlockBlob _blob;
private readonly string _rootPath;
public AzureBlobFileStorage(CloudBlockBlob blob) {
public AzureBlobFileStorage(CloudBlockBlob blob, string rootPath) {
_blob = blob;
_rootPath = rootPath;
}
public string GetPath() {
return _blob.Uri.ToString();
return _blob.Uri.ToString().Substring(_rootPath.Length+1);
}
public string GetName() {
@@ -264,17 +255,19 @@ namespace Orchard.Azure {
private class AzureBlobFolderStorage : IStorageFolder {
private readonly CloudBlobDirectory _blob;
private readonly string _rootPath;
public AzureBlobFolderStorage(CloudBlobDirectory blob) {
public AzureBlobFolderStorage(CloudBlobDirectory blob, string rootPath) {
_blob = blob;
_rootPath = rootPath;
}
public string GetName() {
return Path.GetDirectoryName(_blob.Uri.ToString());
return Path.GetDirectoryName(GetPath() + "/");
}
public string GetPath() {
return _blob.Uri.ToString();
return _blob.Uri.ToString().Substring(_rootPath.Length + 1).TrimEnd('/');
}
public long GetSize() {
@@ -287,7 +280,7 @@ namespace Orchard.Azure {
public IStorageFolder GetParent() {
if ( _blob.Parent != null ) {
return new AzureBlobFolderStorage(_blob.Parent);
return new AzureBlobFolderStorage(_blob.Parent, _rootPath);
}
throw new ArgumentException("Directory " + _blob.Uri + " does not have a parent directory");
}

View File

@@ -8,6 +8,11 @@ namespace Orchard.Azure.Web {
public override bool OnStart() {
DiagnosticMonitor.Start("DiagnosticsConnectionString");
CloudStorageAccount.SetConfigurationSettingPublisher(
(configName, configSetter) =>
configSetter(RoleEnvironment.GetConfigurationSettingValue(configName))
);
// For information on handling configuration changes
// see the MSDN topic at http://go.microsoft.com/fwlink/?LinkId=166357.
RoleEnvironment.Changing += RoleEnvironmentChanging;

View File

@@ -2,9 +2,6 @@
<configuration>
<system.web>
<httpHandlers>
<add path="*.aspx" verb="*" type="System.Web.HttpNotFoundHandler"/>
<add path="*.ascx" verb="*" type="System.Web.HttpNotFoundHandler"/>
<add path="*.master" verb="*" type="System.Web.HttpNotFoundHandler"/>
</httpHandlers>
<!--
@@ -28,8 +25,6 @@
<system.webServer>
<validation validateIntegratedModeConfiguration="false"/>
<handlers>
<remove name="BlockViewHandler"/>
<add name="BlockViewHandler" path="*.aspx,*.ascx,*.master" verb="*" preCondition="integratedMode" type="System.Web.HttpNotFoundHandler"/>
</handlers>
</system.webServer>
<runtime>

View File

@@ -0,0 +1,63 @@
using NUnit.Framework;
using Orchard.Media.Extensions;
namespace Orchard.Tests.Modules.Media.Extensions {
[TestFixture]
public class LongExtensionsTests {
[Test]
public void BytesAreFriendly() {
long size = 123;
string friendly = size.ToFriendlySizeString();
Assert.That(friendly, Is.EqualTo("123 B"));
}
[Test]
public void KilobytesAreFriendly() {
long size = 93845;
string friendly = size.ToFriendlySizeString();
Assert.That(friendly, Is.EqualTo("92 KB"));
}
[Test]
public void MegabytesAreFriendly() {
long size = 6593528;
string friendly = size.ToFriendlySizeString();
Assert.That(friendly, Is.EqualTo("6.3 MB"));
}
[Test]
public void GigabytesAreFriendly() {
long size = 46896534657;
string friendly = size.ToFriendlySizeString();
Assert.That(friendly, Is.EqualTo("43.68 GB"));
}
[Test]
public void TerabytesAreFriendly() {
long size = 386594723458690;
string friendly = size.ToFriendlySizeString();
Assert.That(friendly, Is.EqualTo("351.606 TB"));
}
[Test]
public void PetabytesAreSlightlyFriendlyAsTerabytes() {
long size = 56794738495678965;
string friendly = size.ToFriendlySizeString();
Assert.That(friendly, Is.EqualTo("51654.514 TB"));
}
[Test]
public void VeryLargeSizeDoesNotCauseFailure() {
long size = 5679473849567896593;
string friendly = size.ToFriendlySizeString();
Assert.That(friendly, Is.EqualTo("5165451.375 TB"));
}
[Test]
public void NegativeSizeDoesNotCauseFailure(){
long size = -2598;
string friendly = size.ToFriendlySizeString();
Assert.That(friendly, Is.EqualTo("-2598 B"));
}
}
}

View File

@@ -126,6 +126,7 @@
<ItemGroup>
<Compile Include="CodeGeneration\Commands\CodeGenerationCommandsTests.cs" />
<Compile Include="DatabaseEnabledTestsBase.cs" />
<Compile Include="Media\Extensions\LongExtensionsTests.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Roles\Controllers\AdminControllerTests.cs" />
<Compile Include="Roles\Services\RoleServiceTests.cs" />
@@ -155,6 +156,10 @@
<Project>{C0C45321-B51D-4D8D-9B7B-AA4C2E0B2962}</Project>
<Name>Orchard.CodeGeneration</Name>
</ProjectReference>
<ProjectReference Include="..\Orchard.Web\Modules\Orchard.Media\Orchard.Media.csproj">
<Project>{D9A7B330-CD22-4DA1-A95A-8DE1982AD8EB}</Project>
<Name>Orchard.Media</Name>
</ProjectReference>
<ProjectReference Include="..\Orchard.Web\Modules\Orchard.Modules\Orchard.Modules.csproj">
<Project>{17F86780-9A1F-4AA1-86F1-875EEC2730C7}</Project>
<Name>Orchard.Modules</Name>

View File

@@ -116,16 +116,17 @@ namespace Orchard.Tests.Modules.Users.Controllers {
[Test]
[Ignore("Needs to instead be a specflow test.")]
public void CreateShouldAddUserAndRedirect() {
_authorizer.Setup(x => x.Authorize(It.IsAny<Permission>(), It.IsAny<LocalizedString>())).Returns(true);
var controller = _container.Resolve<AdminController>();
var result = controller.CreatePOST(new UserCreateViewModel {
UserName = "four",
Email = "six@example.org",
Password = "five",
ConfirmPassword = "five"
});
ActionResult result = null; // controller.CreatePOST(new UserCreateViewModel {
// UserName = "four",
// Email = "six@example.org",
// Password = "five",
// ConfirmPassword = "five"
//});
Assert.That(result, Is.TypeOf<RedirectToRouteResult>());
var redirect = (RedirectToRouteResult)result;
@@ -136,7 +137,7 @@ namespace Orchard.Tests.Modules.Users.Controllers {
}
[Test]
[Ignore("Needs fixing")]
[Ignore("Needs fixing. Needs to instead be a specflow test.")]
public void EditShouldDisplayUserAndStoreChanges() {
_authorizer.Setup(x => x.Authorize(It.IsAny<Permission>(), It.IsAny<LocalizedString>())).Returns(true);
@@ -144,7 +145,7 @@ namespace Orchard.Tests.Modules.Users.Controllers {
var id = repository.Get(x => x.UserName == "two").Id;
var result = (ViewResult)_container.Resolve<AdminController>().Edit(id);
var model = (UserEditViewModel)result.ViewData.Model;
Assert.That(model.UserName, Is.EqualTo("two"));
//Assert.That(model.UserName, Is.EqualTo("two"));
var controller = _container.Resolve<AdminController>();
controller.ValueProvider = Values.From(new {

View File

@@ -248,6 +248,15 @@ namespace Orchard.Tests.ContentManagement {
}
[Test]
public void CountReturnsNumber() {
AddSampleData();
var count = _manager.Query()
.Count();
Assert.That(count, Is.EqualTo(4));
}
[Test]
public void QueryShouldJoinVersionedRecords() {

View File

@@ -26,6 +26,7 @@ namespace Orchard.Tests.DataMigration {
private string _tempFolder;
private SchemaBuilder _schemaBuilder;
private DefaultDataMigrationInterpreter _interpreter;
private ISession _session;
[SetUp]
public void Setup() {
@@ -38,7 +39,7 @@ namespace Orchard.Tests.DataMigration {
var builder = new ContainerBuilder();
var session = _sessionFactory.OpenSession();
_session = _sessionFactory.OpenSession();
builder.RegisterInstance(appDataFolder).As<IAppDataFolder>();
builder.RegisterType<SqlCeDataServicesProvider>().As<IDataServicesProvider>();
builder.RegisterType<DataServicesProviderFactory>().As<IDataServicesProviderFactory>();
@@ -46,7 +47,7 @@ namespace Orchard.Tests.DataMigration {
builder.RegisterType<DefaultDataMigrationInterpreter>().As<IDataMigrationInterpreter>();
builder.RegisterType<SessionConfigurationCache>().As<ISessionConfigurationCache>();
builder.RegisterType<SessionFactoryHolder>().As<ISessionFactoryHolder>();
builder.RegisterInstance(new DefaultContentManagerTests.TestSessionLocator(session)).As<ISessionLocator>();
builder.RegisterInstance(new DefaultContentManagerTests.TestSessionLocator(_session)).As<ISessionLocator>();
builder.RegisterInstance(new ShellBlueprint { Records = Enumerable.Empty<RecordBlueprint>() }).As<ShellBlueprint>();
builder.RegisterInstance(new ShellSettings { Name = "temp", DataProvider = "SqlCe", DataTablePrefix = "TEST" }).As<ShellSettings>();
builder.RegisterModule(new DataModule());
@@ -133,10 +134,24 @@ namespace Orchard.Tests.DataMigration {
.AlterTable("User", table => table
.AddColumn("Age", DbType.Int32))
.AlterTable("User", table => table
.AlterColumn("Lastname", column => column.WithDefault("John")))
.AlterColumn("Lastname", column => column.WithDefault("Doe")))
.AlterTable("User", table => table
.DropColumn("Firstname")
);
// creating a new row should assign a default value to Firstname and Age
_schemaBuilder
.ExecuteSql("insert into TEST_User VALUES (DEFAULT, DEFAULT)");
// ensure wehave one record woth the default value
var command = _session.Connection.CreateCommand();
command.CommandText = "SELECT count(*) FROM TEST_User WHERE Lastname = 'Doe'";
Assert.That(command.ExecuteScalar(), Is.EqualTo(1));
// ensure this is not a false positive
command = _session.Connection.CreateCommand();
command.CommandText = "SELECT count(*) FROM TEST_User WHERE Lastname = 'Foo'";
Assert.That(command.ExecuteScalar(), Is.EqualTo(0));
}
[Test]

View File

@@ -1,7 +1,7 @@
using System;
using System.Collections.Generic;
using NUnit.Framework;
using Orchard.UI.Navigation;
using Orchard.UI;
namespace Orchard.Tests.UI.Navigation {
[TestFixture]
@@ -10,7 +10,7 @@ namespace Orchard.Tests.UI.Navigation {
[SetUp]
public void Init() {
_comparer = new PositionComparer();
_comparer = new FlatPositionComparer();
}
@@ -47,6 +47,22 @@ namespace Orchard.Tests.UI.Navigation {
AssertSame("007", "7");
}
[Test]
public void NegativeNumericValuesAreLessThanPositive() {
AssertLess("-5", "5");
AssertSame("-5", "-5");
AssertMore("42", "-42");
}
[Test]
public void NegativeNumericValuesShouldCompareNumerically() {
AssertMore("-3", "-5");
AssertLess("-8", "-5");
AssertSame("-5", "-5");
AssertLess("-100", "-5");
AssertSame("-007", "-7");
}
[Test]
public void DotsSplitParts() {
AssertLess("0500.3", "0500.5");

View File

@@ -2,8 +2,6 @@
<configuration>
<system.web>
<httpHandlers>
<add path="*" verb="*"
type="System.Web.HttpNotFoundHandler"/>
</httpHandlers>
<!--
@@ -27,8 +25,6 @@
<system.webServer>
<validation validateIntegratedModeConfiguration="false"/>
<handlers>
<remove name="BlockViewHandler"/>
<add name="BlockViewHandler" path="*" verb="*" preCondition="integratedMode" type="System.Web.HttpNotFoundHandler"/>
</handlers>
</system.webServer>
<runtime>

View File

@@ -21,14 +21,18 @@ namespace Orchard.Core.Contents {
public void GetNavigation(NavigationBuilder builder) {
var contentTypeDefinitions = _contentDefinitionManager.ListTypeDefinitions().OrderBy(d => d.Name);
builder.Add(T("Content"), "2", menu => {
menu.Add(T("Manage Content"), "1", item => item.Action("List", "Admin", new { area = "Contents", id = "" }));
foreach (var contentTypeDefinition in contentTypeDefinitions.Where(ctd => ctd.Settings.GetModel<ContentTypeSettings>().Creatable)) {
builder.Add(T("Content"), "2",
menu => menu.Add(T("Content Items"), "1", item => item.Action("List", "Admin", new {area = "Contents", id = ""})));
builder.Add(T("New"), "-1", menu => {
menu.Add(T("Content Item"), "1", item => item.Action("List", "Admin", new { area = "Contents", id = "" }));
foreach (var contentTypeDefinition in contentTypeDefinitions.Where(ctd => ctd.Settings.GetModel<ContentTypeSettings>().Creatable).OrderBy(ctd => ctd.DisplayName)) {
var ci = _contentManager.New(contentTypeDefinition.Name);
var cim = _contentManager.GetItemMetadata(ci);
var createRouteValues = cim.CreateRouteValues;
// review: the display name should be a LocalizedString
if (createRouteValues.Any())
menu.Add(T("Create {0}", contentTypeDefinition.DisplayName), "1.3", item => item.Action(cim.CreateRouteValues["Action"] as string, cim.CreateRouteValues["Controller"] as string, cim.CreateRouteValues));
menu.Add(T(contentTypeDefinition.DisplayName), "5", item => item.Action(cim.CreateRouteValues["Action"] as string, cim.CreateRouteValues["Controller"] as string, cim.CreateRouteValues));
}
});
}

View File

@@ -8,6 +8,7 @@ using Orchard.ContentManagement;
using Orchard.ContentManagement.Aspects;
using Orchard.ContentManagement.MetaData;
using Orchard.ContentManagement.MetaData.Models;
using Orchard.ContentManagement.Records;
using Orchard.Core.Common.Models;
using Orchard.Core.Contents.Settings;
using Orchard.Core.Contents.ViewModels;
@@ -67,30 +68,29 @@ namespace Orchard.Core.Contents.Controllers {
switch (model.Options.OrderBy) {
case ContentsOrder.Modified:
//query = query.OrderByDescending<ContentPartRecord, int>(ci => ci.ContentItemRecord.Versions.Single(civr => civr.Latest).Id);
query = query.OrderByDescending<CommonPartRecord, DateTime?>(cr => cr.ModifiedUtc);
break;
case ContentsOrder.Published:
query = query.OrderByDescending<CommonPartRecord, DateTime?>(cr => cr.PublishedUtc);
break;
case ContentsOrder.Created:
//query = query.OrderByDescending<ContentPartRecord, int>(ci => ci.Id);
query = query.OrderByDescending<CommonPartRecord, DateTime?>(cr => cr.CreatedUtc);
break;
}
var pageOfContentItems = query.Slice(pager.GetStartIndex(), pager.PageSize).ToList();
model.Options.SelectedFilter = model.TypeName;
model.Options.FilterOptions = GetCreatableTypes()
.Select(ctd => new KeyValuePair<string, string>(ctd.Name, ctd.DisplayName))
.ToList().OrderBy(kvp => kvp.Key);
var pagerShape = Shape.Pager(pager).TotalItemCount(query.Count());
var pageOfContentItems = query.Slice(pager.GetStartIndex(), pager.PageSize).ToList();
var list = Shape.List();
list.AddRange(pageOfContentItems.Select(ci => _contentManager.BuildDisplay(ci, "SummaryAdmin")));
var hasNextPage = query.Slice(pager.GetStartIndex(pager.Page + 1), 1).Any();
var pagerShape = Shape.Pager(pager).HasNextPage(hasNextPage);
var viewModel = Shape.ViewModel()
.ContentItems(list)
.Pager(pagerShape)
@@ -192,24 +192,39 @@ namespace Orchard.Core.Contents.Controllers {
return View(model);
}
[HttpPost, ActionName("Create")]
[FormValueRequired("submit.Save")]
public ActionResult CreatePOST(string id) {
return CreatePOST(id, contentItem => {
if (!contentItem.Has<IPublishingControlAspect>() && !contentItem.TypeDefinition.Settings.GetModel<ContentTypeSettings>().Draftable)
_contentManager.Publish(contentItem);
});
}
[HttpPost, ActionName("Create")]
public ActionResult CreatePOST(string id) {
[FormValueRequired("submit.Publish")]
public ActionResult CreateAndPublishPOST(string id) {
return CreatePOST(id, contentItem => _contentManager.Publish(contentItem));
}
private ActionResult CreatePOST(string id, Action<ContentItem> conditionallyPublish) {
var contentItem = _contentManager.New(id);
if (!Services.Authorizer.Authorize(Permissions.PublishContent, contentItem, T("Couldn't create content")))
return new HttpUnauthorizedResult();
_contentManager.Create(contentItem, VersionOptions.Draft);
var model = _contentManager.UpdateEditor(contentItem, this);
var isDraftable = contentItem.TypeDefinition.Settings.GetModel<ContentTypeSettings>().Draftable;
_contentManager.Create(
contentItem,
isDraftable ? VersionOptions.Draft : VersionOptions.Published);
var model = _contentManager.UpdateEditor(contentItem, this);
if (!ModelState.IsValid) {
_transactionManager.Cancel();
return View(model);
}
if (!contentItem.Has<IPublishingControlAspect>())
_contentManager.Publish(contentItem);
conditionallyPublish(contentItem);
Services.Notifier.Information(string.IsNullOrWhiteSpace(contentItem.TypeDefinition.DisplayName)
? T("Your content has been created.")
@@ -232,7 +247,21 @@ namespace Orchard.Core.Contents.Controllers {
}
[HttpPost, ActionName("Edit")]
[FormValueRequired("submit.Save")]
public ActionResult EditPOST(int id, string returnUrl) {
return EditPOST(id, returnUrl, contentItem => {
if (!contentItem.Has<IPublishingControlAspect>() && !contentItem.TypeDefinition.Settings.GetModel<ContentTypeSettings>().Draftable)
_contentManager.Publish(contentItem);
});
}
[HttpPost, ActionName("Edit")]
[FormValueRequired("submit.Publish")]
public ActionResult EditAndPublishPOST(int id, string returnUrl) {
return EditPOST(id, returnUrl, contentItem => _contentManager.Publish(contentItem));
}
private ActionResult EditPOST(int id, string returnUrl, Action<ContentItem> conditionallyPublish) {
var contentItem = _contentManager.Get(id, VersionOptions.DraftRequired);
if (contentItem == null)
@@ -247,9 +276,7 @@ namespace Orchard.Core.Contents.Controllers {
return View("Edit", model);
}
//need to go about this differently - to know when to publish (IPlublishableAspect ?)
if (!contentItem.Has<IPublishingControlAspect>())
_contentManager.Publish(contentItem);
conditionallyPublish(contentItem);
Services.Notifier.Information(string.IsNullOrWhiteSpace(contentItem.TypeDefinition.DisplayName)
? T("Your content has been saved.")

View File

@@ -1,5 +1,7 @@
using Orchard.ContentManagement;
using System.Collections.Generic;
using Orchard.ContentManagement;
using Orchard.ContentManagement.Drivers;
using Orchard.Core.Contents.Settings;
namespace Orchard.Core.Contents.Drivers {
public class ContentsDriver : ContentPartDriver<ContentPart> {
@@ -13,5 +15,18 @@ namespace Orchard.Core.Contents.Drivers {
() => shapeHelper.Parts_Contents_Publish_SummaryAdmin(ContentPart: part))
);
}
protected override DriverResult Editor(ContentPart part, dynamic shapeHelper) {
var results = new List<DriverResult> { ContentShape("Content_SaveButton", saveButton => saveButton) };
if (part.TypeDefinition.Settings.GetModel<ContentTypeSettings>().Draftable)
results.Add(ContentShape("Content_PublishButton", publishButton => publishButton));
return Combined(results.ToArray());
}
protected override DriverResult Editor(ContentPart part, IUpdateModel updater, dynamic shapeHelper) {
return Editor(part, updater);
}
}
}

View File

@@ -6,6 +6,9 @@ namespace Orchard.Core.Contents.Extensions {
public static ContentTypeDefinitionBuilder Creatable(this ContentTypeDefinitionBuilder builder, bool creatable = true) {
return builder.WithSetting("ContentTypeSettings.Creatable", creatable.ToString());
}
public static ContentTypeDefinitionBuilder Draftable(this ContentTypeDefinitionBuilder builder, bool draftable = true) {
return builder.WithSetting("ContentTypeSettings.Draftable", draftable.ToString());
}
public static ContentPartDefinitionBuilder Attachable(this ContentPartDefinitionBuilder builder, bool attachable = true) {
return builder.WithSetting("ContentPartSettings.Attachable", attachable.ToString());
}

View File

@@ -4,6 +4,9 @@
Parts_Contents_Publish
Parts_Contents_Publish_SummaryAdmin
-->
<!-- edit "shape" -->
<Place Content_PublishButton="Sidebar:20"/>
<Place Content_SaveButton="Sidebar:22"/>
<Match DisplayType="Detail">
<Place Parts_Contents_Publish="Content:5"/>
</Match>

View File

@@ -1,8 +1,12 @@
namespace Orchard.Core.Contents.Settings {
public class ContentTypeSettings {
/// <summary>
/// This setting is used to display a Content Type in Content Management menu like
/// Used to determine if an instance of this content type can be created through the UI
/// </summary>
public bool Creatable { get; set; }
/// <summary>
/// Used to determine if this content type supports draft versions
/// </summary>
public bool Draftable { get; set; }
}
}

View File

@@ -0,0 +1,3 @@
<fieldset class="publish-button">
<button type="submit" name="submit.Publish" value="submit.Publish">@T("Publish Now")</button>
</fieldset>

View File

@@ -0,0 +1,3 @@
<fieldset class="save-button">
<button class="primaryAction" type="submit" name="submit.Save" value="submit.Save">@T("Save")</button>
</fieldset>

View File

@@ -4,9 +4,5 @@
</div>
<div class="secondary">
@Display(Model.Sidebar)
@* todo: (heskew) remove when the CommonPart is adding the save button *@
<fieldset>
<button class="primaryAction" type="submit" name="submit.Save" value="submit.Save">@T("Save")</button>
</fieldset>
</div>
</div>

View File

@@ -2,8 +2,6 @@
<configuration>
<system.web>
<httpHandlers>
<add path="*" verb="*"
type="System.Web.HttpNotFoundHandler"/>
</httpHandlers>
<!--
@@ -27,8 +25,6 @@
<system.webServer>
<validation validateIntegratedModeConfiguration="false"/>
<handlers>
<remove name="BlockViewHandler"/>
<add name="BlockViewHandler" path="*" verb="*" preCondition="integratedMode" type="System.Web.HttpNotFoundHandler"/>
</handlers>
</system.webServer>
<runtime>

View File

@@ -8,8 +8,9 @@ namespace Orchard.Core.Dashboard {
public string MenuName { get { return "admin"; } }
public void GetNavigation(NavigationBuilder builder) {
builder.Add(T("Orchard"), "0",
menu => menu.Add(T("Dashboard"), "0", item => item.Action("Index", "Admin", new { area = "Dashboard" }).Permission(StandardPermissions.AccessAdminPanel)));
builder.Add(T("Dashboard"), "0",
menu => menu.Add(T("Orchard"), "0", item => item.Action("Index", "Admin", new { area = "Dashboard" })
.Permission(StandardPermissions.AccessAdminPanel)));
}
}
}

View File

@@ -2,8 +2,6 @@
<configuration>
<system.web>
<httpHandlers>
<add path="*" verb="*"
type="System.Web.HttpNotFoundHandler"/>
</httpHandlers>
<!--
@@ -27,8 +25,6 @@
<system.webServer>
<validation validateIntegratedModeConfiguration="false"/>
<handlers>
<remove name="BlockViewHandler"/>
<add name="BlockViewHandler" path="*" verb="*" preCondition="integratedMode" type="System.Web.HttpNotFoundHandler"/>
</handlers>
</system.webServer>
<runtime>

View File

@@ -6,7 +6,7 @@
Parts_Localization_ContentTranslations_SummaryAdmin
-->
<!-- edit shape just gets default placement -->
<Place Parts_Localization_ContentTranslations_Edit="Content:before.1"/>
<Place Parts_Localization_ContentTranslations_Edit="Content:0"/>
<Match DisplayType="Detail">
<Place Parts_Localization_ContentTranslations="Content:2"/>
</Match>

View File

@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<system.web>
<httpHandlers>
<!-- iis6 - for any request in this location, return via managed static file handler -->
<add path="*" verb="*" type="System.Web.StaticFileHandler" />
</httpHandlers>
</system.web>
<system.webServer>
<handlers accessPolicy="Script,Read">
<!--
iis7 - for any request to a file exists on disk, return it via native http module.
accessPolicy 'Script' is to allow for a managed 404 page.
-->
<add name="StaticFile" path="*" verb="*" modules="StaticFileModule" preCondition="integratedMode" resourceType="File" requireAccess="Read" />
</handlers>
</system.webServer>
</configuration>

View File

@@ -1,10 +1,6 @@
.summary .content-localization {
margin: .7em 0;
}
.content-localization .content-localizations li,
.content-localization .add-localization {
font-size:1.4em;
}
.content-localization .culture-selected {
margin-bottom:.5em;
}

View File

@@ -2,8 +2,6 @@
<configuration>
<system.web>
<httpHandlers>
<add path="*" verb="*"
type="System.Web.HttpNotFoundHandler"/>
</httpHandlers>
<!--
@@ -27,8 +25,6 @@
<system.webServer>
<validation validateIntegratedModeConfiguration="false"/>
<handlers>
<remove name="BlockViewHandler"/>
<add name="BlockViewHandler" path="*" verb="*" preCondition="integratedMode" type="System.Web.HttpNotFoundHandler"/>
</handlers>
</system.webServer>
<runtime>

View File

@@ -2,8 +2,6 @@
<configuration>
<system.web>
<httpHandlers>
<add path="*" verb="*"
type="System.Web.HttpNotFoundHandler"/>
</httpHandlers>
<!--
@@ -27,8 +25,6 @@
<system.webServer>
<validation validateIntegratedModeConfiguration="false"/>
<handlers>
<remove name="BlockViewHandler"/>
<add name="BlockViewHandler" path="*" verb="*" preCondition="integratedMode" type="System.Web.HttpNotFoundHandler"/>
</handlers>
</system.webServer>
</configuration>

View File

@@ -9,8 +9,8 @@ namespace Orchard.Core.Navigation {
public void GetNavigation(NavigationBuilder builder) {
//todo: - add new menu? and list menus? ...and remove hard-coded menu name here
builder.Add(T("Navigation"), "8",
menu => menu
.Add(T("Main Menu"), "6.0", item => item.Action("Index", "Admin", new { area = "Navigation" }).Permission(Permissions.ManageMainMenu)));
menu => menu.Add(T("Main Menu"), "0", item => item.Action("Index", "Admin", new { area = "Navigation" })
.Permission(Permissions.ManageMainMenu)));
}
}
}

View File

@@ -8,6 +8,7 @@ using Orchard.Core.Navigation.ViewModels;
using Orchard.DisplayManagement;
using Orchard.Localization;
using Orchard.Mvc.AntiForgery;
using Orchard.UI;
using Orchard.UI.Navigation;
using Orchard.Utility;
@@ -41,7 +42,7 @@ namespace Orchard.Core.Navigation.Controllers {
model = new NavigationManagementViewModel();
if (model.MenuItemEntries == null || model.MenuItemEntries.Count() < 1)
model.MenuItemEntries = _menuService.Get().Select(CreateMenuItemEntries).OrderBy(menuPartEntry => menuPartEntry.MenuItem.Position, new PositionComparer()).ToList();
model.MenuItemEntries = _menuService.Get().Select(CreateMenuItemEntries).OrderBy(menuPartEntry => menuPartEntry.MenuItem.Position, new FlatPositionComparer()).ToList();
// need action name as this action is referenced from another action
return View("Index", model);

View File

@@ -35,7 +35,7 @@
}
</tbody>
</table>
<fieldset class="actions"><button type="submit" class="button primaryAction">@T("Update All")</button></fieldset>
<fieldset class="actions"><button type="submit" class="primaryAction">@T("Update All")</button></fieldset>
}
<h2>@T("Add New Item")</h2>

View File

@@ -2,8 +2,6 @@
<configuration>
<system.web>
<httpHandlers>
<add path="*" verb="*"
type="System.Web.HttpNotFoundHandler"/>
</httpHandlers>
<!--
@@ -27,8 +25,6 @@
<system.webServer>
<validation validateIntegratedModeConfiguration="false"/>
<handlers>
<remove name="BlockViewHandler"/>
<add name="BlockViewHandler" path="*" verb="*" preCondition="integratedMode" type="System.Web.HttpNotFoundHandler"/>
</handlers>
</system.webServer>
<runtime>

View File

@@ -274,12 +274,8 @@
<Content Include="Settings\Views\Admin\Index.cshtml" />
<Content Include="Settings\Views\Admin\Culture.cshtml" />
<Content Include="Contents\Views\Items\Content.Edit.cshtml" />
<Content Include="Routable\Placement.info">
<SubType>Designer</SubType>
</Content>
<Content Include="Settings\Placement.info">
<SubType>Designer</SubType>
</Content>
<Content Include="Routable\Placement.info" />
<Content Include="Settings\Placement.info" />
<Content Include="Settings\Views\DisplayTemplates\CurrentCulture.cshtml" />
<Content Include="Settings\Views\DisplayTemplates\RemovableCulture.cshtml" />
<Content Include="Shapes\Module.txt" />
@@ -298,8 +294,6 @@
<Content Include="Shapes\Views\HeadPreload.cshtml" />
<Content Include="Shapes\Views\Message.cshtml" />
<Content Include="Shapes\Views\NotFound.cshtml" />
<Content Include="Shapes\Views\UI\Switchable.cshtml" />
<Content Include="Web.config" />
<Content Include="XmlRpc\Module.txt" />
<Content Include="Settings\Views\EditorTemplates\Parts\Settings.SiteSettingsPart.cshtml" />
</ItemGroup>
@@ -359,18 +353,31 @@
<Content Include="Contents\Views\Content.ControlWrapper.cshtml" />
<Content Include="Contents\Views\Item\Display.cshtml" />
<Content Include="Localization\Placement.info" />
<Content Include="Messaging\Placement.info">
<SubType>Designer</SubType>
</Content>
<Content Include="Navigation\Placement.info">
<SubType>Designer</SubType>
</Content>
<Content Include="Messaging\Placement.info" />
<Content Include="Navigation\Placement.info" />
<Content Include="Routable\Views\Parts\RoutableTitle.cshtml" />
<Content Include="Routable\Views\Item\Display.cshtml" />
<Content Include="Routable\Views\Routable.HomePage.cshtml" />
<Content Include="Localization\Views\Parts\Localization.ContentTranslations.SummaryAdmin.cshtml" />
<Content Include="Contents\Views\Items\Content.Summary.cshtml" />
<Content Include="Shapes\Views\Pager.cshtml" />
<Content Include="Contents\Views\Content.SaveButton.cshtml" />
<Content Include="Contents\Views\Content.PublishButton.cshtml" />
<Content Include="Shapes\Scripts\Web.config">
<SubType>Designer</SubType>
</Content>
<Content Include="Shapes\Styles\Web.config">
<SubType>Designer</SubType>
</Content>
<Content Include="Routable\Scripts\Web.config">
<SubType>Designer</SubType>
</Content>
<Content Include="Localization\Styles\Web.config">
<SubType>Designer</SubType>
</Content>
<Content Include="Settings\Styles\Web.config">
<SubType>Designer</SubType>
</Content>
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v10.0\WebApplications\Microsoft.WebApplication.targets" />

View File

@@ -1,5 +1,6 @@
using System.Reflection;
using System.Runtime.InteropServices;
using System.Security;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
@@ -32,3 +33,4 @@ using System.Runtime.InteropServices;
// by using the '*' as shown below:
[assembly: AssemblyVersion("0.8.0")]
[assembly: AssemblyFileVersion("0.8.0")]
[assembly: SecurityTransparent]

View File

@@ -8,8 +8,9 @@ namespace Orchard.Core.Reports {
public string MenuName { get { return "admin"; } }
public void GetNavigation(NavigationBuilder builder) {
builder.Add(T("Site Configuration"), "11",
menu => menu.Add(T("Reports"), "15", item => item.Action("Index", "Admin", new { area = "Reports" }).Permission(StandardPermissions.AccessAdminPanel)));
builder.Add(T("Configuration"), "50",
menu => menu.Add(T("Reports"), "20", item => item.Action("Index", "Admin", new { area = "Reports" })
.Permission(StandardPermissions.AccessAdminPanel)));
}
}
}

View File

@@ -2,8 +2,6 @@
<configuration>
<system.web>
<httpHandlers>
<add path="*" verb="*"
type="System.Web.HttpNotFoundHandler"/>
</httpHandlers>
<!--
@@ -27,8 +25,6 @@
<system.webServer>
<validation validateIntegratedModeConfiguration="false"/>
<handlers>
<remove name="BlockViewHandler"/>
<add name="BlockViewHandler" path="*" verb="*" preCondition="integratedMode" type="System.Web.HttpNotFoundHandler"/>
</handlers>
</system.webServer>
<runtime>

View File

@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<system.web>
<httpHandlers>
<!-- iis6 - for any request in this location, return via managed static file handler -->
<add path="*" verb="*" type="System.Web.StaticFileHandler" />
</httpHandlers>
</system.web>
<system.webServer>
<handlers accessPolicy="Script,Read">
<!--
iis7 - for any request to a file exists on disk, return it via native http module.
accessPolicy 'Script' is to allow for a managed 404 page.
-->
<add name="StaticFile" path="*" verb="*" modules="StaticFileModule" preCondition="integratedMode" resourceType="File" requireAccess="Read" />
</handlers>
</system.webServer>
</configuration>

View File

@@ -2,8 +2,6 @@
<configuration>
<system.web>
<httpHandlers>
<add path="*" verb="*"
type="System.Web.HttpNotFoundHandler"/>
</httpHandlers>
<!--
@@ -27,8 +25,6 @@
<system.webServer>
<validation validateIntegratedModeConfiguration="false"/>
<handlers>
<remove name="BlockViewHandler"/>
<add name="BlockViewHandler" path="*" verb="*" preCondition="integratedMode" type="System.Web.HttpNotFoundHandler"/>
</handlers>
</system.webServer>
<runtime>

View File

@@ -7,9 +7,9 @@ namespace Orchard.Core.Settings {
public string MenuName { get { return "admin"; } }
public void GetNavigation(NavigationBuilder builder) {
builder.Add(T("Site Configuration"), "11",
menu => menu
.Add(T("Settings"), "10", item => item.Action("Index", "Admin", new { area = "Settings" }).Permission(Permissions.ManageSettings)));
builder.Add(T("Configuration"), "50",
menu => menu.Add(T("Settings"), "10", item => item.Action("Index", "Admin", new { area = "Settings" })
.Permission(Permissions.ManageSettings)));
}
}
}

View File

@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<system.web>
<httpHandlers>
<!-- iis6 - for any request in this location, return via managed static file handler -->
<add path="*" verb="*" type="System.Web.StaticFileHandler" />
</httpHandlers>
</system.web>
<system.webServer>
<handlers accessPolicy="Script,Read">
<!--
iis7 - for any request to a file exists on disk, return it via native http module.
accessPolicy 'Script' is to allow for a managed 404 page.
-->
<add name="StaticFile" path="*" verb="*" modules="StaticFileModule" preCondition="integratedMode" resourceType="File" requireAccess="Read" />
</handlers>
</system.webServer>
</configuration>

View File

@@ -3,7 +3,6 @@
@Html.ValidationSummary()
@Display(Model.Content)
<fieldset>
<input class="button primaryAction" type="submit" value="@T("Save")" />
<button class="primaryAction" type="submit">@T("Save")</button>
</fieldset>
}
}

View File

@@ -2,8 +2,6 @@
<configuration>
<system.web>
<httpHandlers>
<add path="*" verb="*"
type="System.Web.HttpNotFoundHandler"/>
</httpHandlers>
<!--
@@ -27,8 +25,6 @@
<system.webServer>
<validation validateIntegratedModeConfiguration="false"/>
<handlers>
<remove name="BlockViewHandler"/>
<add name="BlockViewHandler" path="*" verb="*" preCondition="integratedMode" type="System.Web.HttpNotFoundHandler"/>
</handlers>
</system.webServer>
<runtime>

View File

@@ -1,7 +1,3 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Orchard.UI.Resources;
namespace Orchard.Core.Shapes {
@@ -11,6 +7,11 @@ namespace Orchard.Core.Shapes {
manifest.DefineScript("ShapesBase").SetUrl("base.js").SetDependencies("jQuery");
manifest.DefineStyle("Shapes").SetUrl("site.css"); // todo: missing
manifest.DefineStyle("ShapesSpecial").SetUrl("special.css");
manifest.DefineScript("Switchable").SetUrl("jquery.switchable.js")
.SetDependencies("jQuery")
.SetDependencies("ShapesBase");
manifest.DefineStyle("Switchable").SetUrl("jquery.switchable.css");
}
}
}

View File

@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<system.web>
<httpHandlers>
<!-- iis6 - for any request in this location, return via managed static file handler -->
<add path="*" verb="*" type="System.Web.StaticFileHandler" />
</httpHandlers>
</system.web>
<system.webServer>
<handlers accessPolicy="Script,Read">
<!--
iis7 - for any request to a file exists on disk, return it via native http module.
accessPolicy 'Script' is to allow for a managed 404 page.
-->
<add name="StaticFile" path="*" verb="*" modules="StaticFileModule" preCondition="integratedMode" resourceType="File" requireAccess="Read" />
</handlers>
</system.webServer>
</configuration>

View File

@@ -103,14 +103,14 @@
_controllees.hide(); // <- unhook this when the following comment applies
$(_controllees.show()[0]).find("input").focus(); // <- aaaand a slideDown there...eventually
} else if (!(_this.is(":checked") && _controlleesAreHidden)) {
//_controllees.slideUp(200); <- hook this back up when chrome behaves, or when I care less
//_controllees.slideUp(200); <- hook this back up when chrome behaves, or when I care less...or when chrome behaves
_controllees.hide()
}
return this;
}
});
// collapsable areas - anything with a data-controllerid attribute has its visibility controlled by the id-ed radio/checkbox
(function () {
$(function () {
$("[data-controllerid]").each(function () {
var controller = $("#" + $(this).attr("data-controllerid"));
if (controller.data("isControlling")) {
@@ -126,11 +126,12 @@
$("[name=" + controller.attr("name") + "]").click(function () { $("[name=" + $(this).attr("name") + "]").each($(this).toggleWhatYouControl); });
}
});
})();
});
// inline form link buttons (form.inline.link button) swapped out for a link that submits said form
(function () {
$(function () {
$("form.inline.link").each(function () {
var _this = $(this);
console.log(_this.html())
var link = $("<a class='wasFormInlineLink' href='.'/>");
var button = _this.children("button").first();
link.text(button.text())
@@ -141,7 +142,7 @@
_this.css({ "position": "absolute", "left": "-9999em" });
$("body").append(_this);
});
})();
});
// (do) a little better autofocus
$(function () {
$("body").helpfullyFocus();

View File

@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<system.web>
<httpHandlers>
<!-- iis6 - for any request in this location, return via managed static file handler -->
<add path="*" verb="*" type="System.Web.StaticFileHandler" />
</httpHandlers>
</system.web>
<system.webServer>
<handlers accessPolicy="Script,Read">
<!--
iis7 - for any request to a file exists on disk, return it via native http module.
accessPolicy 'Script' is to allow for a managed 404 page.
-->
<add name="StaticFile" path="*" verb="*" modules="StaticFileModule" preCondition="integratedMode" resourceType="File" requireAccess="Read" />
</handlers>
</system.webServer>
</configuration>

View File

@@ -6,7 +6,7 @@
var queryString = ViewContext.HttpContext.Request.QueryString;
if (queryString != null) {
foreach (string key in queryString.Keys) {
if (!routeData.ContainsKey(key)) {
if (key != null && !routeData.ContainsKey(key)) {
var value = queryString[key];
routeData[key] = queryString[key];
}
@@ -17,21 +17,23 @@
routeData.Remove("id");
}
var hasNextPage = (Model.Page * Model.PageSize) < Model.TotalItemCount;
Model.Classes.Add("pager");
Model.Classes.Add("group");
var tag = Tag(Model, "ul");
}
@if (Model.HasNextPage || Model.Page > 1) {
@if (hasNextPage || Model.Page > 1) {
@tag.StartElement
if(Model.HasNextPage) {
if(hasNextPage) {
routeData["page"] = Model.Page + 1;
<li class="older">
<li class="page-next">
@Html.ActionLink((string)nextText, (string)routeData["action"], (string)routeData["controller"], routeData, null)
</li>
}
if(Model.Page > 1) {
routeData["page"] = Model.Page - 1;
<li class="newer">
<li class="page-previous">
@Html.ActionLink((string)previousText, (string)routeData["action"], (string)routeData["controller"], routeData, null)
</li>
}

View File

@@ -1,5 +0,0 @@
@{
Style.Require("Switchable");
Script.Require("Switchable");
}
@string.Format("{0} switchable", Model)

View File

@@ -2,8 +2,6 @@
<configuration>
<system.web>
<httpHandlers>
<add path="*" verb="*"
type="System.Web.HttpNotFoundHandler"/>
</httpHandlers>
<!--
@@ -27,8 +25,6 @@
<system.webServer>
<validation validateIntegratedModeConfiguration="false"/>
<handlers>
<remove name="BlockViewHandler"/>
<add name="BlockViewHandler" path="*" verb="*" preCondition="integratedMode" type="System.Web.HttpNotFoundHandler"/>
</handlers>
</system.webServer>
<runtime>

View File

@@ -1,31 +0,0 @@
<?xml version="1.0"?>
<configuration>
<system.web>
<compilation debug="true" targetFramework="4.0">
<assemblies>
<add assembly="System.Web.Mvc, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL"/>
</assemblies>
</compilation>
<pages controlRenderingCompatibilityVersion="3.5" clientIDMode="AutoID">
<namespaces>
<add namespace="System.Web.Mvc"/>
<add namespace="System.Web.Mvc.Ajax"/>
<add namespace="System.Web.Mvc.Html"/>
<add namespace="System.Web.Routing"/>
<add namespace="System.Linq"/>
<add namespace="System.Collections.Generic"/>
<add namespace="Orchard.Mvc.Html"/>
</namespaces>
</pages>
</system.web>
<system.web.extensions/>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35" />
<bindingRedirect oldVersion="2.0.0.0" newVersion="3.0.0.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>

View File

@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<system.web>
<httpHandlers>
<!-- iis6 - for any request in this location, return via managed static file handler -->
<add path="*" verb="*" type="System.Web.StaticFileHandler" />
</httpHandlers>
</system.web>
<system.webServer>
<handlers accessPolicy="Script,Read">
<!--
iis7 - for any request to a file exists on disk, return it via native http module.
accessPolicy 'Script' is to allow for a managed 404 page.
-->
<add name="StaticFile" path="*" verb="*" modules="StaticFileModule" preCondition="integratedMode" resourceType="File" requireAccess="Read" />
</handlers>
</system.webServer>
</configuration>

View File

@@ -80,9 +80,6 @@
<ItemGroup>
<Content Include="Module.txt" />
</ItemGroup>
<ItemGroup>
<Content Include="Web.config" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\Orchard\Orchard.Framework.csproj">
<Project>{2D1D92BB-4555-4CBE-8D0E-63563D6CE4C6}</Project>

View File

@@ -1,6 +1,6 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Security;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
@@ -33,3 +33,4 @@ using System.Runtime.InteropServices;
// by using the '*' as shown below:
[assembly: AssemblyVersion("0.8.0")]
[assembly: AssemblyFileVersion("0.8.0")]
[assembly: SecurityTransparent]

View File

@@ -1,32 +0,0 @@
<?xml version="1.0"?>
<configuration>
<system.web>
<compilation debug="true" targetFramework="4.0">
<assemblies>
<add assembly="System.Web.Mvc, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35, processorArchitecture=MSIL"/>
</assemblies>
</compilation>
<pages controlRenderingCompatibilityVersion="3.5" clientIDMode="AutoID">
<namespaces>
<add namespace="System.Web.Mvc"/>
<add namespace="System.Web.Mvc.Ajax"/>
<add namespace="System.Web.Mvc.Html"/>
<add namespace="System.Web.Routing"/>
<add namespace="System.Linq"/>
<add namespace="System.Collections.Generic"/>
<add namespace="Orchard.Mvc.Html"/>
</namespaces>
</pages>
</system.web>
<system.web.extensions/>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35" />
<bindingRedirect oldVersion="2.0.0.0" newVersion="3.0.0.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>

View File

@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<system.web>
<httpHandlers>
<!-- iis6 - for any request in this location, return via managed static file handler -->
<add path="*" verb="*" type="System.Web.StaticFileHandler" />
</httpHandlers>
</system.web>
<system.webServer>
<handlers accessPolicy="Script,Read">
<!--
iis7 - for any request to a file exists on disk, return it via native http module.
accessPolicy 'Script' is to allow for a managed 404 page.
-->
<add name="StaticFile" path="*" verb="*" modules="StaticFileModule" preCondition="integratedMode" resourceType="File" requireAccess="Read" />
</handlers>
</system.webServer>
</configuration>

View File

@@ -106,6 +106,16 @@
<SubType>Designer</SubType>
</Content>
</ItemGroup>
<ItemGroup>
<Content Include="Styles\Web.config">
<SubType>Designer</SubType>
</Content>
</ItemGroup>
<ItemGroup>
<Content Include="Content\Web.config">
<SubType>Designer</SubType>
</Content>
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v10.0\WebApplications\Microsoft.WebApplication.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.

View File

@@ -1,6 +1,6 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Security;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
@@ -32,3 +32,4 @@ using System.Runtime.InteropServices;
// by using the '*' as shown below:
[assembly: AssemblyVersion("0.8.0")]
[assembly: AssemblyFileVersion("0.8.0")]
[assembly: SecurityTransparent]

View File

@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<system.web>
<httpHandlers>
<!-- iis6 - for any request in this location, return via managed static file handler -->
<add path="*" verb="*" type="System.Web.StaticFileHandler" />
</httpHandlers>
</system.web>
<system.webServer>
<handlers accessPolicy="Script,Read">
<!--
iis7 - for any request to a file exists on disk, return it via native http module.
accessPolicy 'Script' is to allow for a managed 404 page.
-->
<add name="StaticFile" path="*" verb="*" modules="StaticFileModule" preCondition="integratedMode" resourceType="File" requireAccess="Read" />
</handlers>
</system.webServer>
</configuration>

View File

@@ -2,8 +2,6 @@
<configuration>
<system.web>
<httpHandlers>
<add path="*" verb="*"
type="System.Web.HttpNotFoundHandler"/>
</httpHandlers>
<!--
@@ -27,8 +25,6 @@
<system.webServer>
<validation validateIntegratedModeConfiguration="false"/>
<handlers>
<remove name="BlockViewHandler"/>
<add name="BlockViewHandler" path="*" verb="*" preCondition="integratedMode" type="System.Web.HttpNotFoundHandler"/>
</handlers>
</system.webServer>
<runtime>

View File

@@ -16,7 +16,7 @@ namespace Orchard.Blogs {
public string MenuName { get { return "admin"; } }
public void GetNavigation(NavigationBuilder builder) {
builder.Add(T("Blogs"), "1", BuildMenu);
builder.Add(T("Blogs"), "2.5", BuildMenu);
}
private void BuildMenu(NavigationItemBuilder menu) {
@@ -24,16 +24,15 @@ namespace Orchard.Blogs {
var blogCount = blogs.Count();
var singleBlog = blogCount == 1 ? blogs.ElementAt(0) : null;
if (blogCount > 0 && singleBlog == null)
menu.Add(T("Manage Blogs"), "1.0",
item =>
item.Action("List", "BlogAdmin", new {area = "Orchard.Blogs"}).Permission(Permissions.MetaListBlogs));
if (blogCount > 0 && singleBlog == null) {
menu.Add(T("List"), "3",
item => item.Action("List", "BlogAdmin", new {area = "Orchard.Blogs"}).Permission(Permissions.MetaListBlogs));
}
else if (singleBlog != null)
menu.Add(T("Manage Blog"), "1.0",
item =>
item.Action("Item", "BlogAdmin", new {area = "Orchard.Blogs", blogSlug = singleBlog.Slug}).Permission(Permissions.MetaListBlogs));
item => item.Action("Item", "BlogAdmin", new { area = "Orchard.Blogs", blogSlug = singleBlog.Slug }).Permission(Permissions.MetaListBlogs));
if ( singleBlog != null )
if (singleBlog != null)
menu.Add(T("Create New Post"), "1.1",
item =>
item.Action("Create", "BlogPostAdmin", new { area = "Orchard.Blogs", blogSlug = singleBlog.Slug }).Permission(Permissions.PublishBlogPost));

View File

@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<system.web>
<httpHandlers>
<!-- iis6 - for any request in this location, return via managed static file handler -->
<add path="*" verb="*" type="System.Web.StaticFileHandler" />
</httpHandlers>
</system.web>
<system.webServer>
<handlers accessPolicy="Script,Read">
<!--
iis7 - for any request to a file exists on disk, return it via native http module.
accessPolicy 'Script' is to allow for a managed 404 page.
-->
<add name="StaticFile" path="*" verb="*" modules="StaticFileModule" preCondition="integratedMode" resourceType="File" requireAccess="Read" />
</handlers>
</system.webServer>
</configuration>

View File

@@ -10,6 +10,7 @@ using Orchard.Data;
using Orchard.DisplayManagement;
using Orchard.Localization;
using Orchard.UI.Admin;
using Orchard.UI.Navigation;
using Orchard.UI.Notify;
namespace Orchard.Blogs.Controllers {
@@ -27,7 +28,8 @@ namespace Orchard.Blogs.Controllers {
IBlogPostService blogPostService,
IContentManager contentManager,
ITransactionManager transactionManager,
IBlogSlugConstraint blogSlugConstraint) {
IBlogSlugConstraint blogSlugConstraint,
IShapeFactory shapeFactory) {
Services = services;
_blogService = blogService;
_blogPostService = blogPostService;
@@ -35,8 +37,10 @@ namespace Orchard.Blogs.Controllers {
_transactionManager = transactionManager;
_blogSlugConstraint = blogSlugConstraint;
T = NullLocalizer.Instance;
Shape = shapeFactory;
}
dynamic Shape { get; set; }
public Localizer T { get; set; }
public IOrchardServices Services { get; set; }
@@ -135,20 +139,25 @@ namespace Orchard.Blogs.Controllers {
return View(viewModel);
}
public ActionResult Item(string blogSlug) {
public ActionResult Item(string blogSlug, Pager pager) {
BlogPart blogPart = _blogService.Get(blogSlug);
if (blogPart == null)
return HttpNotFound();
//() => {
// var list = shapeHelper.List();
// list.AddRange(_blogPostService.Get(part, VersionOptions.Latest)
// .Select(bp => _contentManager.BuildDisplay(bp, "SummaryAdmin")));
// return shapeHelper.Parts_Blogs_BlogPost_List_Admin(ContentPart: part, ContentItems: list);
//})
var model = Services.ContentManager.BuildDisplay(blogPart, "DetailAdmin");
return View(model);
var blogPosts = _blogPostService.Get(blogPart, pager.GetStartIndex(), pager.PageSize, VersionOptions.Latest)
.Select(bp => _contentManager.BuildDisplay(bp, "SummaryAdmin"));
var blog = Services.ContentManager.BuildDisplay(blogPart, "DetailAdmin");
var list = Shape.List();
list.AddRange(blogPosts);
blog.Content.Add(Shape.Parts_Blogs_BlogPost_ListAdmin(ContentItems: list), "5");
var totalItemCount = _blogPostService.PostCount(blogPart, VersionOptions.Latest);
blog.Content.Add(Shape.Pager(pager).TotalItemCount(totalItemCount), "Content:after");
return View(blog);
}
bool IUpdateModel.TryUpdateModel<TModel>(TModel model, string prefix, string[] includeProperties, string[] excludeProperties) {

View File

@@ -74,8 +74,8 @@ namespace Orchard.Blogs.Controllers {
list.AddRange(blogPosts);
blog.Content.Add(Shape.Parts_Blogs_BlogPost_List(ContentItems: list), "5");
var hasNextPage = _blogPostService.Get(blogPart, pager.GetStartIndex(pager.Page + 1), 1).Any();
blog.Content.Add(Shape.Pager(pager).HasNextPage(hasNextPage), "Content:after");
var totalItemCount = _blogPostService.PostCount(blogPart);
blog.Content.Add(Shape.Pager(pager).TotalItemCount(totalItemCount), "Content:after");
return View(blog);
}

View File

@@ -131,11 +131,10 @@
<Content Include="Views\Parts\Blogs.Blog.Manage.cshtml" />
<Content Include="Views\Parts\Blogs.Blog.Description.cshtml" />
<Content Include="Views\EditorTemplates\Parts\Blogs.Blog.Fields.cshtml" />
<Content Include="Views\Parts\Blogs.BlogPost.List.Admin.cshtml">
<Content Include="Views\Parts\Blogs.BlogPost.ListAdmin.cshtml">
<SubType>Code</SubType>
</Content>
<Content Include="Views\Items\Content-Blog.SummaryAdmin.cshtml" />
<Content Include="Web.config" />
<Content Include="Views\Web.config" />
</ItemGroup>
<ItemGroup>
@@ -159,10 +158,18 @@
<Content Include="Views\EditorTemplates\Parts\Blogs.BlogArchives.cshtml" />
<Content Include="Views\Items\Content-Blog.DetailAdmin.cshtml" />
<Content Include="Views\Items\Content-Blog.Edit.cshtml" />
<Content Include="Views\Items\Content-BlogPost.Editor.cshtml" />
<Content Include="Views\Parts\Blogs.BlogPost.List.cshtml" />
<Content Include="Views\Parts\Blogs.RecentBlogPosts.cshtml" />
<Content Include="Views\Parts\Blogs.Blog.BlogPostCount.cshtml" />
<Content Include="Scripts\Web.config">
<SubType>Designer</SubType>
</Content>
<Content Include="Styles\Web.config">
<SubType>Designer</SubType>
</Content>
<Content Include="Content\Web.config">
<SubType>Designer</SubType>
</Content>
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v10.0\WebApplications\Microsoft.WebApplication.targets" />

View File

@@ -1,6 +1,6 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Security;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
@@ -32,3 +32,4 @@ using System.Runtime.InteropServices;
// by using the '*' as shown below:
[assembly: AssemblyVersion("0.8.0")]
[assembly: AssemblyFileVersion("0.8.0")]
[assembly: SecurityTransparent]

View File

@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<system.web>
<httpHandlers>
<!-- iis6 - for any request in this location, return via managed static file handler -->
<add path="*" verb="*" type="System.Web.StaticFileHandler" />
</httpHandlers>
</system.web>
<system.webServer>
<handlers accessPolicy="Script,Read">
<!--
iis7 - for any request to a file exists on disk, return it via native http module.
accessPolicy 'Script' is to allow for a managed 404 page.
-->
<add name="StaticFile" path="*" verb="*" modules="StaticFileModule" preCondition="integratedMode" resourceType="File" requireAccess="Read" />
</handlers>
</system.webServer>
</configuration>

View File

@@ -49,9 +49,20 @@ namespace Orchard.Blogs.Services {
return GetBlogQuery(blogPart, versionOptions).List().Select(ci => ci.As<BlogPostPart>());
}
public IEnumerable<BlogPostPart> Get(BlogPart blogPart, int skip, int count) {
return GetBlogQuery(blogPart, VersionOptions.Published).Slice(skip, count).ToList().Select(ci => ci.As<BlogPostPart>());
return Get(blogPart, skip, count, VersionOptions.Published);
}
public IEnumerable<BlogPostPart> Get(BlogPart blogPart, int skip, int count, VersionOptions versionOptions) {
return GetBlogQuery(blogPart, versionOptions).Slice(skip, count).ToList().Select(ci => ci.As<BlogPostPart>());
}
public int PostCount(BlogPart blogPart) {
return PostCount(blogPart, VersionOptions.Published);
}
public int PostCount(BlogPart blogPart, VersionOptions versionOptions) {
return GetBlogQuery(blogPart, versionOptions).Count();
}
public IEnumerable<BlogPostPart> Get(BlogPart blogPart, ArchiveData archiveData) {

View File

@@ -13,6 +13,9 @@ namespace Orchard.Blogs.Services {
IEnumerable<BlogPostPart> Get(BlogPart blogPart, VersionOptions versionOptions);
IEnumerable<BlogPostPart> Get(BlogPart blogPart, ArchiveData archiveData);
IEnumerable<BlogPostPart> Get(BlogPart blogPart, int skip, int count);
IEnumerable<BlogPostPart> Get(BlogPart blogPart, int skip, int count, VersionOptions versionOptions);
int PostCount(BlogPart blogPart);
int PostCount(BlogPart blogPart, VersionOptions versionOptions);
IEnumerable<KeyValuePair<ArchiveData, int>> GetArchives(BlogPart blogPart);
void Delete(BlogPostPart blogPostPart);
void Publish(BlogPostPart blogPostPart);

View File

@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<system.web>
<httpHandlers>
<!-- iis6 - for any request in this location, return via managed static file handler -->
<add path="*" verb="*" type="System.Web.StaticFileHandler" />
</httpHandlers>
</system.web>
<system.webServer>
<handlers accessPolicy="Script,Read">
<!--
iis7 - for any request to a file exists on disk, return it via native http module.
accessPolicy 'Script' is to allow for a managed 404 page.
-->
<add name="StaticFile" path="*" verb="*" modules="StaticFileModule" preCondition="integratedMode" resourceType="File" requireAccess="Read" />
</handlers>
</system.webServer>
</configuration>

View File

@@ -8,7 +8,5 @@
</div>
<div class="secondary">
@Display(Model.Sidebar)
@* todo: (heskew) remove when the CommonPart is adding the save button *@
<fieldset><button class="primaryAction" type="submit">@T("Save")</button></fieldset>
</div>
</div>

View File

@@ -1,23 +0,0 @@
@* todo: (heskew) remove - not being used but keeping around for the "remove draft" reminder *@
@using Orchard.Blogs.Models;
@{
Html.AddTitleParts((string)Model.Title);
BlogPostPart blogPost = Model.ContentItem.Get(typeof(BlogPostPart));
}
<div class="sections">
<div class="primary">
@Display(Model.Content)
</div>
<div class="secondary">
@Display(Model.Sidebar)
@* todo: (heskew) remove when the CommonPart is adding the save button - also move the remove draft functionality to the CommonPart at that time *@
<fieldset>
<button class="primaryAction" type="submit" name="submit.Save">@T("Save")</button>
@* TODO: (erikpo) In the future, remove the HasPublished check so the user can delete the content item from here if the choose to *@
@if (blogPost.HasDraft && blogPost.HasPublished) {
@Html.AntiForgeryTokenValueOrchardLink(T("Discard Draft").ToString(), Url.Action("DiscardDraft", new {Area = "Orchard.Blogs", Controller = "BlogPostAdmin", id = Model.Item.Id}), new {@class = "button"})
}
</fieldset>
</div>
</div>asdfsdaf

View File

@@ -2,8 +2,6 @@
<configuration>
<system.web>
<httpHandlers>
<add path="*" verb="*"
type="System.Web.HttpNotFoundHandler"/>
</httpHandlers>
<!--
@@ -27,8 +25,6 @@
<system.webServer>
<validation validateIntegratedModeConfiguration="false"/>
<handlers>
<remove name="BlockViewHandler"/>
<add name="BlockViewHandler" path="*" verb="*" preCondition="integratedMode" type="System.Web.HttpNotFoundHandler"/>
</handlers>
</system.webServer>
<runtime>

View File

@@ -1,32 +0,0 @@
<?xml version="1.0"?>
<configuration>
<system.web>
<compilation debug="true" targetFramework="4.0">
<assemblies>
<add assembly="System.Web.Mvc, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL"/>
</assemblies>
</compilation>
<pages controlRenderingCompatibilityVersion="3.5" clientIDMode="AutoID">
<namespaces>
<add namespace="System.Web.Mvc"/>
<add namespace="System.Web.Mvc.Ajax"/>
<add namespace="System.Web.Mvc.Html"/>
<add namespace="System.Web.Routing"/>
<add namespace="System.Linq"/>
<add namespace="System.Collections.Generic"/>
<add namespace="Orchard.Mvc.Html"/>
</namespaces>
</pages>
</system.web>
<system.web.extensions/>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35" />
<bindingRedirect oldVersion="2.0.0.0" newVersion="3.0.0.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>

View File

@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<system.web>
<httpHandlers>
<!-- iis6 - for any request in this location, return via managed static file handler -->
<add path="*" verb="*" type="System.Web.StaticFileHandler" />
</httpHandlers>
</system.web>
<system.webServer>
<handlers accessPolicy="Script,Read">
<!--
iis7 - for any request to a file exists on disk, return it via native http module.
accessPolicy 'Script' is to allow for a managed 404 page.
-->
<add name="StaticFile" path="*" verb="*" modules="StaticFileModule" preCondition="integratedMode" resourceType="File" requireAccess="Read" />
</handlers>
</system.webServer>
</configuration>

View File

@@ -2,8 +2,6 @@
<configuration>
<system.web>
<httpHandlers>
<add path="*" verb="*"
type="System.Web.HttpNotFoundHandler"/>
</httpHandlers>
<!--
@@ -27,8 +25,6 @@
<system.webServer>
<validation validateIntegratedModeConfiguration="false"/>
<handlers>
<remove name="BlockViewHandler"/>
<add name="BlockViewHandler" path="*" verb="*" preCondition="integratedMode" type="System.Web.HttpNotFoundHandler"/>
</handlers>
</system.webServer>
</configuration>

View File

@@ -23,7 +23,7 @@ namespace Orchard.CodeGeneration.Commands {
"", "Content", "Styles", "Scripts", "Views", "Zones"
};
private static readonly string[] _moduleDirectories = new [] {
"", "Properties", "Controllers", "Views", "Models", "Scripts"
"", "Properties", "Controllers", "Views", "Models", "Scripts", "Styles"
};
private const string ModuleName = "CodeGeneration";
@@ -227,6 +227,10 @@ namespace Orchard.CodeGeneration.Commands {
File.WriteAllText(modulePath + "Views\\Web.config", File.ReadAllText(_codeGenTemplatePath + "ViewsWebConfig.txt"));
content.Add(modulePath + "Views\\Web.config");
File.WriteAllText(modulePath + "Scripts\\Web.config", File.ReadAllText(_codeGenTemplatePath + "StaticFilesWebConfig.txt"));
content.Add(modulePath + "Scripts\\Web.config");
File.WriteAllText(modulePath + "Styles\\Web.config", File.ReadAllText(_codeGenTemplatePath + "StaticFilesWebConfig.txt"));
content.Add(modulePath + "Styles\\Web.config");
string templateText = File.ReadAllText(_codeGenTemplatePath + "ModuleAssemblyInfo.txt");
templateText = templateText.Replace("$$ModuleName$$", moduleName);
@@ -270,6 +274,10 @@ namespace Orchard.CodeGeneration.Commands {
var webConfig = themePath + "Views\\Web.config";
File.WriteAllText(webConfig, File.ReadAllText(_codeGenTemplatePath + "\\ViewsWebConfig.txt"));
createdFiles.Add(webConfig);
File.WriteAllText(themePath + "Scripts\\Web.config", File.ReadAllText(_codeGenTemplatePath + "StaticFilesWebConfig.txt"));
createdFiles.Add(themePath + "Scripts\\Web.config");
File.WriteAllText(themePath + "Styles\\Web.config", File.ReadAllText(_codeGenTemplatePath + "StaticFilesWebConfig.txt"));
createdFiles.Add(themePath + "Styles\\Web.config");
var templateText = File.ReadAllText(_codeGenTemplatePath + "\\ThemeManifest.txt").Replace("$$ThemeName$$", themeName);
if (string.IsNullOrEmpty(baseTheme)) {

View File

@@ -76,6 +76,7 @@
<Compile Include="Services\CodeGenerationCommandInterpreter.cs" />
</ItemGroup>
<ItemGroup>
<Content Include="CodeGenerationTemplates\StaticFilesWebConfig.txt" />
<Content Include="CodeGenerationTemplates\ThemeManifest.txt" />
<Content Include="Module.txt" />
<Content Include="CodeGenerationTemplates\Controller.txt" />
@@ -85,7 +86,6 @@
<Content Include="CodeGenerationTemplates\ModuleManifest.txt" />
<Content Include="CodeGenerationTemplates\ModuleWebConfig.txt" />
<Content Include="CodeGenerationTemplates\ViewsWebConfig.txt" />
<Content Include="Web.config" />
</ItemGroup>
<ItemGroup />
<ItemGroup>

View File

@@ -1,5 +1,6 @@
using System.Reflection;
using System.Runtime.InteropServices;
using System.Security;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
@@ -31,3 +32,4 @@ using System.Runtime.InteropServices;
// by using the '*' as shown below:
[assembly: AssemblyVersion("0.8.0")]
[assembly: AssemblyFileVersion("0.8.0")]
[assembly: SecurityTransparent]

View File

@@ -1,32 +0,0 @@
<?xml version="1.0"?>
<configuration>
<system.web>
<compilation debug="true" targetFramework="4.0">
<assemblies>
<add assembly="System.Web.Mvc, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL"/>
</assemblies>
</compilation>
<pages controlRenderingCompatibilityVersion="3.5" clientIDMode="AutoID">
<namespaces>
<add namespace="System.Web.Mvc"/>
<add namespace="System.Web.Mvc.Ajax"/>
<add namespace="System.Web.Mvc.Html"/>
<add namespace="System.Web.Routing"/>
<add namespace="System.Linq"/>
<add namespace="System.Collections.Generic"/>
<add namespace="Orchard.Mvc.Html"/>
</namespaces>
</pages>
</system.web>
<system.web.extensions/>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35" />
<bindingRedirect oldVersion="2.0.0.0" newVersion="3.0.0.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>

View File

@@ -8,10 +8,9 @@ namespace Orchard.Comments {
public string MenuName { get { return "admin"; } }
public void GetNavigation(NavigationBuilder builder) {
builder.Add(T("Comments"), "3",
menu => menu
.Add(T("Manage Comments"), "1.0", item => item.Action("Index", "Admin", new { area = "Orchard.Comments" }).Permission(Permissions.ManageComments))
);
builder.Add(T("Comments"), "10",
menu => menu.Add(T("List"), "0", item => item.Action("Index", "Admin", new { area = "Orchard.Comments" })
.Permission(Permissions.ManageComments)));
}
}
}

View File

@@ -5,6 +5,7 @@ using System.Reflection;
using System.Web.Mvc;
using JetBrains.Annotations;
using Orchard.Comments.Models;
using Orchard.ContentManagement;
using Orchard.DisplayManagement;
using Orchard.Localization;
using Orchard.Logging;
@@ -42,7 +43,7 @@ namespace Orchard.Comments.Controllers {
options = new CommentIndexOptions();
// Filtering
IEnumerable<CommentPart> comments;
IContentQuery<CommentPart, CommentPartRecord> comments;
try {
switch (options.Filter) {
case CommentIndexFilter.All:
@@ -60,13 +61,16 @@ namespace Orchard.Comments.Controllers {
default:
throw new ArgumentOutOfRangeException();
}
var entries = comments.Skip(pager.GetStartIndex()).Take(pager.PageSize).Select(comment => CreateCommentEntry(comment.Record)).ToList();
var hasNextPage = comments.Skip(pager.GetStartIndex(pager.Page + 1)).Any();
var pagerShape = Shape.Pager(pager).HasNextPage(hasNextPage);
var pagerShape = Shape.Pager(pager).TotalItemCount(comments.Count());
var entries = comments
.OrderByDescending<CommentPartRecord, DateTime?>(cpr => cpr.CommentDateUtc)
.Slice(pager.GetStartIndex(), pager.PageSize)
.ToList()
.Select(comment => CreateCommentEntry(comment.Record));
var model = new CommentsIndexViewModel {
Comments = entries,
Comments = entries.ToList(),
Options = options,
Pager = pagerShape
};
@@ -97,12 +101,12 @@ namespace Orchard.Comments.Controllers {
_commentService.MarkCommentAsSpam(entry.Comment.Id);
}
break;
case CommentIndexBulkAction.Pend:
case CommentIndexBulkAction.Unapprove:
if (!Services.Authorizer.Authorize(Permissions.ManageComments, T("Couldn't moderate comment")))
return new HttpUnauthorizedResult();
//TODO: Transaction
foreach (CommentEntry entry in checkedEntries) {
_commentService.PendComment(entry.Comment.Id);
_commentService.UnapproveComment(entry.Comment.Id);
}
break;
case CommentIndexBulkAction.Approve:
@@ -140,7 +144,7 @@ namespace Orchard.Comments.Controllers {
options = new CommentDetailsOptions();
// Filtering
IEnumerable<CommentPart> comments;
IContentQuery<CommentPart, CommentPartRecord> comments;
try {
switch (options.Filter) {
case CommentDetailsFilter.All:
@@ -158,7 +162,7 @@ namespace Orchard.Comments.Controllers {
default:
throw new ArgumentOutOfRangeException();
}
var entries = comments.Select(comment => CreateCommentEntry(comment.Record)).ToList();
var entries = comments.List().Select(comment => CreateCommentEntry(comment.Record)).ToList();
var model = new CommentsDetailsViewModel {
Comments = entries,
Options = options,
@@ -193,12 +197,12 @@ namespace Orchard.Comments.Controllers {
_commentService.MarkCommentAsSpam(entry.Comment.Id);
}
break;
case CommentDetailsBulkAction.Pend:
case CommentDetailsBulkAction.Unapprove:
if (!Services.Authorizer.Authorize(Permissions.ManageComments, T("Couldn't moderate comment")))
return new HttpUnauthorizedResult();
foreach (CommentEntry entry in checkedEntries) {
_commentService.PendComment(entry.Comment.Id);
_commentService.UnapproveComment(entry.Comment.Id);
}
break;
case CommentDetailsBulkAction.Approve:
@@ -307,6 +311,75 @@ namespace Orchard.Comments.Controllers {
}
}
[HttpPost]
public ActionResult Approve(int id, string returnUrl) {
try {
if (!Services.Authorizer.Authorize(Permissions.ManageComments, T("Couldn't approve comment")))
return new HttpUnauthorizedResult();
int commentedOn = _commentService.GetComment(id).Record.CommentedOn;
_commentService.ApproveComment(id);
if (!String.IsNullOrEmpty(returnUrl)) {
return Redirect(returnUrl);
}
return RedirectToAction("Details", new { id = commentedOn });
}
catch (Exception exception) {
Services.Notifier.Error(T("Approving comment failed: " + exception.Message));
if (!String.IsNullOrEmpty(returnUrl)) {
return Redirect(returnUrl);
}
return RedirectToAction("Index");
}
}
[HttpPost]
public ActionResult Unapprove(int id, string returnUrl) {
try {
if (!Services.Authorizer.Authorize(Permissions.ManageComments, T("Couldn't unapprove comment")))
return new HttpUnauthorizedResult();
int commentedOn = _commentService.GetComment(id).Record.CommentedOn;
_commentService.UnapproveComment(id);
if (!String.IsNullOrEmpty(returnUrl)) {
return Redirect(returnUrl);
}
return RedirectToAction("Details", new { id = commentedOn });
}
catch (Exception exception) {
Services.Notifier.Error(T("Unapproving comment failed: " + exception.Message));
if (!String.IsNullOrEmpty(returnUrl)) {
return Redirect(returnUrl);
}
return RedirectToAction("Index");
}
}
[HttpPost]
public ActionResult MarkAsSpam(int id, string returnUrl) {
try {
if (!Services.Authorizer.Authorize(Permissions.ManageComments, T("Couldn't mark comment as spam")))
return new HttpUnauthorizedResult();
int commentedOn = _commentService.GetComment(id).Record.CommentedOn;
_commentService.MarkCommentAsSpam(id);
if (!String.IsNullOrEmpty(returnUrl)) {
return Redirect(returnUrl);
}
return RedirectToAction("Details", new { id = commentedOn });
}
catch (Exception exception) {
Services.Notifier.Error(T("Marking comment as spam failed: " + exception.Message));
if (!String.IsNullOrEmpty(returnUrl)) {
return Redirect(returnUrl);
}
return RedirectToAction("Index");
}
}
[HttpPost]
public ActionResult Delete(int id, string returnUrl) {
try {
@@ -333,7 +406,7 @@ namespace Orchard.Comments.Controllers {
private CommentEntry CreateCommentEntry(CommentPartRecord commentPart) {
return new CommentEntry {
Comment = commentPart,
CommentedOn = _commentService.GetDisplayForCommentedContent(commentPart.CommentedOn).DisplayText,
CommentedOn = _commentService.GetCommentedContent(commentPart.CommentedOn),
IsChecked = false,
};
}

View File

@@ -35,7 +35,8 @@ namespace Orchard.Comments.Handlers {
OnRemoved<CommentsPart>(
(context, c) => {
foreach (var comment in commentService.GetCommentsForCommentedContent(context.ContentItem.Id)) {
var comments = commentService.GetCommentsForCommentedContent(context.ContentItem.Id).List();
foreach (var comment in comments) {
contentManager.Remove(comment.ContentItem);
}
});

View File

@@ -110,8 +110,8 @@
</ItemGroup>
<ItemGroup>
<Content Include="Module.txt" />
<Content Include="Styles\admin.css" />
<Content Include="Views\Admin\Details.cshtml" />
<Content Include="Web.config" />
<Content Include="Views\Web.config" />
</ItemGroup>
<ItemGroup>
@@ -139,6 +139,7 @@
<SubType>Designer</SubType>
</Content>
</ItemGroup>
<ItemGroup />
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v10.0\WebApplications\Microsoft.WebApplication.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.

View File

@@ -1,6 +1,6 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Security;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
@@ -32,3 +32,4 @@ using System.Runtime.InteropServices;
// by using the '*' as shown below:
[assembly: AssemblyVersion("0.8.0")]
[assembly: AssemblyFileVersion("0.8.0")]
[assembly: SecurityTransparent]

View File

@@ -1,7 +1,5 @@
using System.Collections.Generic;
using System.Linq;
using System.Linq;
using JetBrains.Annotations;
using Orchard.Comments.Drivers;
using Orchard.Comments.Models;
using Orchard.ContentManagement.Aspects;
using Orchard.Data;
@@ -32,32 +30,28 @@ namespace Orchard.Comments.Services {
public ILogger Logger { get; set; }
protected virtual IUser CurrentUser { get; [UsedImplicitly] private set; }
public IEnumerable<CommentPart> GetComments() {
public IContentQuery<CommentPart, CommentPartRecord> GetComments() {
return _contentManager
.Query<CommentPart, CommentPartRecord>()
.List();
.Query<CommentPart, CommentPartRecord>();
}
public IEnumerable<CommentPart> GetComments(CommentStatus status) {
public IContentQuery<CommentPart, CommentPartRecord> GetComments(CommentStatus status) {
return _contentManager
.Query<CommentPart, CommentPartRecord>()
.Where(c => c.Status == status)
.List();
.Query<CommentPart, CommentPartRecord>()
.Where(c => c.Status == status);
}
public IEnumerable<CommentPart> GetCommentsForCommentedContent(int id) {
public IContentQuery<CommentPart, CommentPartRecord> GetCommentsForCommentedContent(int id) {
return _contentManager
.Query<CommentPart, CommentPartRecord>()
.Where(c => c.CommentedOn == id || c.CommentedOnContainer == id)
.List();
.Query<CommentPart, CommentPartRecord>()
.Where(c => c.CommentedOn == id || c.CommentedOnContainer == id);
}
public IEnumerable<CommentPart> GetCommentsForCommentedContent(int id, CommentStatus status) {
public IContentQuery<CommentPart, CommentPartRecord> GetCommentsForCommentedContent(int id, CommentStatus status) {
return _contentManager
.Query<CommentPart, CommentPartRecord>()
.Where(c => c.CommentedOn == id || c.CommentedOnContainer == id)
.Where(ctx => ctx.Status == status)
.List();
.Query<CommentPart, CommentPartRecord>()
.Where(c => c.CommentedOn == id || c.CommentedOnContainer == id)
.Where(ctx => ctx.Status == status);
}
public CommentPart GetComment(int id) {
@@ -71,6 +65,10 @@ namespace Orchard.Comments.Services {
return _contentManager.GetItemMetadata(content);
}
public ContentItem GetCommentedContent(int id) {
return _contentManager.Get(id);
}
public CommentPart CreateComment(CreateCommentContext context, bool moderateComments) {
var comment = _contentManager.Create<CommentPart>("Comment");
@@ -110,7 +108,7 @@ namespace Orchard.Comments.Services {
commentPart.Record.Status = CommentStatus.Approved;
}
public void PendComment(int commentId) {
public void UnapproveComment(int commentId) {
CommentPart commentPart = GetComment(commentId);
commentPart.Record.Status = CommentStatus.Pending;
}

View File

@@ -1,19 +1,19 @@
using System.Collections.Generic;
using Orchard.Comments.Models;
using Orchard.ContentManagement;
namespace Orchard.Comments.Services {
public interface ICommentService : IDependency {
IEnumerable<CommentPart> GetComments();
IEnumerable<CommentPart> GetComments(CommentStatus status);
IEnumerable<CommentPart> GetCommentsForCommentedContent(int id);
IEnumerable<CommentPart> GetCommentsForCommentedContent(int id, CommentStatus status);
IContentQuery<CommentPart, CommentPartRecord> GetComments();
IContentQuery<CommentPart, CommentPartRecord> GetComments(CommentStatus status);
IContentQuery<CommentPart, CommentPartRecord> GetCommentsForCommentedContent(int id);
IContentQuery<CommentPart, CommentPartRecord> GetCommentsForCommentedContent(int id, CommentStatus status);
CommentPart GetComment(int id);
ContentItemMetadata GetDisplayForCommentedContent(int id);
ContentItem GetCommentedContent(int id);
CommentPart CreateComment(CreateCommentContext commentRecord, bool moderateComments);
void UpdateComment(int id, string name, string email, string siteName, string commentText, CommentStatus status);
void ApproveComment(int commentId);
void PendComment(int commentId);
void UnapproveComment(int commentId);
void MarkCommentAsSpam(int commentId);
void DeleteComment(int commentId);
bool CommentsClosedForCommentedContent(int id);

View File

@@ -0,0 +1,3 @@
table.items .actions {
white-space:nowrap;
}

View File

@@ -16,7 +16,7 @@ namespace Orchard.Comments.ViewModels {
public enum CommentDetailsBulkAction {
None,
Pend,
Unapprove,
Approve,
MarkAsSpam,
Delete,

View File

@@ -1,5 +1,6 @@
using System.Collections.Generic;
using Orchard.Comments.Models;
using Orchard.ContentManagement;
namespace Orchard.Comments.ViewModels {
public class CommentsIndexViewModel {
@@ -10,7 +11,7 @@ namespace Orchard.Comments.ViewModels {
public class CommentEntry {
public CommentPartRecord Comment { get; set; }
public string CommentedOn { get; set; }
public ContentItem CommentedOn { get; set; }
public bool IsChecked { get; set; }
}
@@ -21,7 +22,7 @@ namespace Orchard.Comments.ViewModels {
public enum CommentIndexBulkAction {
None,
Pend,
Unapprove,
Approve,
MarkAsSpam,
Delete

View File

@@ -13,7 +13,7 @@
} else {
using (Html.BeginFormAntiForgeryPost(Url.Action("Close", new { commentedItemId = Model.CommentedItemId }), FormMethod.Post, new { @class = "inline" })) {
<fieldset>
<button type="submit" class="button primaryAction" title="@T("Close Comments")">@T("Close Comments")</button>
<button type="submit" class="primaryAction" title="@T("Close Comments")">@T("Close Comments")</button>
</fieldset>
}
}
@@ -29,7 +29,7 @@
@Html.SelectOption(Model.Options.BulkAction, CommentDetailsBulkAction.MarkAsSpam, T("Mark as Spam").ToString())
@Html.SelectOption(Model.Options.BulkAction, CommentDetailsBulkAction.Delete, T("Remove").ToString())
</select>
<input class="button" type="submit" name="submit.BulkEdit" value="@T("Apply")" />
<button type="submit" name="submit.BulkEdit" value="@T("Apply")">@T("Apply")</button>
</fieldset>
<fieldset class="bulk-actions">
<label for="filterResults">@T("Filter:")</label>
@@ -39,7 +39,7 @@
@Html.SelectOption(Model.Options.Filter, CommentDetailsFilter.Pending, T("Pending Comments").ToString())
@Html.SelectOption(Model.Options.Filter, CommentDetailsFilter.Spam, T("Spam").ToString())
</select>
<input class="button" type="submit" name="submit.Filter" value="@T("Apply")"/>
<button type="submit" name="submit.Filter" value="@T("Apply")">@T("Apply")</button>
</fieldset>
<fieldset>
<table class="items" summary="@T("This is a table of the comments for the content item")">
@@ -108,7 +108,7 @@
} else {
using (Html.BeginFormAntiForgeryPost(Url.Action("Close", new { commentedItemId = Model.CommentedItemId }), FormMethod.Post, new { @class = "inline" })) {
<fieldset>
<button type="submit" class="button primaryAction" title="@T("Close Comments")">@T("Close Comments")</button>
<button type="submit" class="primaryAction" title="@T("Close Comments")">@T("Close Comments")</button>
</fieldset>
}
}

Some files were not shown because too many files have changed in this diff Show More