mirror of
https://github.com/OrchardCMS/Orchard.git
synced 2025-07-31 20:18:40 +08:00
Merge with 1.x
This commit is contained in:
commit
1b5f9b2a16
6
.hgsub
6
.hgsub
@ -6,4 +6,8 @@ src/Orchard.Web/Modules/Orchard.TaskLease = https://hg.codeplex.com/orchardtaskl
|
||||
src/orchard.web/modules/Orchard.Fields = https://hg.codeplex.com/orchardfields
|
||||
src/Orchard.Web/Modules/Orchard.Autoroute = https://hg.codeplex.com/orchardautoroute
|
||||
src/orchard.web/Modules/Orchard.Alias = https://hg.codeplex.com/orchardalias
|
||||
src/orchard.web/Modules/Orchard.Projections = https://hg.codeplex.com/orchardprojections
|
||||
src/orchard.web/Modules/Orchard.Projections = https://hg.codeplex.com/orchardprojections
|
||||
src/Orchard.Web/Modules/Orchard.AntiSpam = https://hg.codeplex.com/orchardantispam
|
||||
src/Orchard.Web/Modules/Orchard.CustomForms = https://hg.codeplex.com/orchardcustomforms
|
||||
src/Orchard.Web/Modules/Orchard.ContentPermissions = https://hg.codeplex.com/orchardcontentperm
|
||||
src/Orchard.Web/Modules/Orchard.ContentPicker = https://hg.codeplex.com/orchardcontentpicker
|
||||
|
18
.hgsubstate
18
.hgsubstate
@ -1,8 +1,12 @@
|
||||
bf20391f8fe1ba5d67cadc0643d79ad9fe892d4e src/Orchard.Web/Modules/Orchard.Autoroute
|
||||
e7fc05ff6137ed5459d198b2bea9a5804818b0bd src/Orchard.Web/Modules/Orchard.Forms
|
||||
681acdfadd946098a10a4a22f6904e8c482c122f src/Orchard.Web/Modules/Orchard.Rules
|
||||
c47525e90819321d37962a11313006a4ccfc8362 src/Orchard.Web/Modules/Orchard.AntiSpam
|
||||
03306c0dad118c03c4ee21ce274a5f9c5855aec3 src/Orchard.Web/Modules/Orchard.Autoroute
|
||||
a8cd78f4730747bf592935aaa605874938a9c89f src/Orchard.Web/Modules/Orchard.ContentPermissions
|
||||
4a97d09dc6a31a083643c4b7468c307413a43f44 src/Orchard.Web/Modules/Orchard.ContentPicker
|
||||
3ad1bdc80b8374433d98469e8740bc48ef114be2 src/Orchard.Web/Modules/Orchard.CustomForms
|
||||
b639cb33d2ba038de6048350400b664399608996 src/Orchard.Web/Modules/Orchard.Forms
|
||||
b748de63e3cf8debfc3eba77f26089705147047d src/Orchard.Web/Modules/Orchard.Rules
|
||||
419399ef2e37122a000e6cc8674148d3183d7032 src/Orchard.Web/Modules/Orchard.TaskLease
|
||||
aca1f5aeb5dd426bc80c6142afc7f2717fc6d5a1 src/Orchard.Web/Modules/Orchard.Tokens
|
||||
4ed51e0e76c2aacc2de90ce9984fd00cfdfae2ce src/orchard.web/Modules/Orchard.Alias
|
||||
f5353e9e0f678d396735df6eb6ca3c7f30a09660 src/orchard.web/Modules/Orchard.Projections
|
||||
4d125be1a6b35451214768cd8e46b6e7e2b08174 src/orchard.web/modules/Orchard.Fields
|
||||
63dda71453ebbfd0e165662a0d56c9c0a7a3d3d4 src/Orchard.Web/Modules/Orchard.Tokens
|
||||
a47761330447df38f714bc17797b8895721a6974 src/orchard.web/Modules/Orchard.Alias
|
||||
a2ed939103036405c0d446d6562bd365752ca9d3 src/orchard.web/Modules/Orchard.Projections
|
||||
c1f7fa43511eb21314eb0fda82f74bd07769d508 src/orchard.web/modules/Orchard.Fields
|
||||
|
@ -16,7 +16,7 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<Import Project="$(LibFolder)\msbuild\MSBuild.Community.Tasks.Targets"/>
|
||||
<Import Project="$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v10.0\Windows Azure Tools\1.6\Microsoft.WindowsAzure.targets" />
|
||||
<Import Project="$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v10.0\Windows Azure Tools\1.7\Microsoft.WindowsAzure.targets" />
|
||||
|
||||
<!-- Coordinating Targets -->
|
||||
|
||||
|
@ -277,7 +277,6 @@
|
||||
$(StageFolder)\**\Modules\Orchard.CodeGeneration\**;
|
||||
$(StageFolder)\**\Modules\Orchard.DesignerTools\**;
|
||||
$(StageFolder)\**\Modules\Orchard.Email\**;
|
||||
$(StageFolder)\**\Modules\Orchard.Experimental\**;
|
||||
$(StageFolder)\**\Modules\Orchard.ImportExport\**;
|
||||
$(StageFolder)\**\Modules\Orchard.Indexing\**;
|
||||
$(StageFolder)\**\Modules\Orchard.Lists\**;
|
||||
@ -311,6 +310,7 @@
|
||||
$(MSBuildProjectDirectory)\**\*.suo;
|
||||
$(MSBuildProjectDirectory)\**\*.user;
|
||||
$(MSBuildProjectDirectory)\**\*.patch;
|
||||
$(MSBuildProjectDirectory)\**\*.hgignore;
|
||||
$(MSBuildProjectDirectory)\**\*.hg*\**\*;
|
||||
$(LibFolder)\nunit\addins\**\*;
|
||||
" />
|
||||
@ -383,7 +383,6 @@
|
||||
<Exec Command=""$(GalleryFolder)\bin\Orchard.exe" package create Orchard.CodeGeneration "$(GalleryArtifactFolder)"" WorkingDirectory="$(GalleryFolder)"/>
|
||||
<Exec Command=""$(GalleryFolder)\bin\Orchard.exe" package create Orchard.DesignerTools "$(GalleryArtifactFolder)"" WorkingDirectory="$(GalleryFolder)"/>
|
||||
<Exec Command=""$(GalleryFolder)\bin\Orchard.exe" package create Orchard.Email "$(GalleryArtifactFolder)"" WorkingDirectory="$(GalleryFolder)"/>
|
||||
<Exec Command=""$(GalleryFolder)\bin\Orchard.exe" package create Orchard.Experimental "$(GalleryArtifactFolder)"" WorkingDirectory="$(GalleryFolder)"/>
|
||||
<Exec Command=""$(GalleryFolder)\bin\Orchard.exe" package create Orchard.ImportExport "$(GalleryArtifactFolder)"" WorkingDirectory="$(GalleryFolder)"/>
|
||||
<Exec Command=""$(GalleryFolder)\bin\Orchard.exe" package create Orchard.Indexing "$(GalleryArtifactFolder)"" WorkingDirectory="$(GalleryFolder)"/>
|
||||
<Exec Command=""$(GalleryFolder)\bin\Orchard.exe" package create Orchard.Lists "$(GalleryArtifactFolder)"" WorkingDirectory="$(GalleryFolder)"/>
|
||||
|
@ -1,7 +1,7 @@
|
||||
<?xml version="1.0"?>
|
||||
<configuration>
|
||||
<appSettings>
|
||||
<add key="AzureSDK" value="C:\Program Files\Windows Azure SDK\v1.6\"/>
|
||||
<add key="AzureSDK" value="C:\Program Files\Microsoft SDKs\Windows Azure\"/>
|
||||
</appSettings>
|
||||
<startup>
|
||||
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/>
|
||||
|
@ -17,8 +17,7 @@ namespace Orchard.Azure.Tests {
|
||||
if ( count == 0 ) {
|
||||
var start = new ProcessStartInfo {
|
||||
Arguments = "/devstore:start",
|
||||
FileName =
|
||||
Path.Combine(ConfigurationManager.AppSettings["AzureSDK"], @"C:\Program Files\Windows Azure Emulator\emulator\csrun.exe")
|
||||
FileName = Path.Combine(ConfigurationManager.AppSettings["AzureSDK"], @"emulator\csrun.exe")
|
||||
};
|
||||
|
||||
_dsService = new Process { StartInfo = start };
|
||||
|
@ -53,9 +53,9 @@
|
||||
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="Microsoft.WindowsAzure.Diagnostics, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL" />
|
||||
<Reference Include="Microsoft.WindowsAzure.ServiceRuntime, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL" />
|
||||
<Reference Include="Microsoft.WindowsAzure.StorageClient, Version=1.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL" />
|
||||
<Reference Include="Microsoft.WindowsAzure.Diagnostics, Version=1.7.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL" />
|
||||
<Reference Include="Microsoft.WindowsAzure.ServiceRuntime, Version=1.7.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL" />
|
||||
<Reference Include="Microsoft.WindowsAzure.StorageClient, Version=1.7.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL" />
|
||||
<Reference Include="Moq, Version=4.0.812.4, Culture=neutral, PublicKeyToken=69f491c39445e920, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\..\lib\moq\Moq.dll</HintPath>
|
||||
@ -96,7 +96,9 @@
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="App.config" />
|
||||
<None Include="App.config">
|
||||
<SubType>Designer</SubType>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<BootstrapperPackage Include="Microsoft.Net.Client.3.5">
|
||||
|
@ -298,26 +298,37 @@ namespace Orchard.Azure {
|
||||
return "application/unknown";
|
||||
}
|
||||
|
||||
string applicationHost = System.Environment.ExpandEnvironmentVariables(@"%windir%\system32\inetsrv\config\applicationHost.config");
|
||||
if (File.Exists(applicationHost)) {
|
||||
var xdoc = XDocument.Load(applicationHost);
|
||||
var mimeMap = xdoc.XPathSelectElements("//staticContent/mimeMap[@fileExtension='" + extension + "']").FirstOrDefault();
|
||||
if(mimeMap != null) {
|
||||
var mimeType = mimeMap.Attribute("mimeType");
|
||||
if(mimeType != null) {
|
||||
return mimeType.Value;
|
||||
try {
|
||||
string applicationHost = System.Environment.ExpandEnvironmentVariables(@"%windir%\system32\inetsrv\config\applicationHost.config");
|
||||
string webConfig = System.Web.Configuration.WebConfigurationManager.OpenWebConfiguration("/").FilePath;
|
||||
|
||||
// search for custom mime types in web.config and applicationhost.config
|
||||
foreach (var configFile in new[] {webConfig, applicationHost}) {
|
||||
if (File.Exists(configFile)) {
|
||||
var xdoc = XDocument.Load(configFile);
|
||||
var mimeMap = xdoc.XPathSelectElements("//staticContent/mimeMap[@fileExtension='" + extension + "']").FirstOrDefault();
|
||||
if (mimeMap != null) {
|
||||
var mimeType = mimeMap.Attribute("mimeType");
|
||||
if (mimeType != null) {
|
||||
return mimeType.Value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// search into the registry
|
||||
RegistryKey regKey = Registry.ClassesRoot.OpenSubKey(extension.ToLower());
|
||||
if (regKey != null) {
|
||||
var contentType = regKey.GetValue("Content Type");
|
||||
if (contentType != null) {
|
||||
return contentType.ToString();
|
||||
// search into the registry
|
||||
RegistryKey regKey = Registry.ClassesRoot.OpenSubKey(extension.ToLower());
|
||||
if (regKey != null) {
|
||||
var contentType = regKey.GetValue("Content Type");
|
||||
if (contentType != null) {
|
||||
return contentType.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
catch {
|
||||
// if an exception occured return application/unknown
|
||||
return "application/unknown";
|
||||
}
|
||||
|
||||
return "application/unknown";
|
||||
}
|
||||
|
@ -4,7 +4,7 @@
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProductVersion>1.6</ProductVersion>
|
||||
<ProductVersion>1.7</ProductVersion>
|
||||
<ProjectGuid>{03c5327d-4e8e-45a7-acd1-e18e7caa3c4a}</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
@ -12,6 +12,7 @@
|
||||
<AssemblyName>Orchard.Azure.CloudService</AssemblyName>
|
||||
<StartDevelopmentStorage>True</StartDevelopmentStorage>
|
||||
<Name>OrchardCloudService</Name>
|
||||
<UseIISExpressByDefault>False</UseIISExpressByDefault>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
@ -47,7 +48,7 @@
|
||||
<!-- Import the target files for this project template -->
|
||||
<PropertyGroup>
|
||||
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">10.0</VisualStudioVersion>
|
||||
<CloudExtensionsDir Condition=" '$(CloudExtensionsDir)' == '' ">$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v$(VisualStudioVersion)\Windows Azure Tools\1.6\</CloudExtensionsDir>
|
||||
<CloudExtensionsDir Condition=" '$(CloudExtensionsDir)' == '' ">$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v$(VisualStudioVersion)\Windows Azure Tools\1.7\</CloudExtensionsDir>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(CloudExtensionsDir)Microsoft.WindowsAzure.targets" />
|
||||
</Project>
|
@ -1,5 +1,5 @@
|
||||
<?xml version="1.0"?>
|
||||
<ServiceConfiguration serviceName="OrchardCloudService" osFamily="1" osVersion="*" xmlns="http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceConfiguration">
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<ServiceConfiguration serviceName="OrchardCloudService" osFamily="1" osVersion="*" xmlns="http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceConfiguration" schemaVersion="2012-05.1.7">
|
||||
<Role name="Orchard.Azure.Web">
|
||||
<Instances count="1" />
|
||||
<ConfigurationSettings>
|
||||
|
@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<ServiceDefinition name="OrchardCloudService" xmlns="http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceDefinition">
|
||||
<ServiceDefinition name="OrchardCloudService" xmlns="http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceDefinition" schemaVersion="2012-05.1.7">
|
||||
<WebRole name="Orchard.Azure.Web">
|
||||
<Sites>
|
||||
<Site name="Web">
|
||||
|
@ -55,15 +55,10 @@
|
||||
<HintPath>..\..\..\lib\aspnetmvc\Microsoft.Web.Infrastructure.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.WindowsAzure.Diagnostics, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.WindowsAzure.ServiceRuntime, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<Private>False</Private>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.WindowsAzure.StorageClient, Version=1.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.WindowsAzure.Configuration, Version=1.7.0.0, Culture=neutral, processorArchitecture=MSIL" />
|
||||
<Reference Include="Microsoft.WindowsAzure.Diagnostics, Version=1.7.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL" />
|
||||
<Reference Include="Microsoft.WindowsAzure.ServiceRuntime, Version=1.7.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL" />
|
||||
<Reference Include="Microsoft.WindowsAzure.StorageClient, Version=1.7.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL" />
|
||||
<Reference Include="NHibernate.ByteCode.Castle">
|
||||
<HintPath>..\..\..\lib\fluentnhibernate\NHibernate.ByteCode.Castle.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
@ -81,11 +76,8 @@
|
||||
<Reference Include="System.Data.DataSetExtensions">
|
||||
<Private>False</Private>
|
||||
</Reference>
|
||||
<Reference Include="System.Data.SqlServerCe, Version=4.0.0.0, Culture=neutral, PublicKeyToken=89845dcd8080cc91, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\..\lib\sqlce\System.Data.SqlServerCe.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="System.Data.Services.Client" />
|
||||
<Reference Include="System.Data.SqlServerCe, Version=3.5.1.0, PublicKeyToken=89845dcd8080cc91" />
|
||||
<Reference Include="System.Web.ApplicationServices">
|
||||
<Private>False</Private>
|
||||
</Reference>
|
||||
@ -231,11 +223,6 @@
|
||||
<Name>Orchard.Email</Name>
|
||||
<Private>True</Private>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\Orchard.Web\Modules\Orchard.Experimental\Orchard.Experimental.csproj">
|
||||
<Project>{AB3C207C-0126-4143-8D62-1119DF80D366}</Project>
|
||||
<Name>Orchard.Experimental</Name>
|
||||
<Private>True</Private>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\Orchard.Web\Modules\Orchard.Fields\Orchard.Fields.csproj">
|
||||
<Project>{3787DDE5-E5C8-4841-BDA7-DCB325388064}</Project>
|
||||
<Name>Orchard.Fields</Name>
|
||||
|
@ -40,12 +40,9 @@
|
||||
<system.diagnostics>
|
||||
<trace>
|
||||
<listeners>
|
||||
<add type="Microsoft.WindowsAzure.Diagnostics.DiagnosticMonitorTraceListener,
|
||||
Microsoft.WindowsAzure.Diagnostics,
|
||||
Version=1.0.0.0,
|
||||
Culture=neutral,
|
||||
PublicKeyToken=31bf3856ad364e35"
|
||||
name="AzureDiagnostics">
|
||||
<add type="Microsoft.WindowsAzure.Diagnostics.DiagnosticMonitorTraceListener, Microsoft.WindowsAzure.Diagnostics, Version=1.7.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
|
||||
name="AzureDiagnostics">
|
||||
<filter type="" />
|
||||
</add>
|
||||
</listeners>
|
||||
</trace>
|
||||
|
@ -57,12 +57,11 @@
|
||||
<HintPath>..\..\lib\fluentnhibernate\log4net.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.WindowsAzure.Diagnostics, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL" />
|
||||
<Reference Include="Microsoft.WindowsAzure.ServiceRuntime, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL" />
|
||||
<Reference Include="Microsoft.WindowsAzure.StorageClient, Version=1.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.WindowsAzure.Diagnostics, Version=1.7.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL" />
|
||||
<Reference Include="Microsoft.WindowsAzure.ServiceRuntime, Version=1.7.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL" />
|
||||
<Reference Include="Microsoft.WindowsAzure.StorageClient, Version=1.7.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL" />
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.configuration" />
|
||||
<Reference Include="System.Core">
|
||||
<RequiredTargetFramework>3.5</RequiredTargetFramework>
|
||||
</Reference>
|
||||
|
@ -49,8 +49,6 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Lucene", "..\Orchard.Web\Mo
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Orchard.Packaging", "..\Orchard.Web\Modules\Orchard.Packaging\Orchard.Packaging.csproj", "{DFD137A2-DDB5-4D22-BE0D-FA9AD4C8B059}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Orchard.Experimental", "..\Orchard.Web\Modules\Orchard.Experimental\Orchard.Experimental.csproj", "{AB3C207C-0126-4143-8D62-1119DF80D366}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Orchard.CodeGeneration", "..\Orchard.Web\Modules\Orchard.CodeGeneration\Orchard.CodeGeneration.csproj", "{C0C45321-B51D-4D8D-9B7B-AA4C2E0B2962}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Orchard.ArchiveLater", "..\Orchard.Web\Modules\Orchard.ArchiveLater\Orchard.ArchiveLater.csproj", "{1C981BB3-26F7-494C-9005-CC27A5144233}"
|
||||
@ -107,6 +105,12 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Orchard.Projections", "..\O
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UpgradeTo14", "..\Orchard.Web\Modules\UpgradeTo14\UpgradeTo14.csproj", "{8A9FDB57-342D-49C2-BAFC-D885AAE5CC7C}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Orchard.AntiSpam", "..\Orchard.Web\Modules\Orchard.AntiSpam\Orchard.AntiSpam.csproj", "{91BC2E7F-DA04-421C-98EF-76D37CEC130C}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Orchard.ContentPermissions", "..\Orchard.Web\Modules\Orchard.ContentPermissions\Orchard.ContentPermissions.csproj", "{E826F796-8CE3-4B5B-8423-5AA5F81D2FC3}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Orchard.CustomForms", "..\Orchard.Web\Modules\Orchard.CustomForms\Orchard.CustomForms.csproj", "{2CF067CA-064B-43C6-8B88-5E3B99A65F1D}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
@ -201,10 +205,6 @@ Global
|
||||
{DFD137A2-DDB5-4D22-BE0D-FA9AD4C8B059}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{DFD137A2-DDB5-4D22-BE0D-FA9AD4C8B059}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{DFD137A2-DDB5-4D22-BE0D-FA9AD4C8B059}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{AB3C207C-0126-4143-8D62-1119DF80D366}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{AB3C207C-0126-4143-8D62-1119DF80D366}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{AB3C207C-0126-4143-8D62-1119DF80D366}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{AB3C207C-0126-4143-8D62-1119DF80D366}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{C0C45321-B51D-4D8D-9B7B-AA4C2E0B2962}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{C0C45321-B51D-4D8D-9B7B-AA4C2E0B2962}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{C0C45321-B51D-4D8D-9B7B-AA4C2E0B2962}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
@ -313,6 +313,18 @@ Global
|
||||
{8A9FDB57-342D-49C2-BAFC-D885AAE5CC7C}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{8A9FDB57-342D-49C2-BAFC-D885AAE5CC7C}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{8A9FDB57-342D-49C2-BAFC-D885AAE5CC7C}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{91BC2E7F-DA04-421C-98EF-76D37CEC130C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{91BC2E7F-DA04-421C-98EF-76D37CEC130C}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{91BC2E7F-DA04-421C-98EF-76D37CEC130C}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{91BC2E7F-DA04-421C-98EF-76D37CEC130C}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{E826F796-8CE3-4B5B-8423-5AA5F81D2FC3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{E826F796-8CE3-4B5B-8423-5AA5F81D2FC3}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{E826F796-8CE3-4B5B-8423-5AA5F81D2FC3}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{E826F796-8CE3-4B5B-8423-5AA5F81D2FC3}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{2CF067CA-064B-43C6-8B88-5E3B99A65F1D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{2CF067CA-064B-43C6-8B88-5E3B99A65F1D}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{2CF067CA-064B-43C6-8B88-5E3B99A65F1D}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{2CF067CA-064B-43C6-8B88-5E3B99A65F1D}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
@ -334,7 +346,6 @@ Global
|
||||
{954CA994-D204-468B-9D69-51F6AD3E1C29} = {8E3DE014-9B28-4B32-8AC1-B2BE404E9B2D}
|
||||
{D5D447D7-EF8E-43A6-B9A4-3B025DD9F45D} = {8E3DE014-9B28-4B32-8AC1-B2BE404E9B2D}
|
||||
{DFD137A2-DDB5-4D22-BE0D-FA9AD4C8B059} = {8E3DE014-9B28-4B32-8AC1-B2BE404E9B2D}
|
||||
{AB3C207C-0126-4143-8D62-1119DF80D366} = {8E3DE014-9B28-4B32-8AC1-B2BE404E9B2D}
|
||||
{C0C45321-B51D-4D8D-9B7B-AA4C2E0B2962} = {8E3DE014-9B28-4B32-8AC1-B2BE404E9B2D}
|
||||
{1C981BB3-26F7-494C-9005-CC27A5144233} = {8E3DE014-9B28-4B32-8AC1-B2BE404E9B2D}
|
||||
{05660F47-D649-48BD-9DED-DF4E01E7CFF9} = {8E3DE014-9B28-4B32-8AC1-B2BE404E9B2D}
|
||||
@ -361,6 +372,9 @@ Global
|
||||
{3787DDE5-E5C8-4841-BDA7-DCB325388064} = {8E3DE014-9B28-4B32-8AC1-B2BE404E9B2D}
|
||||
{5531E894-D259-45A3-AA61-26DBE720C1CE} = {8E3DE014-9B28-4B32-8AC1-B2BE404E9B2D}
|
||||
{8A9FDB57-342D-49C2-BAFC-D885AAE5CC7C} = {8E3DE014-9B28-4B32-8AC1-B2BE404E9B2D}
|
||||
{91BC2E7F-DA04-421C-98EF-76D37CEC130C} = {8E3DE014-9B28-4B32-8AC1-B2BE404E9B2D}
|
||||
{E826F796-8CE3-4B5B-8423-5AA5F81D2FC3} = {8E3DE014-9B28-4B32-8AC1-B2BE404E9B2D}
|
||||
{2CF067CA-064B-43C6-8B88-5E3B99A65F1D} = {8E3DE014-9B28-4B32-8AC1-B2BE404E9B2D}
|
||||
{33B1BC8D-E292-4972-A363-22056B207156} = {75E7476C-C05B-4C41-8E38-081D3EB55659}
|
||||
{CB70A642-8CEC-4DDE-8C9F-AD08900EC98D} = {84650275-884D-4CBB-9CC0-67553996E211}
|
||||
EndGlobalSection
|
||||
|
@ -232,13 +232,35 @@ namespace Orchard.Core.Tests.Common.Providers {
|
||||
|
||||
_container.Resolve<DefaultShapeTableManagerTests.TestShapeProvider>().Discover =
|
||||
b => b.Describe("Parts_Common_Owner_Edit").From(TestFeature())
|
||||
.Placement(ShapePlacementParsingStrategy.BuildPredicate(c => true, new KeyValuePair<string, string>("Path", "~/yadda")), new PlacementInfo { Location = "Match" });
|
||||
.Placement(ctx => new PlacementInfo { Location = "Content" });
|
||||
|
||||
contentManager.UpdateEditor(item.ContentItem, updater);
|
||||
|
||||
Assert.That(updater.ModelErrors.ContainsKey("OwnerEditor.Owner"), Is.True);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void PublishingShouldNotFailIfOwnerIsEmptyAndShapeIsHidden() {
|
||||
var contentManager = _container.Resolve<IContentManager>();
|
||||
|
||||
var item = contentManager.Create<ICommonPart>("test-item", VersionOptions.Draft, init => { });
|
||||
|
||||
var user = contentManager.New<IUser>("User");
|
||||
_authn.Setup(x => x.GetAuthenticatedUser()).Returns(user);
|
||||
_authz.Setup(x => x.TryCheckAccess(StandardPermissions.SiteOwner, user, item)).Returns(true);
|
||||
|
||||
item.Owner = user;
|
||||
|
||||
var updater = new UpdatModelStub() { Owner = "" };
|
||||
|
||||
_container.Resolve<DefaultShapeTableManagerTests.TestShapeProvider>().Discover =
|
||||
b => b.Describe("Parts_Common_Owner_Edit").From(TestFeature())
|
||||
.Placement(ctx => new PlacementInfo { Location = "-" });
|
||||
|
||||
contentManager.UpdateEditor(item.ContentItem, updater);
|
||||
|
||||
Assert.That(updater.ModelErrors.ContainsKey("OwnerEditor.Owner"), Is.False);
|
||||
}
|
||||
[Test]
|
||||
public void CreatingShouldSetCreatedAndModifiedUtc() {
|
||||
var contentManager = _container.Resolve<IContentManager>();
|
||||
|
@ -8,7 +8,6 @@ From the base of the checkout, execute
|
||||
|
||||
* the ./orchard.proj creates an orchard web site at ./build/Profiling
|
||||
* the ./src/Orchard.Profile/profiling-setup-commands.txt holds the additional orchard.exe steps used to initialize
|
||||
* the ./src/Orchard.Experimental/Commands/ProfilingCommands.cs holds an additional handful of steps to populate items
|
||||
|
||||
The localhost:80 web server should be pointed to the ./build/Profiling folder at this point
|
||||
The "admin" password is "profiling-secret" without quotes
|
||||
|
@ -1 +1 @@
|
||||
setup /SiteName:Profiling /AdminUsername:admin /AdminPassword:profiling-secret /DatabaseProvider:SQLServer /DatabaseConnectionString:"Data Source=.;Initial Catalog=Orchard;Integrated Security=True" /EnabledFeatures:Profiling,Orchard.Framework,Common,Containers,Contents,Dashboard,Feeds,Navigation,Reports,Scheduling,Settings,Shapes,Title,PackagingServices,Gallery,Orchard.PublishLater,Orchard.Blogs,Orchard.Comments,Orchard.ContentTypes,Orchard.jQuery,Orchard.Lists,Orchard.Media,Orchard.MediaPicker,Orchard.Modules,Orchard.Packaging,Orchard.Pages,Orchard.Recipes,Orchard.Roles,Orchard.Tags,Orchard.Themes,Orchard.Users,Orchard.Scripting,Orchard.Scripting.Lightweight,Orchard.Widgets,TinyMce,TheThemeMachine,Orchard.Tokens,Orchard.Alias,Orchard.Autoroute
|
||||
setup /SiteName:Profiling /AdminUsername:admin /AdminPassword:profiling-secret /DatabaseProvider:SQLServer /DatabaseConnectionString:"Data Source=.;Initial Catalog=Orchard;Integrated Security=True" /EnabledFeatures:Profiling,Orchard.Framework,Common,Containers,Contents,Dashboard,Feeds,Navigation,Reports,Scheduling,Settings,Shapes,Title,PackagingServices,Gallery,Orchard.PublishLater,Orchard.Blogs,Orchard.Comments,Orchard.ContentTypes,Orchard.jQuery,Orchard.Lists,Orchard.Media,Orchard.ContentPicker,Orchard.MediaPicker,Orchard.Modules,Orchard.Packaging,Orchard.Pages,Orchard.Recipes,Orchard.Roles,Orchard.Tags,Orchard.Themes,Orchard.Users,Orchard.Scripting,Orchard.Scripting.Lightweight,Orchard.Widgets,TinyMce,TheThemeMachine,Orchard.Tokens,Orchard.Alias,Orchard.Autoroute
|
||||
|
@ -23,7 +23,7 @@ namespace Orchard.Specs.Bindings {
|
||||
webApp.GivenIHaveACleanSiteWith(
|
||||
virtualDirectory,
|
||||
TableData(
|
||||
new { extension = "Module", names = "Orchard.Setup, Orchard.Pages, Orchard.Blogs, Orchard.Messaging, Orchard.Media, Orchard.MediaPicker, Orchard.Modules, Orchard.Packaging, Orchard.PublishLater, Orchard.Themes, Orchard.Scripting, Orchard.Widgets, Orchard.Users, Orchard.ContentTypes, Orchard.Roles, Orchard.Comments, Orchard.jQuery, Orchard.Tags, TinyMce, Orchard.Packaging, Orchard.Recipes, Orchard.Warmup, Orchard.Alias, Orchard.Forms, Orchard.Tokens, Orchard.Autoroute, Orchard.Projections, Orchard.Fields" },
|
||||
new { extension = "Module", names = "Orchard.Setup, Orchard.Pages, Orchard.Blogs, Orchard.Messaging, Orchard.Media, Orchard.MediaPicker, Orchard.ContentPicker, Orchard.Modules, Orchard.Packaging, Orchard.PublishLater, Orchard.Themes, Orchard.Scripting, Orchard.Widgets, Orchard.Users, Orchard.ContentTypes, Orchard.Roles, Orchard.Comments, Orchard.jQuery, Orchard.Tags, TinyMce, Orchard.Packaging, Orchard.Recipes, Orchard.Warmup, Orchard.Alias, Orchard.Forms, Orchard.Tokens, Orchard.Autoroute, Orchard.Projections, Orchard.Fields" },
|
||||
new { extension = "Core", names = "Common, Containers, Dashboard, Feeds, Navigation, Contents, Scheduling, Settings, Shapes, XmlRpc, Title" },
|
||||
new { extension = "Theme", names = "SafeMode, TheAdmin, TheThemeMachine" }));
|
||||
|
||||
|
@ -39,7 +39,7 @@ Scenario: Some of the initial form values are required
|
||||
Scenario: Calling setup on a brand new install
|
||||
Given I have a clean site with
|
||||
| extension | names |
|
||||
| Module | Orchard.Setup, Orchard.Pages, Orchard.Blogs, Orchard.Messaging, Orchard.Media, Orchard.MediaPicker, Orchard.Modules, Orchard.Packaging, Orchard.PublishLater, Orchard.Themes, Orchard.Scripting, Orchard.Widgets, Orchard.Users, Orchard.ContentTypes, Orchard.Roles, Orchard.Comments, Orchard.jQuery, Orchard.Tags, TinyMce, Orchard.Packaging, Orchard.Recipes, Orchard.Warmup, Orchard.Alias, Orchard.Forms, Orchard.Tokens, Orchard.Autoroute, Orchard.Projections, Orchard.Fields |
|
||||
| Module | Orchard.Setup, Orchard.Pages, Orchard.Blogs, Orchard.Messaging, Orchard.Media, Orchard.MediaPicker, Orchard.ContentPicker, Orchard.Modules, Orchard.Packaging, Orchard.PublishLater, Orchard.Themes, Orchard.Scripting, Orchard.Widgets, Orchard.Users, Orchard.ContentTypes, Orchard.Roles, Orchard.Comments, Orchard.jQuery, Orchard.Tags, TinyMce, Orchard.Packaging, Orchard.Recipes, Orchard.Warmup, Orchard.Alias, Orchard.Forms, Orchard.Tokens, Orchard.Autoroute, Orchard.Projections, Orchard.Fields |
|
||||
| Core | Common, Containers, Dashboard, Feeds, Navigation, Contents, Scheduling, Settings, Shapes, XmlRpc, Title |
|
||||
| Theme | SafeMode, TheAdmin, TheThemeMachine |
|
||||
And I am on "/Setup"
|
||||
|
4
src/Orchard.Specs/Setup.feature.cs
generated
4
src/Orchard.Specs/Setup.feature.cs
generated
@ -3,7 +3,7 @@
|
||||
// This code was generated by SpecFlow (http://www.specflow.org/).
|
||||
// SpecFlow Version:1.8.1.0
|
||||
// SpecFlow Generator Version:1.8.0.0
|
||||
// Runtime Version:4.0.30319.239
|
||||
// Runtime Version:4.0.30319.269
|
||||
//
|
||||
// Changes to this file may cause incorrect behavior and will be lost if
|
||||
// the code is regenerated.
|
||||
@ -188,7 +188,7 @@ this.ScenarioSetup(scenarioInfo);
|
||||
"names"});
|
||||
table4.AddRow(new string[] {
|
||||
"Module",
|
||||
@"Orchard.Setup, Orchard.Pages, Orchard.Blogs, Orchard.Messaging, Orchard.Media, Orchard.MediaPicker, Orchard.Modules, Orchard.Packaging, Orchard.PublishLater, Orchard.Themes, Orchard.Scripting, Orchard.Widgets, Orchard.Users, Orchard.ContentTypes, Orchard.Roles, Orchard.Comments, Orchard.jQuery, Orchard.Tags, TinyMce, Orchard.Packaging, Orchard.Recipes, Orchard.Warmup, Orchard.Alias, Orchard.Forms, Orchard.Tokens, Orchard.Autoroute, Orchard.Projections, Orchard.Fields"});
|
||||
@"Orchard.Setup, Orchard.Pages, Orchard.Blogs, Orchard.Messaging, Orchard.Media, Orchard.MediaPicker, Orchard.ContentPicker, Orchard.Modules, Orchard.Packaging, Orchard.PublishLater, Orchard.Themes, Orchard.Scripting, Orchard.Widgets, Orchard.Users, Orchard.ContentTypes, Orchard.Roles, Orchard.Comments, Orchard.jQuery, Orchard.Tags, TinyMce, Orchard.Packaging, Orchard.Recipes, Orchard.Warmup, Orchard.Alias, Orchard.Forms, Orchard.Tokens, Orchard.Autoroute, Orchard.Projections, Orchard.Fields"});
|
||||
table4.AddRow(new string[] {
|
||||
"Core",
|
||||
"Common, Containers, Dashboard, Feeds, Navigation, Contents, Scheduling, Settings," +
|
||||
|
@ -92,14 +92,14 @@ namespace Orchard.Tests.Modules.ImportExport.Services {
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ImportFailsWhenRecipeContainsNonImportSteps() {
|
||||
Assert.Throws(typeof(InvalidOperationException), () => _importExportService.Import(
|
||||
@"<Orchard>
|
||||
<Recipe>
|
||||
<Name>MyModuleInstaller</Name>
|
||||
</Recipe>
|
||||
<Module name=""MyModule"" />
|
||||
</Orchard>"));
|
||||
public void ImportDoesntFailsWhenRecipeContainsNonImportSteps() {
|
||||
Assert.DoesNotThrow(() => _importExportService.Import(
|
||||
@"<Orchard>
|
||||
<Recipe>
|
||||
<Name>MyModuleInstaller</Name>
|
||||
</Recipe>
|
||||
<Module name=""MyModule"" />
|
||||
</Orchard>"));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using NHibernate;
|
||||
@ -200,6 +201,14 @@ namespace Orchard.Tests.Data {
|
||||
Assert.That(two.Name, Is.EqualTo("two"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void StoringDateTimeDoesntRemovePrecision() {
|
||||
_fooRepos.Create(new FooRecord { Name = "one", Timespan = DateTime.Parse("2001-01-01 16:28:21.489", CultureInfo.InvariantCulture) });
|
||||
|
||||
var one = _fooRepos.Fetch(f => f.Name == "one").Single();
|
||||
|
||||
Assert.That(one.Name, Is.EqualTo("one"));
|
||||
Assert.That(one.Timespan.Value.Millisecond, Is.EqualTo(489));
|
||||
}
|
||||
}
|
||||
}
|
@ -112,7 +112,7 @@ namespace Orchard.Tests.Environment {
|
||||
public void PathAlsoCausesMatch() {
|
||||
var table = (IRunningShellTable)new RunningShellTable();
|
||||
var settings = new ShellSettings { Name = ShellSettings.DefaultName };
|
||||
var settingsA = new ShellSettings { Name = "Alpha", RequestUrlPrefix = "~/foo" };
|
||||
var settingsA = new ShellSettings { Name = "Alpha", RequestUrlPrefix = "foo" };
|
||||
table.Add(settings);
|
||||
table.Add(settingsA);
|
||||
var match = table.Match(new StubHttpContext("~/foo/bar", "a.example.com"));
|
||||
@ -123,10 +123,10 @@ namespace Orchard.Tests.Environment {
|
||||
public void PathAndHostMustBothMatch() {
|
||||
var table = (IRunningShellTable)new RunningShellTable();
|
||||
var settings = new ShellSettings { Name = ShellSettings.DefaultName, RequestUrlHost = "www.example.com", };
|
||||
var settingsA = new ShellSettings { Name = "Alpha", RequestUrlHost = "wiki.example.com", RequestUrlPrefix = "~/foo" };
|
||||
var settingsB = new ShellSettings { Name = "Beta", RequestUrlHost = "wiki.example.com", RequestUrlPrefix = "~/bar" };
|
||||
var settingsA = new ShellSettings { Name = "Alpha", RequestUrlHost = "wiki.example.com", RequestUrlPrefix = "foo" };
|
||||
var settingsB = new ShellSettings { Name = "Beta", RequestUrlHost = "wiki.example.com", RequestUrlPrefix = "bar" };
|
||||
var settingsG = new ShellSettings { Name = "Gamma", RequestUrlHost = "wiki.example.com" };
|
||||
var settingsD = new ShellSettings { Name = "Delta", RequestUrlPrefix = "~/Quux" };
|
||||
var settingsD = new ShellSettings { Name = "Delta", RequestUrlPrefix = "Quux" };
|
||||
table.Add(settings);
|
||||
table.Add(settingsA);
|
||||
table.Add(settingsB);
|
||||
@ -152,7 +152,7 @@ namespace Orchard.Tests.Environment {
|
||||
[Test]
|
||||
public void PathAloneWillMatch() {
|
||||
var table = (IRunningShellTable)new RunningShellTable();
|
||||
var settingsA = new ShellSettings { Name = "Alpha", RequestUrlPrefix = "~/foo" };
|
||||
var settingsA = new ShellSettings { Name = "Alpha", RequestUrlPrefix = "foo" };
|
||||
table.Add(settingsA);
|
||||
|
||||
Assert.That(table.Match(new StubHttpContext("~/foo/bar", "wiki.example.com")), Is.EqualTo(settingsA).Using(new ShellComparer()));
|
||||
|
@ -1,6 +1,9 @@
|
||||
using System;
|
||||
|
||||
namespace Orchard.Tests.Records {
|
||||
public class FooRecord {
|
||||
public virtual int Id { get; set; }
|
||||
public virtual string Name { get; set; }
|
||||
public virtual DateTime? Timespan { get; set; }
|
||||
}
|
||||
}
|
@ -135,11 +135,11 @@ namespace Orchard.Tests.UI.Navigation {
|
||||
base(navigationManager, workContextAccessor, shapeFactory) {}
|
||||
|
||||
public static Stack<MenuItem> FindSelectedPathAccessor(IEnumerable<MenuItem> menuItems, RouteData currentRouteData) {
|
||||
return SetSelectedPath(menuItems, currentRouteData);
|
||||
return NavigationHelper.SetSelectedPath(menuItems, currentRouteData);
|
||||
}
|
||||
|
||||
public static MenuItem FindParentLocalTaskAccessor(Stack<MenuItem> selectedPath) {
|
||||
return FindParentLocalTask(selectedPath);
|
||||
return NavigationHelper.FindParentLocalTask(selectedPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -18,7 +18,7 @@ namespace Orchard.Tests.UI.Navigation {
|
||||
public class NavigationManagerTests {
|
||||
[Test]
|
||||
public void EmptyMenuIfNameDoesntMatch() {
|
||||
var manager = new NavigationManager(new[] { new StubProvider() }, new StubAuth(), new UrlHelper(new RequestContext(new StubHttpContext("~/"), new RouteData())), new StubOrchardServices());
|
||||
var manager = new NavigationManager(new[] { new StubProvider() }, new IMenuProvider[] { }, new StubAuth(), new INavigationFilter[0], new UrlHelper(new RequestContext(new StubHttpContext("~/"), new RouteData())), new StubOrchardServices());
|
||||
|
||||
var menuItems = manager.BuildMenu("primary");
|
||||
Assert.That(menuItems.Count(), Is.EqualTo(0));
|
||||
@ -35,7 +35,7 @@ namespace Orchard.Tests.UI.Navigation {
|
||||
|
||||
[Test]
|
||||
public void NavigationManagerShouldUseProvidersToBuildNamedMenu() {
|
||||
var manager = new NavigationManager(new[] { new StubProvider() }, new StubAuth(), new UrlHelper(new RequestContext(new StubHttpContext("~/"), new RouteData())), new StubOrchardServices());
|
||||
var manager = new NavigationManager(new[] { new StubProvider() }, new IMenuProvider[] { }, new StubAuth(), new INavigationFilter[0], new UrlHelper(new RequestContext(new StubHttpContext("~/"), new RouteData())), new StubOrchardServices());
|
||||
|
||||
var menuItems = manager.BuildMenu("admin");
|
||||
Assert.That(menuItems.Count(), Is.EqualTo(2));
|
||||
@ -47,7 +47,7 @@ namespace Orchard.Tests.UI.Navigation {
|
||||
|
||||
[Test]
|
||||
public void NavigationManagerShouldCatchProviderErrors() {
|
||||
var manager = new NavigationManager(new[] { new BrokenProvider() }, new StubAuth(), new UrlHelper(new RequestContext(new StubHttpContext("~/"), new RouteData())), new StubOrchardServices());
|
||||
var manager = new NavigationManager(new[] { new BrokenProvider() }, new IMenuProvider[] { }, new StubAuth(), new INavigationFilter[0], new UrlHelper(new RequestContext(new StubHttpContext("~/"), new RouteData())), new StubOrchardServices());
|
||||
|
||||
var menuItems = manager.BuildMenu("admin");
|
||||
Assert.That(menuItems.Count(), Is.EqualTo(0));
|
||||
@ -55,7 +55,7 @@ namespace Orchard.Tests.UI.Navigation {
|
||||
|
||||
[Test]
|
||||
public void NavigationManagerShouldMergeAndOrderNavigation() {
|
||||
var manager = new NavigationManager(new INavigationProvider[] { new StubProvider(), new Stub2Provider() }, new StubAuth(), new UrlHelper(new RequestContext(new StubHttpContext("~/"), new RouteData())), new StubOrchardServices());
|
||||
var manager = new NavigationManager(new INavigationProvider[] { new StubProvider(), new Stub2Provider() }, new IMenuProvider[] { }, new StubAuth(), new INavigationFilter[0], new UrlHelper(new RequestContext(new StubHttpContext("~/"), new RouteData())), new StubOrchardServices());
|
||||
|
||||
var menuItems = manager.BuildMenu("admin");
|
||||
Assert.That(menuItems.Count(), Is.EqualTo(3));
|
||||
|
@ -54,7 +54,9 @@
|
||||
<staticLogFileName value="false" />
|
||||
<rollingStyle value="Date" />
|
||||
<datepattern value="-yyyy.MM.dd'.log'" />
|
||||
|
||||
<!-- prevent orchard.exe from displaying locking debug messages -->
|
||||
<lockingModel type="log4net.Appender.FileAppender+MinimalLock" />
|
||||
|
||||
<layout type="log4net.Layout.PatternLayout">
|
||||
<conversionPattern value="%date [%thread] %logger - %message%newline" />
|
||||
</layout>
|
||||
@ -73,6 +75,9 @@
|
||||
<rollingStyle value="Date" />
|
||||
<datepattern value="-yyyy.MM.dd'.log'" />
|
||||
|
||||
<!-- prevent orchard.exe from displaying locking error messages -->
|
||||
<lockingModel type="log4net.Appender.FileAppender+MinimalLock" />
|
||||
|
||||
<filter type="log4net.Filter.LevelRangeFilter">
|
||||
<!-- only error and fatal messages end up in this target, even if child loggers accept lower priority -->
|
||||
<levelMin value="ERROR" />
|
||||
|
@ -84,6 +84,10 @@ namespace Orchard.Core.Common.Drivers {
|
||||
var contentIdentity = new ContentIdentity(owner);
|
||||
part.Owner = _membershipService.GetUser(contentIdentity.Get("User.UserName"));
|
||||
}
|
||||
// use the super user if the referenced one doesn't exist
|
||||
else {
|
||||
part.Owner = _membershipService.GetUser(Services.WorkContext.CurrentSite.SuperUser);
|
||||
}
|
||||
|
||||
var container = context.Attribute(part.PartDefinition.Name, "Container");
|
||||
if (container != null) {
|
||||
|
@ -39,10 +39,8 @@ namespace Orchard.Core.Common.Drivers {
|
||||
var settings = field.PartFieldDefinition.Settings.GetModel<TextFieldSettings>();
|
||||
object fieldValue = field.Value;
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(settings.Flavor)) {
|
||||
fieldValue = new HtmlString(_htmlFilters.Aggregate(field.Value, (text, filter) => filter.ProcessContent(text, settings.Flavor)));
|
||||
}
|
||||
|
||||
fieldValue = new HtmlString(_htmlFilters.Aggregate(field.Value, (text, filter) => filter.ProcessContent(text, settings.Flavor)));
|
||||
|
||||
return shapeHelper.Fields_Common_Text(Name: field.Name, Value: fieldValue);
|
||||
});
|
||||
}
|
||||
|
@ -2,8 +2,8 @@
|
||||
AntiForgery: enabled
|
||||
Author: The Orchard Team
|
||||
Website: http://orchardproject.net
|
||||
Version: 1.4.2
|
||||
OrchardVersion: 1.4.2
|
||||
Version: 1.5
|
||||
OrchardVersion: 1.5
|
||||
Description: The common module introduces content parts that are going to be used by most content types (common, body, identity).
|
||||
FeatureDescription: Core content parts.
|
||||
Dependencies: Settings
|
||||
|
@ -1,7 +1,7 @@
|
||||
@model Orchard.Core.Common.ViewModels.TextFieldDriverViewModel
|
||||
|
||||
<fieldset>
|
||||
<label for="@Html.FieldIdFor(m => m.Text)">@Model.Field.DisplayName</label>
|
||||
<label for="@Html.FieldIdFor(m => m.Text)" @if(Model.Settings.Required) { <text>class="required"</text> }>@Model.Field.DisplayName</label>
|
||||
@if (String.IsNullOrWhiteSpace(Model.Settings.Flavor)) {
|
||||
@Html.TextBoxFor(m => m.Text, new { @class = "text" })
|
||||
@Html.ValidationMessageFor(m => m.Text)
|
||||
|
@ -1,7 +1,8 @@
|
||||
@{
|
||||
@using Orchard.Utility.Extensions;
|
||||
@{
|
||||
string name = Model.ContentField.DisplayName;
|
||||
}
|
||||
|
||||
@if (HasText(name) && HasText(Model.Value)) {
|
||||
<p class="text-field"><span class="name">@name:</span> <span class="value">@Model.Value</span></p>
|
||||
<p class="text-field"><span class="name">@name:</span> <span class="value">@(new MvcHtmlString(Html.Encode((HtmlString) Model.Value).ReplaceNewLinesWith("<br />$1")))</span></p>
|
||||
}
|
@ -7,6 +7,7 @@ using Orchard.Core.Common.Models;
|
||||
using Orchard.Core.Containers.Models;
|
||||
using Orchard.Core.Containers.ViewModels;
|
||||
using Orchard.Localization;
|
||||
using Orchard.ContentManagement.Handlers;
|
||||
|
||||
namespace Orchard.Core.Containers.Drivers {
|
||||
public class ContainablePartDriver : ContentPartDriver<ContainablePart> {
|
||||
@ -40,7 +41,7 @@ namespace Orchard.Core.Containers.Drivers {
|
||||
if (oldContainerId != model.ContainerId) {
|
||||
if (commonPart != null) {
|
||||
var containerItem = _contentManager.Get(model.ContainerId, VersionOptions.Latest);
|
||||
commonPart.Record.Container = containerItem == null ? null : containerItem.Record;
|
||||
commonPart.Container = containerItem;
|
||||
}
|
||||
}
|
||||
part.Weight = model.Weight;
|
||||
@ -65,5 +66,15 @@ namespace Orchard.Core.Containers.Drivers {
|
||||
});
|
||||
}
|
||||
|
||||
protected override void Importing(ContainablePart part, ImportContentContext context) {
|
||||
var weight = context.Attribute(part.PartDefinition.Name, "Weight");
|
||||
if (weight != null) {
|
||||
part.Weight = Convert.ToInt32(weight);
|
||||
}
|
||||
}
|
||||
|
||||
protected override void Exporting(ContainablePart part, ExportContentContext context) {
|
||||
context.Element(part.PartDefinition.Name).SetAttributeValue("Weight", part.Weight);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -10,13 +10,11 @@ using Orchard.Core.Containers.Models;
|
||||
using Orchard.Core.Containers.ViewModels;
|
||||
using Orchard.Localization;
|
||||
using Orchard.UI.Notify;
|
||||
using Orchard.DisplayManagement;
|
||||
using Orchard.Core.Containers.Extensions;
|
||||
using System.Web.Routing;
|
||||
using Orchard.Settings;
|
||||
using Orchard.Core.Feeds;
|
||||
using Orchard.UI.Navigation;
|
||||
using Orchard.ContentManagement.Aspects;
|
||||
|
||||
namespace Orchard.Core.Containers.Drivers {
|
||||
public class ContainerPartDriver : ContentPartDriver<ContainerPart> {
|
||||
|
@ -6,5 +6,5 @@ Version: 1.4.2
|
||||
OrchardVersion: 1.4.2
|
||||
Description: The containers module introduces container and containable behaviors for content items.
|
||||
FeatureDescription: Container and containable parts to enable parent-child relationships between content items.
|
||||
Dependencies: Contents
|
||||
Dependencies: Contents, Feeds
|
||||
Category: Content
|
||||
|
@ -275,7 +275,7 @@ namespace Orchard.Core.Contents.Controllers {
|
||||
[HttpPost, ActionName("Edit")]
|
||||
[FormValueRequired("submit.Publish")]
|
||||
public ActionResult EditAndPublishPOST(int id, string returnUrl) {
|
||||
var content = _contentManager.Get(id, VersionOptions.DraftRequired);
|
||||
var content = _contentManager.Get(id, VersionOptions.Latest);
|
||||
|
||||
if (content == null)
|
||||
return HttpNotFound();
|
||||
|
@ -20,7 +20,7 @@ namespace Orchard.Core.Contents.Controllers {
|
||||
dynamic Shape { get; set; }
|
||||
public IOrchardServices Services { get; private set; }
|
||||
public Localizer T { get; set; }
|
||||
|
||||
|
||||
// /Contents/Item/Display/72
|
||||
public ActionResult Display(int id) {
|
||||
var contentItem = _contentManager.Get(id, VersionOptions.Published);
|
||||
@ -28,6 +28,10 @@ namespace Orchard.Core.Contents.Controllers {
|
||||
if (contentItem == null)
|
||||
return HttpNotFound();
|
||||
|
||||
if (!Services.Authorizer.Authorize(Permissions.ViewContent, contentItem, T("Cannot view content"))) {
|
||||
return new HttpUnauthorizedResult();
|
||||
}
|
||||
|
||||
dynamic model = _contentManager.BuildDisplay(contentItem);
|
||||
return new ShapeResult(this, model);
|
||||
}
|
||||
@ -41,12 +45,16 @@ namespace Orchard.Core.Contents.Controllers {
|
||||
versionOptions = VersionOptions.Number((int)version);
|
||||
|
||||
var contentItem = _contentManager.Get(id, versionOptions);
|
||||
|
||||
if (contentItem == null)
|
||||
return HttpNotFound();
|
||||
|
||||
if (!Services.Authorizer.Authorize(Permissions.EditContent, contentItem, T("Cannot preview content")))
|
||||
if (!Services.Authorizer.Authorize(Permissions.ViewContent, contentItem, T("Cannot preview content"))) {
|
||||
return new HttpUnauthorizedResult();
|
||||
}
|
||||
|
||||
if (!Services.Authorizer.Authorize(Permissions.EditContent, contentItem, T("Cannot preview content"))) {
|
||||
return new HttpUnauthorizedResult();
|
||||
}
|
||||
|
||||
dynamic model = _contentManager.BuildDisplay(contentItem);
|
||||
return new ShapeResult(this, model);
|
||||
|
@ -15,6 +15,8 @@ namespace Orchard.Core.Contents {
|
||||
private static readonly Permission EditOwnContent = new Permission { Description = "Edit {0}", Name = "EditOwn_{0}", ImpliedBy = new[] { EditContent, PublishOwnContent, Permissions.EditOwnContent } };
|
||||
private static readonly Permission DeleteContent = new Permission { Description = "Delete {0} for others", Name = "Delete_{0}", ImpliedBy = new[] { Permissions.DeleteContent } };
|
||||
private static readonly Permission DeleteOwnContent = new Permission { Description = "Delete {0}", Name = "DeleteOwn_{0}", ImpliedBy = new[] { DeleteContent, Permissions.DeleteOwnContent } };
|
||||
private static readonly Permission ViewContent = new Permission { Description = "View {0} by others", Name = "View_{0}", ImpliedBy = new[] { Permissions.EditContent } };
|
||||
private static readonly Permission ViewOwnContent = new Permission { Description = "View own {0}", Name = "ViewOwn_{0}", ImpliedBy = new[] { ViewContent, Permissions.ViewOwnContent } };
|
||||
|
||||
public static readonly Dictionary<string, Permission> PermissionTemplates = new Dictionary<string, Permission> {
|
||||
{Permissions.PublishContent.Name, PublishContent},
|
||||
@ -22,7 +24,9 @@ namespace Orchard.Core.Contents {
|
||||
{Permissions.EditContent.Name, EditContent},
|
||||
{Permissions.EditOwnContent.Name, EditOwnContent},
|
||||
{Permissions.DeleteContent.Name, DeleteContent},
|
||||
{Permissions.DeleteOwnContent.Name, DeleteOwnContent}
|
||||
{Permissions.DeleteOwnContent.Name, DeleteOwnContent},
|
||||
{Permissions.ViewContent.Name, ViewContent},
|
||||
{Permissions.ViewOwnContent.Name, ViewOwnContent}
|
||||
};
|
||||
|
||||
private readonly IContentDefinitionManager _contentDefinitionManager;
|
||||
@ -38,8 +42,8 @@ namespace Orchard.Core.Contents {
|
||||
var creatableTypes = _contentDefinitionManager.ListTypeDefinitions()
|
||||
.Where(ctd => ctd.Settings.GetModel<ContentTypeSettings>().Creatable);
|
||||
|
||||
foreach(var typeDefinition in creatableTypes) {
|
||||
foreach ( var permissionTemplate in PermissionTemplates.Values ) {
|
||||
foreach (var typeDefinition in creatableTypes) {
|
||||
foreach (var permissionTemplate in PermissionTemplates.Values) {
|
||||
yield return CreateDynamicPermission(permissionTemplate, typeDefinition);
|
||||
}
|
||||
}
|
||||
@ -53,7 +57,7 @@ namespace Orchard.Core.Contents {
|
||||
/// Returns a dynamic permission for a content type, based on a global content permission template
|
||||
/// </summary>
|
||||
public static Permission ConvertToDynamicPermission(Permission permission) {
|
||||
if (PermissionTemplates.ContainsKey(permission.Name) ) {
|
||||
if (PermissionTemplates.ContainsKey(permission.Name)) {
|
||||
return PermissionTemplates[permission.Name];
|
||||
}
|
||||
|
||||
@ -68,7 +72,7 @@ namespace Orchard.Core.Contents {
|
||||
Name = String.Format(template.Name, typeDefinition.Name),
|
||||
Description = String.Format(template.Description, typeDefinition.DisplayName),
|
||||
Category = typeDefinition.DisplayName,
|
||||
ImpliedBy = ( template.ImpliedBy ?? new Permission[0] ).Select(t => CreateDynamicPermission(t, typeDefinition))
|
||||
ImpliedBy = (template.ImpliedBy ?? new Permission[0]).Select(t => CreateDynamicPermission(t, typeDefinition))
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -2,8 +2,8 @@
|
||||
AntiForgery: enabled
|
||||
Author: The Orchard Team
|
||||
Website: http://orchardproject.net
|
||||
Version: 1.4.2
|
||||
OrchardVersion: 1.4.2
|
||||
Version: 1.5
|
||||
OrchardVersion: 1.5
|
||||
Description: The contents module enables the creation of custom content types.
|
||||
Features:
|
||||
Contents
|
||||
|
@ -14,19 +14,24 @@ namespace Orchard.Core.Contents {
|
||||
public static readonly Permission EditOwnContent = new Permission { Description = "Edit own content", Name = "EditOwnContent", ImpliedBy = new[] { EditContent, PublishOwnContent } };
|
||||
public static readonly Permission DeleteContent = new Permission { Description = "Delete content for others", Name = "DeleteContent" };
|
||||
public static readonly Permission DeleteOwnContent = new Permission { Description = "Delete own content", Name = "DeleteOwnContent", ImpliedBy = new[] { DeleteContent } };
|
||||
public static readonly Permission ViewContent = new Permission { Description = "View all content", Name = "ViewContent", ImpliedBy = new[] { EditContent } };
|
||||
public static readonly Permission ViewOwnContent = new Permission { Description = "View own content", Name = "ViewOwnContent", ImpliedBy = new[] { ViewContent } };
|
||||
|
||||
|
||||
public static readonly Permission MetaListContent = new Permission { ImpliedBy = new[] { EditOwnContent, PublishOwnContent, DeleteOwnContent } };
|
||||
|
||||
public virtual Feature Feature { get; set; }
|
||||
|
||||
public IEnumerable<Permission> GetPermissions() {
|
||||
return new [] {
|
||||
return new[] {
|
||||
EditOwnContent,
|
||||
EditContent,
|
||||
PublishOwnContent,
|
||||
PublishContent,
|
||||
DeleteOwnContent,
|
||||
DeleteContent,
|
||||
ViewContent,
|
||||
ViewOwnContent
|
||||
};
|
||||
}
|
||||
|
||||
@ -51,6 +56,14 @@ namespace Orchard.Core.Contents {
|
||||
Name = "Contributor",
|
||||
Permissions = new[] {EditOwnContent}
|
||||
},
|
||||
new PermissionStereotype {
|
||||
Name = "Authenticated",
|
||||
Permissions = new[] {ViewContent}
|
||||
},
|
||||
new PermissionStereotype {
|
||||
Name = "Anonymous",
|
||||
Permissions = new[] {ViewContent}
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -5,17 +5,15 @@ using Orchard.Core.Contents.Settings;
|
||||
using Orchard.Security;
|
||||
using Orchard.Security.Permissions;
|
||||
|
||||
namespace Orchard.Core.Contents.Security
|
||||
{
|
||||
namespace Orchard.Core.Contents.Security {
|
||||
[UsedImplicitly]
|
||||
public class AuthorizationEventHandler : IAuthorizationServiceEventHandler
|
||||
{
|
||||
public class AuthorizationEventHandler : IAuthorizationServiceEventHandler {
|
||||
public void Checking(CheckAccessContext context) { }
|
||||
public void Complete(CheckAccessContext context) { }
|
||||
|
||||
public void Adjust(CheckAccessContext context) {
|
||||
if ( !context.Granted &&
|
||||
context.Content.Is<ICommonPart>() ) {
|
||||
if (!context.Granted &&
|
||||
context.Content.Is<ICommonPart>()) {
|
||||
|
||||
if (OwnerVariationExists(context.Permission) &&
|
||||
HasOwnership(context.User, context.Content)) {
|
||||
@ -27,10 +25,10 @@ namespace Orchard.Core.Contents.Security
|
||||
var typeDefinition = context.Content.ContentItem.TypeDefinition;
|
||||
|
||||
// replace permission if a content type specific version exists
|
||||
if ( typeDefinition.Settings.GetModel<ContentTypeSettings>().Creatable ) {
|
||||
if (typeDefinition.Settings.GetModel<ContentTypeSettings>().Creatable) {
|
||||
var permission = GetContentTypeVariation(context.Permission);
|
||||
|
||||
if ( permission != null) {
|
||||
if (permission != null) {
|
||||
context.Adjusted = true;
|
||||
context.Permission = DynamicPermissions.CreateDynamicPermission(permission, typeDefinition);
|
||||
}
|
||||
@ -60,6 +58,8 @@ namespace Orchard.Core.Contents.Security
|
||||
return Permissions.EditOwnContent;
|
||||
if (permission.Name == Permissions.DeleteContent.Name)
|
||||
return Permissions.DeleteOwnContent;
|
||||
if (permission.Name == Permissions.ViewContent.Name)
|
||||
return Permissions.ViewOwnContent;
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -8,5 +8,9 @@
|
||||
/// Used to determine if this content type supports draft versions
|
||||
/// </summary>
|
||||
public bool Draftable { get; set; }
|
||||
/// <summary>
|
||||
/// Defines the stereotype of the type
|
||||
/// </summary>
|
||||
public string Stereotype { get; set; }
|
||||
}
|
||||
}
|
@ -2,8 +2,8 @@
|
||||
AntiForgery: enabled
|
||||
Author: The Orchard Team
|
||||
Website: http://orchardproject.net
|
||||
Version: 1.4.2
|
||||
OrchardVersion: 1.4.2
|
||||
Version: 1.5
|
||||
OrchardVersion: 1.5
|
||||
Description: The dashboard module is providing the dashboard screen of the admininstration UI of the application.
|
||||
FeatureDescription: Standard admin dashboard.
|
||||
Category: Core
|
||||
|
@ -2,8 +2,8 @@
|
||||
AntiForgery: enabled
|
||||
Author: The Orchard Team
|
||||
Website: http://orchardproject.net
|
||||
Version: 1.4.2
|
||||
OrchardVersion: 1.4.2
|
||||
Version: 1.5
|
||||
OrchardVersion: 1.5
|
||||
Description: The Feeds module is providing RSS feeds to content items.
|
||||
FeatureDescription: RSS feeds for content items.
|
||||
Category: Syndication
|
||||
|
@ -1,13 +1,18 @@
|
||||
using Orchard.Commands;
|
||||
using System.Linq;
|
||||
using Orchard.Commands;
|
||||
using Orchard.ContentManagement;
|
||||
using Orchard.Core.Navigation.Models;
|
||||
using Orchard.Core.Navigation.Services;
|
||||
using Orchard.Core.Title.Models;
|
||||
|
||||
namespace Orchard.Core.Navigation.Commands {
|
||||
public class MenuCommands : DefaultOrchardCommandHandler {
|
||||
private readonly IContentManager _contentManager;
|
||||
private readonly IMenuService _menuService;
|
||||
|
||||
public MenuCommands(IContentManager contentManager) {
|
||||
public MenuCommands(IContentManager contentManager, IMenuService menuService) {
|
||||
_contentManager = contentManager;
|
||||
_menuService = menuService;
|
||||
}
|
||||
|
||||
[OrchardSwitch]
|
||||
@ -20,19 +25,43 @@ namespace Orchard.Core.Navigation.Commands {
|
||||
public string Url { get; set; }
|
||||
|
||||
[OrchardSwitch]
|
||||
public bool OnMainMenu { get; set; }
|
||||
public string MenuName { get; set; }
|
||||
|
||||
[CommandName("menuitem create")]
|
||||
[CommandHelp("menuitem create /MenuPosition:<position> /MenuText:<text> /Url:<url> [/OnMainMenu:true|false]\r\n\t" + "Creates a new menu item")]
|
||||
[OrchardSwitches("MenuPosition,MenuText,Url,OnMainMenu")]
|
||||
[CommandHelp("menuitem create /MenuPosition:<position> /MenuText:<text> /Url:<url> /MenuName:<name>\r\n\t" + "Creates a new menu item")]
|
||||
[OrchardSwitches("MenuPosition,MenuText,Url,MenuName")]
|
||||
public void Create() {
|
||||
// flushes before doing a query in case a previous command created the menu
|
||||
_contentManager.Flush();
|
||||
|
||||
var menu = _menuService.GetMenu(MenuName);
|
||||
|
||||
if(menu == null) {
|
||||
Context.Output.WriteLine(T("Menu not found.").Text);
|
||||
return;
|
||||
}
|
||||
|
||||
var menuItem = _contentManager.Create("MenuItem");
|
||||
menuItem.As<MenuPart>().MenuPosition = MenuPosition;
|
||||
menuItem.As<MenuPart>().MenuText = T(MenuText).ToString();
|
||||
menuItem.As<MenuPart>().OnMainMenu = OnMainMenu;
|
||||
menuItem.As<MenuPart>().Menu = menu.ContentItem;
|
||||
menuItem.As<MenuItemPart>().Url = Url;
|
||||
|
||||
Context.Output.WriteLine(T("Menu item created successfully.").Text);
|
||||
}
|
||||
|
||||
[CommandName("menu create")]
|
||||
[CommandHelp("menu create /MenuName:<name>\r\n\t" + "Creates a new menu")]
|
||||
[OrchardSwitches("MenuName")]
|
||||
public void CreateMenu() {
|
||||
if (string.IsNullOrWhiteSpace(MenuName)) {
|
||||
Context.Output.WriteLine(T("Menu name can't be empty.").Text);
|
||||
return;
|
||||
}
|
||||
|
||||
_menuService.Create(MenuName);
|
||||
|
||||
Context.Output.WriteLine(T("Menu created successfully.").Text);
|
||||
}
|
||||
}
|
||||
}
|
@ -2,66 +2,91 @@
|
||||
using System.Linq;
|
||||
using System.Web.Mvc;
|
||||
using Orchard.ContentManagement;
|
||||
using Orchard.Core.Common.Models;
|
||||
using Orchard.Core.Navigation.Models;
|
||||
using Orchard.Core.Navigation.Services;
|
||||
using Orchard.Core.Navigation.ViewModels;
|
||||
using Orchard.DisplayManagement;
|
||||
using Orchard.Core.Title.Models;
|
||||
using Orchard.Localization;
|
||||
using Orchard.Mvc.AntiForgery;
|
||||
using Orchard.Mvc.Extensions;
|
||||
using Orchard.UI;
|
||||
using Orchard.UI.Notify;
|
||||
using Orchard.UI.Navigation;
|
||||
using Orchard.Utility;
|
||||
using System;
|
||||
using Orchard.Logging;
|
||||
|
||||
namespace Orchard.Core.Navigation.Controllers {
|
||||
[ValidateInput(false)]
|
||||
public class AdminController : Controller, IUpdateModel {
|
||||
private readonly IMenuService _menuService;
|
||||
private readonly IOrchardServices _services;
|
||||
private readonly INavigationManager _navigationManager;
|
||||
private readonly IMenuManager _menuManager;
|
||||
|
||||
public AdminController(
|
||||
IOrchardServices orchardServices,
|
||||
IMenuService menuService,
|
||||
IOrchardServices services,
|
||||
INavigationManager navigationManager,
|
||||
IShapeFactory shapeFactory) {
|
||||
IMenuManager menuManager,
|
||||
INavigationManager navigationManager) {
|
||||
_menuService = menuService;
|
||||
_services = services;
|
||||
_menuManager = menuManager;
|
||||
_navigationManager = navigationManager;
|
||||
|
||||
Services = orchardServices;
|
||||
T = NullLocalizer.Instance;
|
||||
Shape = shapeFactory;
|
||||
Logger = NullLogger.Instance;
|
||||
}
|
||||
|
||||
dynamic Shape { get; set; }
|
||||
public Localizer T { get; set; }
|
||||
public ILogger Logger { get; set; }
|
||||
public IOrchardServices Services { get; set; }
|
||||
|
||||
public ActionResult Index(NavigationManagementViewModel model) {
|
||||
if (!_services.Authorizer.Authorize(Permissions.ManageMainMenu, T("Not allowed to manage the main menu")))
|
||||
public ActionResult Index(NavigationManagementViewModel model, int? menuId) {
|
||||
if (!Services.Authorizer.Authorize(Permissions.ManageMainMenu, T("Not allowed to manage the main menu"))) {
|
||||
return new HttpUnauthorizedResult();
|
||||
}
|
||||
|
||||
if (model == null)
|
||||
IEnumerable<TitlePart> menus = Services.ContentManager.Query<TitlePart, TitlePartRecord>().OrderBy(x => x.Title).ForType("Menu").List();
|
||||
|
||||
if (!menus.Any()) {
|
||||
return RedirectToAction("Create", "Admin", new {area = "Contents", id = "Menu", returnUrl = Request.RawUrl});
|
||||
}
|
||||
|
||||
IContent currentMenu = menuId == null
|
||||
? menus.FirstOrDefault()
|
||||
: menus.FirstOrDefault(menu => menu.Id == menuId);
|
||||
|
||||
if (currentMenu == null && menuId != null) { // incorrect menu id passed
|
||||
Services.Notifier.Error(T("Menu not found: {0}", menuId));
|
||||
return RedirectToAction("Index");
|
||||
}
|
||||
|
||||
if (model == null) {
|
||||
model = new NavigationManagementViewModel();
|
||||
}
|
||||
|
||||
if (model.MenuItemEntries == null || model.MenuItemEntries.Count() < 1)
|
||||
model.MenuItemEntries = _menuService.Get().Select(CreateMenuItemEntries).OrderBy(menuPartEntry => menuPartEntry.Position, new FlatPositionComparer()).ToList();
|
||||
if (model.MenuItemEntries == null || !model.MenuItemEntries.Any()) {
|
||||
model.MenuItemEntries = _menuService.GetMenuParts(currentMenu.Id).Select(CreateMenuItemEntries).OrderBy(menuPartEntry => menuPartEntry.Position, new FlatPositionComparer()).ToList();
|
||||
}
|
||||
|
||||
model.MenuItemDescriptors = _menuManager.GetMenuItemTypes();
|
||||
model.Menus = menus;
|
||||
model.CurrentMenu = currentMenu;
|
||||
|
||||
// need action name as this action is referenced from another action
|
||||
return View("Index", model);
|
||||
return View(model);
|
||||
}
|
||||
|
||||
[HttpPost, ActionName("Index")]
|
||||
public ActionResult IndexPOST(IList<MenuItemEntry> menuItemEntries) {
|
||||
if (!_services.Authorizer.Authorize(Permissions.ManageMainMenu, T("Couldn't manage the main menu")))
|
||||
if (!Services.Authorizer.Authorize(Permissions.ManageMainMenu, T("Couldn't manage the main menu")))
|
||||
return new HttpUnauthorizedResult();
|
||||
|
||||
// See http://orchard.codeplex.com/workitem/17116
|
||||
if (menuItemEntries != null) {
|
||||
foreach (var menuItemEntry in menuItemEntries) {
|
||||
MenuPart menuPart = _menuService.Get(menuItemEntry.MenuItemId);
|
||||
|
||||
menuPart.MenuText = menuItemEntry.Text;
|
||||
menuPart.MenuPosition = menuItemEntry.Position;
|
||||
if (menuPart.Is<MenuItemPart>())
|
||||
menuPart.As<MenuItemPart>().Url = menuItemEntry.Url;
|
||||
}
|
||||
}
|
||||
|
||||
@ -76,51 +101,26 @@ namespace Orchard.Core.Navigation.Controllers {
|
||||
Position = menuPart.MenuPosition,
|
||||
Url = menuPart.Is<MenuItemPart>()
|
||||
? menuPart.As<MenuItemPart>().Url
|
||||
: _navigationManager.GetUrl(null, _services.ContentManager.GetItemMetadata(menuPart).DisplayRouteValues),
|
||||
: _navigationManager.GetUrl(null, Services.ContentManager.GetItemMetadata(menuPart).DisplayRouteValues),
|
||||
ContentItem = menuPart.ContentItem,
|
||||
};
|
||||
}
|
||||
|
||||
public ActionResult Create() {
|
||||
return RedirectToAction("Index");
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
public ActionResult Create(NavigationManagementViewModel model) {
|
||||
if (!_services.Authorizer.Authorize(Permissions.ManageMainMenu, T("Couldn't manage the main menu")))
|
||||
return new HttpUnauthorizedResult();
|
||||
|
||||
var menuPart = _services.ContentManager.New<MenuPart>("MenuItem");
|
||||
menuPart.OnMainMenu = true;
|
||||
menuPart.MenuText = model.NewMenuItem.Text;
|
||||
menuPart.MenuPosition = model.NewMenuItem.Position;
|
||||
if (string.IsNullOrEmpty(menuPart.MenuPosition))
|
||||
menuPart.MenuPosition = Position.GetNext(_navigationManager.BuildMenu("main"));
|
||||
|
||||
var menuItem = menuPart.As<MenuItemPart>();
|
||||
menuItem.Url = model.NewMenuItem.Url;
|
||||
|
||||
if (!ModelState.IsValid) {
|
||||
_services.TransactionManager.Cancel();
|
||||
return View("Index", model);
|
||||
}
|
||||
|
||||
_services.ContentManager.Create(menuPart);
|
||||
|
||||
return RedirectToAction("Index");
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
public ActionResult Delete(int id) {
|
||||
if (!_services.Authorizer.Authorize(Permissions.ManageMainMenu, T("Couldn't manage the main menu")))
|
||||
if (!Services.Authorizer.Authorize(Permissions.ManageMainMenu, T("Couldn't manage the main menu")))
|
||||
return new HttpUnauthorizedResult();
|
||||
|
||||
MenuPart menuPart = _menuService.Get(id);
|
||||
|
||||
if (menuPart != null) {
|
||||
if (menuPart.Is<MenuItemPart>())
|
||||
// if the menu item is a concrete content item, don't delete it, just unreference the menu
|
||||
if (!menuPart.ContentItem.TypeDefinition.Settings.ContainsKey("Stereotype") || menuPart.ContentItem.TypeDefinition.Settings["Stereotype"] != "MenuItem") {
|
||||
menuPart.Menu = null;
|
||||
}
|
||||
else {
|
||||
_menuService.Delete(menuPart);
|
||||
else
|
||||
menuPart.OnMainMenu = false;
|
||||
}
|
||||
}
|
||||
|
||||
return RedirectToAction("Index");
|
||||
@ -133,5 +133,71 @@ namespace Orchard.Core.Navigation.Controllers {
|
||||
void IUpdateModel.AddModelError(string key, LocalizedString errorMessage) {
|
||||
ModelState.AddModelError(key, errorMessage.ToString());
|
||||
}
|
||||
|
||||
public ActionResult CreateMenuItem(string id, int menuId, string returnUrl) {
|
||||
if (!Services.Authorizer.Authorize(Permissions.ManageMainMenu, T("Couldn't manage the main menu")))
|
||||
return new HttpUnauthorizedResult();
|
||||
|
||||
// create a new temporary menu item
|
||||
var menuPart = Services.ContentManager.New<MenuPart>(id);
|
||||
|
||||
if (menuPart == null)
|
||||
return HttpNotFound();
|
||||
|
||||
// load the menu
|
||||
var menu = Services.ContentManager.Get(menuId);
|
||||
|
||||
if (menu == null)
|
||||
return HttpNotFound();
|
||||
|
||||
try {
|
||||
// filter the content items for this specific menu
|
||||
menuPart.MenuPosition = Position.GetNext(_navigationManager.BuildMenu(menu));
|
||||
|
||||
dynamic model = Services.ContentManager.BuildEditor(menuPart);
|
||||
|
||||
// Casting to avoid invalid (under medium trust) reflection over the protected View method and force a static invocation.
|
||||
return View((object)model);
|
||||
}
|
||||
catch (Exception exception) {
|
||||
Logger.Error(T("Creating menu item failed: {0}", exception.Message).Text);
|
||||
Services.Notifier.Error(T("Creating menu item failed: {0}", exception.Message));
|
||||
return this.RedirectLocal(returnUrl, () => RedirectToAction("Index"));
|
||||
}
|
||||
}
|
||||
|
||||
[HttpPost, ActionName("CreateMenuItem")]
|
||||
public ActionResult CreateMenuItemPost(string id, int menuId, string returnUrl) {
|
||||
if (!Services.Authorizer.Authorize(Permissions.ManageMainMenu, T("Couldn't manage the main menu")))
|
||||
return new HttpUnauthorizedResult();
|
||||
|
||||
var menuPart = Services.ContentManager.New<MenuPart>(id);
|
||||
|
||||
if (menuPart == null)
|
||||
return HttpNotFound();
|
||||
|
||||
// load the menu
|
||||
var menu = Services.ContentManager.Get(menuId);
|
||||
|
||||
if (menu == null)
|
||||
return HttpNotFound();
|
||||
|
||||
var model = Services.ContentManager.UpdateEditor(menuPart, this);
|
||||
|
||||
menuPart.MenuPosition = Position.GetNext(_navigationManager.BuildMenu(menu));
|
||||
menuPart.Menu = menu;
|
||||
|
||||
Services.ContentManager.Create(menuPart);
|
||||
|
||||
if (!ModelState.IsValid) {
|
||||
Services.TransactionManager.Cancel();
|
||||
// Casting to avoid invalid (under medium trust) reflection over the protected View method and force a static invocation.
|
||||
return View((object)model);
|
||||
}
|
||||
|
||||
Services.Notifier.Information(T("Your {0} has been added.", menuPart.TypeDefinition.DisplayName));
|
||||
|
||||
return this.RedirectLocal(returnUrl, () => RedirectToAction("Index"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,82 @@
|
||||
using JetBrains.Annotations;
|
||||
using Orchard.ContentManagement;
|
||||
using Orchard.ContentManagement.Drivers;
|
||||
using Orchard.ContentManagement.Handlers;
|
||||
using Orchard.Core.Navigation.Models;
|
||||
using Orchard.Core.Navigation.ViewModels;
|
||||
using Orchard.Localization;
|
||||
using Orchard.Security;
|
||||
|
||||
namespace Orchard.Core.Navigation.Drivers {
|
||||
[UsedImplicitly]
|
||||
public class ContentMenuItemPartDriver : ContentPartDriver<ContentMenuItemPart> {
|
||||
private readonly IContentManager _contentManager;
|
||||
private readonly IAuthorizationService _authorizationService;
|
||||
private readonly IWorkContextAccessor _workContextAccessor;
|
||||
|
||||
public ContentMenuItemPartDriver(
|
||||
IContentManager contentManager,
|
||||
IAuthorizationService authorizationService,
|
||||
IWorkContextAccessor workContextAccessor) {
|
||||
_contentManager = contentManager;
|
||||
_authorizationService = authorizationService;
|
||||
_workContextAccessor = workContextAccessor;
|
||||
|
||||
T = NullLocalizer.Instance;
|
||||
}
|
||||
|
||||
public Localizer T { get; set; }
|
||||
|
||||
protected override DriverResult Editor(ContentMenuItemPart part, dynamic shapeHelper) {
|
||||
return ContentShape("Parts_ContentMenuItem_Edit",
|
||||
() => {
|
||||
var model = new ContentMenuItemEditViewModel {
|
||||
ContentItemId = part.Content == null ? -1 : part.Content.Id,
|
||||
Part = part
|
||||
};
|
||||
return shapeHelper.EditorTemplate(TemplateName: "Parts.ContentMenuItem.Edit", Model: model, Prefix: Prefix);
|
||||
});
|
||||
}
|
||||
|
||||
protected override DriverResult Editor(ContentMenuItemPart part, IUpdateModel updater, dynamic shapeHelper) {
|
||||
var currentUser = _workContextAccessor.GetContext().CurrentUser;
|
||||
if (!_authorizationService.TryCheckAccess(Permissions.ManageMainMenu, currentUser, part))
|
||||
return null;
|
||||
|
||||
var model = new ContentMenuItemEditViewModel();
|
||||
|
||||
if(updater.TryUpdateModel(model, Prefix, null, null)) {
|
||||
var contentItem = _contentManager.Get(model.ContentItemId);
|
||||
if(contentItem == null) {
|
||||
updater.AddModelError("ContentItemId", T("You must select a Content Item"));
|
||||
}
|
||||
else {
|
||||
part.Content = contentItem;
|
||||
}
|
||||
}
|
||||
|
||||
return Editor(part, shapeHelper);
|
||||
}
|
||||
|
||||
protected override void Importing(ContentMenuItemPart part, ImportContentContext context) {
|
||||
var contentItemId = context.Attribute(part.PartDefinition.Name, "ContentItem");
|
||||
if (contentItemId != null) {
|
||||
var contentItem = context.GetItemFromSession(contentItemId);
|
||||
part.Content = contentItem;
|
||||
}
|
||||
else {
|
||||
part.Content = null;
|
||||
}
|
||||
}
|
||||
|
||||
protected override void Exporting(ContentMenuItemPart part, ExportContentContext context) {
|
||||
if (part.Content != null) {
|
||||
var contentItem = _contentManager.Get(part.Content.Id);
|
||||
if (contentItem != null) {
|
||||
var containerIdentity = _contentManager.GetItemMetadata(contentItem).Identity;
|
||||
context.Element(part.PartDefinition.Name).SetAttributeValue("ContentItem", containerIdentity.ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -15,13 +15,25 @@ namespace Orchard.Core.Navigation.Drivers {
|
||||
_workContextAccessor = workContextAccessor;
|
||||
}
|
||||
|
||||
protected override DriverResult Editor(MenuItemPart itemPart, IUpdateModel updater, dynamic shapeHelper) {
|
||||
protected override DriverResult Editor(MenuItemPart part, dynamic shapeHelper) {
|
||||
var currentUser = _workContextAccessor.GetContext().CurrentUser;
|
||||
if (!_authorizationService.TryCheckAccess(Permissions.ManageMainMenu, currentUser, itemPart))
|
||||
if (!_authorizationService.TryCheckAccess(Permissions.ManageMainMenu, currentUser, part))
|
||||
return null;
|
||||
|
||||
updater.TryUpdateModel(itemPart, Prefix, null, null);
|
||||
return null;
|
||||
return ContentShape("Parts_MenuItem_Edit",
|
||||
() => shapeHelper.EditorTemplate(TemplateName: "Parts.MenuItem.Edit", Model: part, Prefix: Prefix));
|
||||
}
|
||||
|
||||
protected override DriverResult Editor(MenuItemPart part, IUpdateModel updater, dynamic shapeHelper) {
|
||||
var currentUser = _workContextAccessor.GetContext().CurrentUser;
|
||||
if (!_authorizationService.TryCheckAccess(Permissions.ManageMainMenu, currentUser, part))
|
||||
return null;
|
||||
|
||||
if (updater != null) {
|
||||
updater.TryUpdateModel(part, Prefix, null, null);
|
||||
}
|
||||
|
||||
return Editor(part, shapeHelper);
|
||||
}
|
||||
|
||||
protected override void Importing(MenuItemPart part, ContentManagement.Handlers.ImportContentContext context) {
|
||||
|
@ -3,6 +3,8 @@ using JetBrains.Annotations;
|
||||
using Orchard.ContentManagement;
|
||||
using Orchard.ContentManagement.Drivers;
|
||||
using Orchard.Core.Navigation.Models;
|
||||
using Orchard.Core.Navigation.Services;
|
||||
using Orchard.Core.Navigation.ViewModels;
|
||||
using Orchard.Localization;
|
||||
using Orchard.Security;
|
||||
using Orchard.UI.Navigation;
|
||||
@ -14,11 +16,17 @@ namespace Orchard.Core.Navigation.Drivers {
|
||||
private readonly IAuthorizationService _authorizationService;
|
||||
private readonly INavigationManager _navigationManager;
|
||||
private readonly IOrchardServices _orchardServices;
|
||||
private readonly IMenuService _menuService;
|
||||
|
||||
public MenuPartDriver(IAuthorizationService authorizationService, INavigationManager navigationManager, IOrchardServices orchardServices) {
|
||||
public MenuPartDriver(
|
||||
IAuthorizationService authorizationService,
|
||||
INavigationManager navigationManager,
|
||||
IOrchardServices orchardServices,
|
||||
IMenuService menuService) {
|
||||
_authorizationService = authorizationService;
|
||||
_navigationManager = navigationManager;
|
||||
_orchardServices = orchardServices;
|
||||
_menuService = menuService;
|
||||
T = NullLocalizer.Instance;
|
||||
}
|
||||
|
||||
@ -28,21 +36,39 @@ namespace Orchard.Core.Navigation.Drivers {
|
||||
if (!_authorizationService.TryCheckAccess(Permissions.ManageMainMenu, _orchardServices.WorkContext.CurrentUser, part))
|
||||
return null;
|
||||
|
||||
return ContentShape("Parts_Navigation_Menu_Edit",
|
||||
() => shapeHelper.EditorTemplate(TemplateName: "Parts.Navigation.Menu.Edit", Model: part, Prefix: Prefix));
|
||||
return ContentShape("Parts_Navigation_Menu_Edit", () => {
|
||||
var model = new MenuPartViewModel {
|
||||
CurrentMenuId = part.Menu == null ? -1 : part.Menu.Id,
|
||||
ContentItem = part.ContentItem,
|
||||
Menus = _menuService.GetMenus(),
|
||||
OnMenu = part.Menu != null,
|
||||
MenuText = part.MenuText
|
||||
};
|
||||
|
||||
return shapeHelper.EditorTemplate(TemplateName: "Parts.Navigation.Menu.Edit", Model: model, Prefix: Prefix);
|
||||
});
|
||||
}
|
||||
|
||||
protected override DriverResult Editor(MenuPart part, IUpdateModel updater, dynamic shapeHelper) {
|
||||
if (!_authorizationService.TryCheckAccess(Permissions.ManageMainMenu, _orchardServices.WorkContext.CurrentUser, part))
|
||||
return null;
|
||||
|
||||
if (string.IsNullOrEmpty(part.MenuPosition))
|
||||
part.MenuPosition = Position.GetNext(_navigationManager.BuildMenu("main"));
|
||||
var model = new MenuPartViewModel();
|
||||
|
||||
updater.TryUpdateModel(part, Prefix, null, null);
|
||||
if(updater.TryUpdateModel(model, Prefix, null, null)) {
|
||||
var menu = model.OnMenu ? _orchardServices.ContentManager.Get(model.CurrentMenuId) : null;
|
||||
|
||||
if (part.OnMainMenu && string.IsNullOrEmpty(part.MenuText))
|
||||
updater.AddModelError("MenuText", T("The MenuText field is required"));
|
||||
part.MenuText = model.MenuText;
|
||||
part.Menu = menu;
|
||||
|
||||
if (string.IsNullOrEmpty(part.MenuPosition) && menu != null) {
|
||||
part.MenuPosition = Position.GetNext(_navigationManager.BuildMenu(menu));
|
||||
|
||||
if (string.IsNullOrEmpty(part.MenuText)) {
|
||||
updater.AddModelError("MenuText", T("The MenuText field is required"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Editor(part, shapeHelper);
|
||||
}
|
||||
@ -58,16 +84,27 @@ namespace Orchard.Core.Navigation.Drivers {
|
||||
part.MenuPosition = position;
|
||||
}
|
||||
|
||||
var onMainMenu = context.Attribute(part.PartDefinition.Name, "OnMainMenu");
|
||||
if (onMainMenu != null) {
|
||||
part.OnMainMenu = Convert.ToBoolean(onMainMenu);
|
||||
var menuIdentity = context.Attribute(part.PartDefinition.Name, "Menu");
|
||||
if (menuIdentity != null) {
|
||||
var menu = context.GetItemFromSession(menuIdentity);
|
||||
if (menu != null) {
|
||||
part.Menu = menu;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected override void Exporting(MenuPart part, ContentManagement.Handlers.ExportContentContext context) {
|
||||
// is it on a menu ?
|
||||
if(part.Menu == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
var menu = _orchardServices.ContentManager.Get(part.Menu.Id);
|
||||
var menuIdentity = _orchardServices.ContentManager.GetItemMetadata(menu).Identity;
|
||||
context.Element(part.PartDefinition.Name).SetAttributeValue("Menu", menuIdentity);
|
||||
|
||||
context.Element(part.PartDefinition.Name).SetAttributeValue("MenuText", part.MenuText);
|
||||
context.Element(part.PartDefinition.Name).SetAttributeValue("MenuPosition", part.MenuPosition);
|
||||
context.Element(part.PartDefinition.Name).SetAttributeValue("OnMainMenu", part.OnMainMenu);
|
||||
}
|
||||
}
|
||||
}
|
209
src/Orchard.Web/Core/Navigation/Drivers/MenuWidgetPartDriver.cs
Normal file
209
src/Orchard.Web/Core/Navigation/Drivers/MenuWidgetPartDriver.cs
Normal file
@ -0,0 +1,209 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Web.Routing;
|
||||
using Orchard.ContentManagement;
|
||||
using Orchard.ContentManagement.Aspects;
|
||||
using Orchard.ContentManagement.Drivers;
|
||||
using Orchard.ContentManagement.Handlers;
|
||||
using Orchard.Core.Navigation.Models;
|
||||
using Orchard.Core.Navigation.Services;
|
||||
using Orchard.Core.Navigation.ViewModels;
|
||||
using Orchard.Core.Title.Models;
|
||||
using Orchard.Localization;
|
||||
using Orchard.UI.Navigation;
|
||||
using Orchard.Utility.Extensions;
|
||||
|
||||
namespace Orchard.Core.Navigation.Drivers {
|
||||
public class MenuWidgetPartDriver : ContentPartDriver<MenuWidgetPart> {
|
||||
private readonly IContentManager _contentManager;
|
||||
private readonly INavigationManager _navigationManager;
|
||||
private readonly IWorkContextAccessor _workContextAccessor;
|
||||
private readonly IMenuService _menuService;
|
||||
|
||||
public MenuWidgetPartDriver(
|
||||
IContentManager contentManager,
|
||||
INavigationManager navigationManager,
|
||||
IWorkContextAccessor workContextAccessor,
|
||||
IMenuService menuService) {
|
||||
_contentManager = contentManager;
|
||||
_navigationManager = navigationManager;
|
||||
_workContextAccessor = workContextAccessor;
|
||||
_menuService = menuService;
|
||||
T = NullLocalizer.Instance;
|
||||
}
|
||||
|
||||
public Localizer T { get; set; }
|
||||
|
||||
protected override string Prefix {
|
||||
get {
|
||||
return "MenuWidget";
|
||||
}
|
||||
}
|
||||
protected override DriverResult Display(MenuWidgetPart part, string displayType, dynamic shapeHelper) {
|
||||
return ContentShape( "Parts_MenuWidget", () => {
|
||||
var menu = _menuService.GetMenu(part.Menu.Id);
|
||||
|
||||
if(menu == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
var menuName = menu.As<TitlePart>().Title.HtmlClassify();
|
||||
var currentCulture = _workContextAccessor.GetContext().CurrentCulture;
|
||||
|
||||
IEnumerable<MenuItem> menuItems = _navigationManager.BuildMenu(menu);
|
||||
|
||||
var localized = new List<MenuItem>();
|
||||
foreach(var menuItem in menuItems) {
|
||||
// if there is no associated content, it as culture neutral
|
||||
if(menuItem.Content == null) {
|
||||
localized.Add(menuItem);
|
||||
}
|
||||
|
||||
// if the menu item is culture neutral or of the current culture
|
||||
if (String.IsNullOrEmpty(menuItem.Culture) || String.Equals(menuItem.Culture, currentCulture, StringComparison.OrdinalIgnoreCase)) {
|
||||
localized.Add(menuItem);
|
||||
}
|
||||
}
|
||||
|
||||
menuItems = localized;
|
||||
|
||||
var routeData = _workContextAccessor.GetContext().HttpContext.Request.RequestContext.RouteData;
|
||||
|
||||
var selectedPath = NavigationHelper.SetSelectedPath(menuItems, routeData);
|
||||
|
||||
dynamic menuShape = shapeHelper.Menu();
|
||||
|
||||
if (part.Breadcrumb) {
|
||||
menuItems = selectedPath;
|
||||
foreach (var menuItem in menuItems) {
|
||||
menuItem.Items = Enumerable.Empty<MenuItem>();
|
||||
}
|
||||
|
||||
// apply level limites to breadcrumb
|
||||
menuItems = menuItems.Skip(part.StartLevel - 1);
|
||||
if (part.Levels > 0) {
|
||||
menuItems = menuItems.Take(part.Levels);
|
||||
}
|
||||
|
||||
var result = new List<MenuItem>(menuItems);
|
||||
|
||||
// inject the home page
|
||||
if (part.AddHomePage) {
|
||||
result.Insert(0, new MenuItem {
|
||||
Href = _navigationManager.GetUrl("~/", null),
|
||||
Text = T("Home")
|
||||
});
|
||||
}
|
||||
|
||||
// inject the current page
|
||||
if (!part.AddCurrentPage) {
|
||||
result.RemoveAt(result.Count - 1);
|
||||
}
|
||||
|
||||
// prevent the home page to be added as the home page and the current page
|
||||
if (result.Count == 2 && String.Equals(result[0].Href, result[1].Href, StringComparison.OrdinalIgnoreCase)) {
|
||||
result.RemoveAt(1);
|
||||
}
|
||||
|
||||
menuItems = result;
|
||||
|
||||
menuShape = shapeHelper.Breadcrumb();
|
||||
}
|
||||
else {
|
||||
IEnumerable<MenuItem> topLevelItems = menuItems.ToList();
|
||||
|
||||
if(part.StartLevel > 1) {
|
||||
topLevelItems = selectedPath.Where(x => x.Selected);
|
||||
}
|
||||
|
||||
if (topLevelItems.Any()) {
|
||||
// apply start level by pushing childrens as top level items
|
||||
int i = 0;
|
||||
for (; i < part.StartLevel - 1; i++) {
|
||||
var temp = new List<MenuItem>();
|
||||
foreach (var menuItem in topLevelItems) {
|
||||
temp.AddRange(menuItem.Items);
|
||||
}
|
||||
topLevelItems = temp;
|
||||
}
|
||||
|
||||
// apply display level
|
||||
if(part.Levels > 0) {
|
||||
var current = topLevelItems.ToList();
|
||||
for (; i < part.Levels - part.StartLevel; i++ ) {
|
||||
var temp = new List<MenuItem>();
|
||||
foreach (var menuItem in current) {
|
||||
temp.AddRange(menuItem.Items);
|
||||
}
|
||||
current = temp;
|
||||
}
|
||||
foreach(var menuItem in current) {
|
||||
menuItem.Items = Enumerable.Empty<MenuItem>();
|
||||
}
|
||||
}
|
||||
|
||||
menuItems = topLevelItems;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
menuShape.MenuName(menuName);
|
||||
NavigationHelper.PopulateMenu(shapeHelper, menuShape, menuShape, menuItems);
|
||||
|
||||
return shapeHelper.Parts_MenuWidget(Menu: menuShape);
|
||||
});
|
||||
}
|
||||
|
||||
protected override DriverResult Editor(MenuWidgetPart part, dynamic shapeHelper) {
|
||||
return ContentShape("Parts_MenuWidget_Edit", () => {
|
||||
var model = new MenuWidgetViewModel {
|
||||
CurrentMenuId = part.Menu == null ? -1 : part.Menu.Id,
|
||||
StartLevel = part.StartLevel,
|
||||
StopLevel = part.Levels,
|
||||
Breadcrumb = part.Breadcrumb,
|
||||
AddCurrentPage = part.AddCurrentPage,
|
||||
AddHomePage = part.AddHomePage,
|
||||
Menus = _menuService.GetMenus(),
|
||||
};
|
||||
|
||||
return shapeHelper.EditorTemplate(TemplateName: "Parts.MenuWidget.Edit", Model: model, Prefix: Prefix);
|
||||
});
|
||||
}
|
||||
|
||||
protected override DriverResult Editor(MenuWidgetPart part, IUpdateModel updater, dynamic shapeHelper) {
|
||||
var model = new MenuWidgetViewModel();
|
||||
|
||||
if(updater.TryUpdateModel(model, Prefix, null, null)) {
|
||||
part.StartLevel = model.StartLevel;
|
||||
part.Levels = model.StopLevel;
|
||||
part.Breadcrumb = model.Breadcrumb;
|
||||
part.AddHomePage = model.AddHomePage;
|
||||
part.AddCurrentPage = model.AddCurrentPage;
|
||||
part.Menu = _contentManager.Get(model.CurrentMenuId).Record;
|
||||
}
|
||||
|
||||
return Editor(part, shapeHelper);
|
||||
}
|
||||
|
||||
protected override void Importing(MenuWidgetPart part, ImportContentContext context) {
|
||||
context.ImportAttribute(part.PartDefinition.Name, "StartLevel", x => part.StartLevel = Convert.ToInt32(x));
|
||||
context.ImportAttribute(part.PartDefinition.Name, "Levels", x => part.Levels = Convert.ToInt32(x));
|
||||
context.ImportAttribute(part.PartDefinition.Name, "Breadcrumb", x => part.Breadcrumb = Convert.ToBoolean(x));
|
||||
|
||||
context.ImportAttribute(part.PartDefinition.Name, "Menu", x => part.Menu = context.GetItemFromSession(x).Record);
|
||||
}
|
||||
|
||||
protected override void Exporting(MenuWidgetPart part, ExportContentContext context) {
|
||||
var menuIdentity = _contentManager.GetItemMetadata(_contentManager.Get(part.Menu.Id)).Identity;
|
||||
context.Element(part.PartDefinition.Name).SetAttributeValue("Menu", menuIdentity);
|
||||
|
||||
context.Element(part.PartDefinition.Name).SetAttributeValue("StartLevel", part.StartLevel);
|
||||
context.Element(part.PartDefinition.Name).SetAttributeValue("Levels", part.Levels);
|
||||
context.Element(part.PartDefinition.Name).SetAttributeValue("Breadcrumb", part.Breadcrumb);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,41 @@
|
||||
using Orchard.ContentManagement;
|
||||
using Orchard.ContentManagement.Drivers;
|
||||
using Orchard.Core.Navigation.Models;
|
||||
using Orchard.Core.Navigation.ViewModels;
|
||||
using Orchard.Security;
|
||||
|
||||
namespace Orchard.Core.Navigation.Drivers {
|
||||
|
||||
public class NavigationPartDriver : ContentPartDriver<NavigationPart> {
|
||||
private readonly IAuthorizationService _authorizationService;
|
||||
private readonly IWorkContextAccessor _workContextAccessor;
|
||||
private readonly IContentManager _contentManager;
|
||||
|
||||
public NavigationPartDriver(
|
||||
IAuthorizationService authorizationService,
|
||||
IWorkContextAccessor workContextAccessor,
|
||||
IContentManager contentManager) {
|
||||
_authorizationService = authorizationService;
|
||||
_workContextAccessor = workContextAccessor;
|
||||
_contentManager = contentManager;
|
||||
}
|
||||
|
||||
protected override DriverResult Editor(NavigationPart part, dynamic shapeHelper) {
|
||||
var currentUser = _workContextAccessor.GetContext().CurrentUser;
|
||||
if (!_authorizationService.TryCheckAccess(Permissions.ManageMainMenu, currentUser, part))
|
||||
return null;
|
||||
|
||||
return ContentShape("Parts_Navigation_Edit",
|
||||
() => {
|
||||
// loads all menu part of type ContentMenuItem linking to the current content item
|
||||
var model = new NavigationPartViewModel() {
|
||||
Part = part,
|
||||
ContentMenuItems = _contentManager.Query<MenuPart>()
|
||||
.Join<ContentMenuItemPartRecord>().Where(x => x.ContentMenuItemRecord == part.ContentItem.Record).List()
|
||||
};
|
||||
|
||||
return shapeHelper.EditorTemplate(TemplateName: "Parts.Navigation.Edit", Model: model, Prefix: Prefix);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,34 @@
|
||||
using JetBrains.Annotations;
|
||||
using Orchard.ContentManagement;
|
||||
using Orchard.Core.Navigation.Models;
|
||||
using Orchard.Data;
|
||||
using Orchard.ContentManagement.Handlers;
|
||||
|
||||
namespace Orchard.Core.Navigation.Handlers {
|
||||
[UsedImplicitly]
|
||||
public class ContentMenuItemPartHandler : ContentHandler {
|
||||
private readonly IContentManager _contentManager;
|
||||
|
||||
public ContentMenuItemPartHandler(IContentManager contentManager, IRepository<ContentMenuItemPartRecord> repository) {
|
||||
_contentManager = contentManager;
|
||||
Filters.Add(new ActivatingFilter<ContentMenuItemPart>("ContentMenuItem"));
|
||||
Filters.Add(StorageFilter.For(repository));
|
||||
|
||||
OnLoading<ContentMenuItemPart>((context, part) => part._content.Loader(p => contentManager.Get(part.Record.ContentMenuItemRecord.Id)));
|
||||
}
|
||||
|
||||
protected override void GetItemMetadata(GetContentItemMetadataContext context) {
|
||||
base.GetItemMetadata(context);
|
||||
|
||||
if (context.ContentItem.ContentType != "ContentMenuItem") {
|
||||
return;
|
||||
}
|
||||
|
||||
var contentMenuItemPart = context.ContentItem.As<ContentMenuItemPart>();
|
||||
// the display route for the menu item is the one for the referenced content item
|
||||
if(contentMenuItemPart != null) {
|
||||
context.Metadata.DisplayRouteValues = _contentManager.GetItemMetadata(contentMenuItemPart.Content).DisplayRouteValues;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
39
src/Orchard.Web/Core/Navigation/Handlers/MenuHandler.cs
Normal file
39
src/Orchard.Web/Core/Navigation/Handlers/MenuHandler.cs
Normal file
@ -0,0 +1,39 @@
|
||||
using JetBrains.Annotations;
|
||||
using Orchard.ContentManagement;
|
||||
using Orchard.ContentManagement.Handlers;
|
||||
using Orchard.Core.Navigation.Services;
|
||||
using Orchard.Core.Title.Models;
|
||||
|
||||
namespace Orchard.Core.Navigation.Handlers {
|
||||
[UsedImplicitly]
|
||||
public class MenuHandler : ContentHandler {
|
||||
private readonly IMenuService _menuService;
|
||||
private readonly IContentManager _contentManager;
|
||||
|
||||
public MenuHandler(IMenuService menuService, IContentManager contentManager) {
|
||||
_menuService = menuService;
|
||||
_contentManager = contentManager;
|
||||
}
|
||||
|
||||
protected override void GetItemMetadata(GetContentItemMetadataContext context) {
|
||||
if(context.ContentItem.ContentType != "Menu") {
|
||||
return;
|
||||
}
|
||||
|
||||
context.Metadata.Identity.Add("name", context.ContentItem.As<TitlePart>().Title);
|
||||
}
|
||||
|
||||
protected override void Removing(RemoveContentContext context) {
|
||||
if (context.ContentItem.ContentType != "Menu") {
|
||||
return;
|
||||
}
|
||||
|
||||
// remove all menu items
|
||||
var menuParts = _menuService.GetMenuParts(context.ContentItem.Id);
|
||||
|
||||
foreach(var menuPart in menuParts) {
|
||||
_contentManager.Remove(menuPart.ContentItem);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -11,13 +11,5 @@ namespace Orchard.Core.Navigation.Handlers {
|
||||
Filters.Add(new ActivatingFilter<MenuItemPart>("MenuItem"));
|
||||
Filters.Add(StorageFilter.For(repository));
|
||||
}
|
||||
|
||||
protected override void GetItemMetadata(GetContentItemMetadataContext context) {
|
||||
var part = context.ContentItem.As<MenuItemPart>();
|
||||
|
||||
if (part != null) {
|
||||
context.Metadata.Identity.Add("MenuItem.Url", part.Url);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using JetBrains.Annotations;
|
||||
using Orchard.ContentManagement;
|
||||
using Orchard.ContentManagement.Handlers;
|
||||
using Orchard.Core.Navigation.Models;
|
||||
using Orchard.Data;
|
||||
@ -7,13 +8,45 @@ using Orchard.Data;
|
||||
namespace Orchard.Core.Navigation.Handlers {
|
||||
[UsedImplicitly]
|
||||
public class MenuPartHandler : ContentHandler {
|
||||
public MenuPartHandler(IRepository<MenuPartRecord> menuPartRepository) {
|
||||
private readonly IContentManager _contentManager;
|
||||
|
||||
public MenuPartHandler(
|
||||
IRepository<MenuPartRecord> menuPartRepository,
|
||||
IContentManager contentManager
|
||||
) {
|
||||
|
||||
_contentManager = contentManager;
|
||||
Filters.Add(StorageFilter.For(menuPartRepository));
|
||||
|
||||
OnInitializing<MenuPart>((ctx, x) => {
|
||||
x.OnMainMenu = false;
|
||||
x.MenuText = String.Empty;
|
||||
});
|
||||
|
||||
OnActivated<MenuPart>(PropertySetHandlers);
|
||||
}
|
||||
|
||||
protected static void PropertySetHandlers(ActivatedContentContext context, MenuPart menuPart) {
|
||||
menuPart.MenuField.Setter(menu => {
|
||||
menuPart.Record.MenuId = menu.ContentItem.Id;
|
||||
return menu;
|
||||
});
|
||||
}
|
||||
|
||||
protected void LazyLoadHandlers(MenuPart menuPart) {
|
||||
menuPart.MenuField.Loader(ctx =>
|
||||
_contentManager.Get(menuPart.Record.MenuId, menuPart.IsPublished() ? VersionOptions.Published : VersionOptions.Latest));
|
||||
}
|
||||
|
||||
protected override void GetItemMetadata(GetContentItemMetadataContext context) {
|
||||
var part = context.ContentItem.As<MenuPart>();
|
||||
|
||||
if (part != null) {
|
||||
string stereotype;
|
||||
if (context.ContentItem.TypeDefinition.Settings.TryGetValue("Stereotype", out stereotype) && stereotype == "MenuItem") {
|
||||
context.Metadata.DisplayText = part.MenuText;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,13 @@
|
||||
using Orchard.ContentManagement.Handlers;
|
||||
using Orchard.Core.Navigation.Models;
|
||||
using Orchard.Data;
|
||||
|
||||
namespace Orchard.Core.Navigation.Handlers {
|
||||
public class MenuWidgetPartHandler : ContentHandler {
|
||||
public MenuWidgetPartHandler(IRepository<MenuWidgetPartRecord> repository) {
|
||||
Filters.Add(StorageFilter.For(repository));
|
||||
|
||||
OnInitializing<MenuWidgetPart>((context, part) => { part.StartLevel = 1; });
|
||||
}
|
||||
}
|
||||
}
|
@ -1,11 +1,21 @@
|
||||
using Orchard.ContentManagement.MetaData;
|
||||
using Orchard.Core.Contents.Extensions;
|
||||
using Orchard.Core.Navigation.Services;
|
||||
using Orchard.Data.Migration;
|
||||
|
||||
namespace Orchard.Core.Navigation {
|
||||
public class Migrations : DataMigrationImpl {
|
||||
private readonly IMenuService _menuService;
|
||||
|
||||
public Migrations(IMenuService menuService ) {
|
||||
_menuService = menuService;
|
||||
}
|
||||
|
||||
public int Create() {
|
||||
ContentDefinitionManager.AlterPartDefinition("MenuPart", builder => builder.Attachable());
|
||||
ContentDefinitionManager.AlterPartDefinition("NavigationPart", builder => builder.Attachable());
|
||||
ContentDefinitionManager.AlterTypeDefinition("Page", cfg => cfg.WithPart("MenuPart"));
|
||||
|
||||
SchemaBuilder.CreateTable("MenuItemPartRecord",
|
||||
table => table
|
||||
.ContentPartRecord()
|
||||
@ -17,14 +27,79 @@ namespace Orchard.Core.Navigation {
|
||||
.ContentPartRecord()
|
||||
.Column<string>("MenuText")
|
||||
.Column<string>("MenuPosition")
|
||||
.Column<bool>("OnMainMenu")
|
||||
.Column<int>("MenuId")
|
||||
);
|
||||
|
||||
ContentDefinitionManager.AlterTypeDefinition("Page", cfg => cfg.WithPart("MenuPart"));
|
||||
ContentDefinitionManager.AlterTypeDefinition("MenuItem", cfg => cfg.WithPart("MenuPart"));
|
||||
ContentDefinitionManager.AlterPartDefinition("MenuPart", builder => builder.Attachable());
|
||||
ContentDefinitionManager.AlterTypeDefinition("MenuItem", cfg => cfg
|
||||
.WithPart("MenuPart")
|
||||
.WithPart("IdentityPart")
|
||||
.WithPart("CommonPart")
|
||||
.DisplayedAs("Custom Link")
|
||||
.WithSetting("Description", "Represents a simple custom link with a text and an url.")
|
||||
.WithSetting("Stereotype", "MenuItem") // because we declare a new stereotype, the Shape MenuItem_Edit is needed
|
||||
);
|
||||
|
||||
ContentDefinitionManager.AlterTypeDefinition("Menu", cfg => cfg
|
||||
.WithPart("CommonPart", p => p.WithSetting("OwnerEditorSettings.ShowOwnerEditor", "false"))
|
||||
.WithPart("TitlePart")
|
||||
);
|
||||
|
||||
SchemaBuilder.CreateTable("MenuWidgetPartRecord", table => table
|
||||
.ContentPartRecord()
|
||||
.Column<int>("StartLevel")
|
||||
.Column<int>("Levels")
|
||||
.Column<bool>("Breadcrumb")
|
||||
.Column<bool>("AddHomePage")
|
||||
.Column<bool>("AddCurrentPage")
|
||||
.Column<int>("Menu_id")
|
||||
);
|
||||
|
||||
ContentDefinitionManager.AlterTypeDefinition("MenuWidget", cfg => cfg
|
||||
.WithPart("CommonPart")
|
||||
.WithPart("IdentityPart")
|
||||
.WithPart("WidgetPart")
|
||||
.WithPart("MenuWidgetPart")
|
||||
.WithSetting("Stereotype", "Widget")
|
||||
);
|
||||
|
||||
SchemaBuilder.CreateTable("AdminMenuPartRecord",
|
||||
table => table
|
||||
.ContentPartRecord()
|
||||
.Column<string>("AdminMenuText")
|
||||
.Column<string>("AdminMenuPosition")
|
||||
.Column<bool>("OnAdminMenu")
|
||||
);
|
||||
|
||||
ContentDefinitionManager.AlterTypeDefinition("HtmlMenuItem", cfg => cfg
|
||||
.WithPart("MenuPart")
|
||||
.WithPart("BodyPart")
|
||||
.WithPart("CommonPart")
|
||||
.WithPart("IdentityPart")
|
||||
.DisplayedAs("Html Menu Item")
|
||||
.WithSetting("Description", "Renders some custom HTML in the menu.")
|
||||
.WithSetting("BodyPartSettings.FlavorDefault", "html")
|
||||
.WithSetting("Stereotype", "MenuItem")
|
||||
);
|
||||
|
||||
return 1;
|
||||
ContentDefinitionManager.AlterPartDefinition("AdminMenuPart", builder => builder.Attachable());
|
||||
|
||||
SchemaBuilder.CreateTable("ContentMenuItemPartRecord",
|
||||
table => table
|
||||
.ContentPartRecord()
|
||||
.Column<int>("ContentMenuItemRecord_id")
|
||||
);
|
||||
|
||||
ContentDefinitionManager.AlterTypeDefinition("ContentMenuItem", cfg => cfg
|
||||
.WithPart("MenuPart")
|
||||
.WithPart("CommonPart")
|
||||
.WithPart("IdentityPart")
|
||||
.WithPart("ContentMenuItemPart")
|
||||
.DisplayedAs("Content Menu Item")
|
||||
.WithSetting("Description", "Adds a Content Item to the menu.")
|
||||
.WithSetting("Stereotype", "MenuItem")
|
||||
);
|
||||
|
||||
return 3;
|
||||
}
|
||||
|
||||
public int UpdateFrom1() {
|
||||
@ -39,5 +114,73 @@ namespace Orchard.Core.Navigation {
|
||||
return 2;
|
||||
}
|
||||
|
||||
public int UpdateFrom2() {
|
||||
ContentDefinitionManager.AlterTypeDefinition("MenuItem", cfg => cfg
|
||||
.WithPart("MenuPart")
|
||||
.WithPart("CommonPart")
|
||||
.WithPart("IdentityPart")
|
||||
.DisplayedAs("Custom Link")
|
||||
.WithSetting("Description", "Represents a simple custom link with a text and an url.")
|
||||
.WithSetting("Stereotype", "MenuItem") // because we declare a new stereotype, the Shape MenuItem_Edit is needed
|
||||
);
|
||||
|
||||
ContentDefinitionManager.AlterTypeDefinition("Menu", cfg => cfg
|
||||
.WithPart("CommonPart")
|
||||
.WithPart("TitlePart")
|
||||
);
|
||||
|
||||
SchemaBuilder.CreateTable("MenuWidgetPartRecord",table => table
|
||||
.ContentPartRecord()
|
||||
.Column<int>("StartLevel")
|
||||
.Column<int>("Levels")
|
||||
.Column<bool>("Breadcrumb")
|
||||
.Column<bool>("AddHomePage")
|
||||
.Column<bool>("AddCurrentPage")
|
||||
.Column<int>("Menu_id")
|
||||
);
|
||||
|
||||
ContentDefinitionManager.AlterTypeDefinition("MenuWidget", cfg => cfg
|
||||
.WithPart("CommonPart")
|
||||
.WithPart("IdentityPart")
|
||||
.WithPart("WidgetPart")
|
||||
.WithPart("MenuWidgetPart")
|
||||
.WithSetting("Stereotype", "Widget")
|
||||
);
|
||||
|
||||
SchemaBuilder
|
||||
.AlterTable("MenuPartRecord", table => table.DropColumn("OnMainMenu"))
|
||||
.AlterTable("MenuPartRecord", table => table.AddColumn<int>("MenuId"))
|
||||
;
|
||||
|
||||
ContentDefinitionManager.AlterTypeDefinition("HtmlMenuItem", cfg => cfg
|
||||
.WithPart("MenuPart")
|
||||
.WithPart("BodyPart")
|
||||
.WithPart("CommonPart")
|
||||
.WithPart("IdentityPart")
|
||||
.DisplayedAs("Html Menu Item")
|
||||
.WithSetting("Description", "Renders some custom HTML in the menu.")
|
||||
.WithSetting("BodyPartSettings.FlavorDefault", "html")
|
||||
.WithSetting("Stereotype", "MenuItem")
|
||||
);
|
||||
|
||||
ContentDefinitionManager.AlterPartDefinition("NavigationPart", builder => builder.Attachable());
|
||||
|
||||
|
||||
// create a Main Menu
|
||||
var mainMenu = _menuService.Create("Main Menu");
|
||||
|
||||
// assign the Main Menu to all current menu items
|
||||
foreach (var menuItem in _menuService.Get()) {
|
||||
// if they don't have a position, then they are not displayed
|
||||
if(string.IsNullOrWhiteSpace(menuItem.MenuPosition)) {
|
||||
continue;
|
||||
}
|
||||
menuItem.Menu = mainMenu.ContentItem;
|
||||
}
|
||||
|
||||
// at this point a widget should still be created to display the navigation
|
||||
|
||||
return 3;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,17 @@
|
||||
using Orchard.ContentManagement;
|
||||
using Orchard.ContentManagement.Utilities;
|
||||
|
||||
namespace Orchard.Core.Navigation.Models {
|
||||
public class ContentMenuItemPart : ContentPart<ContentMenuItemPartRecord> {
|
||||
|
||||
public readonly LazyField<ContentItem> _content = new LazyField<ContentItem>();
|
||||
|
||||
public ContentItem Content {
|
||||
get { return _content.Value; }
|
||||
set {
|
||||
_content.Value = value;
|
||||
Record.ContentMenuItemRecord = value == null ? null : value.Record;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,7 @@
|
||||
using Orchard.ContentManagement.Records;
|
||||
|
||||
namespace Orchard.Core.Navigation.Models {
|
||||
public class ContentMenuItemPartRecord : ContentPartRecord {
|
||||
public virtual ContentItemRecord ContentMenuItemRecord { get; set; }
|
||||
}
|
||||
}
|
@ -1,9 +1,8 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using Orchard.ContentManagement;
|
||||
using Orchard.ContentManagement;
|
||||
|
||||
namespace Orchard.Core.Navigation.Models {
|
||||
public class MenuItemPart : ContentPart<MenuItemPartRecord> {
|
||||
[Required]
|
||||
|
||||
public string Url {
|
||||
get { return Record.Url; }
|
||||
set { Record.Url = value; }
|
||||
|
@ -1,12 +1,16 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using Orchard.ContentManagement;
|
||||
using Orchard.ContentManagement.Utilities;
|
||||
|
||||
namespace Orchard.Core.Navigation.Models {
|
||||
public class MenuPart : ContentPart<MenuPartRecord> {
|
||||
|
||||
public bool OnMainMenu {
|
||||
get { return Record.OnMainMenu; }
|
||||
set { Record.OnMainMenu = value; }
|
||||
private readonly LazyField<IContent> _menu = new LazyField<IContent>();
|
||||
public LazyField<IContent> MenuField { get { return _menu; } }
|
||||
|
||||
public IContent Menu {
|
||||
get { return _menu.Value; }
|
||||
set { _menu.Value = value; }
|
||||
}
|
||||
|
||||
[StringLength(MenuPartRecord.DefaultMenuTextLength)]
|
||||
|
@ -8,6 +8,6 @@ namespace Orchard.Core.Navigation.Models {
|
||||
[StringLength(DefaultMenuTextLength)]
|
||||
public virtual string MenuText { get; set; }
|
||||
public virtual string MenuPosition { get; set; }
|
||||
public virtual bool OnMainMenu { get; set; }
|
||||
public virtual int MenuId { get; set; }
|
||||
}
|
||||
}
|
36
src/Orchard.Web/Core/Navigation/Models/MenuWidgetPart.cs
Normal file
36
src/Orchard.Web/Core/Navigation/Models/MenuWidgetPart.cs
Normal file
@ -0,0 +1,36 @@
|
||||
using Orchard.ContentManagement;
|
||||
using Orchard.ContentManagement.Records;
|
||||
|
||||
namespace Orchard.Core.Navigation.Models {
|
||||
public class MenuWidgetPart : ContentPart<MenuWidgetPartRecord> {
|
||||
public int StartLevel {
|
||||
get { return Record.StartLevel; }
|
||||
set { Record.StartLevel = value; }
|
||||
}
|
||||
|
||||
public int Levels {
|
||||
get { return Record.Levels; }
|
||||
set { Record.Levels = value; }
|
||||
}
|
||||
|
||||
public bool Breadcrumb {
|
||||
get { return Record.Breadcrumb; }
|
||||
set { Record.Breadcrumb = value; }
|
||||
}
|
||||
|
||||
public bool AddHomePage {
|
||||
get { return Record.AddHomePage; }
|
||||
set { Record.AddHomePage = value; }
|
||||
}
|
||||
|
||||
public bool AddCurrentPage {
|
||||
get { return Record.AddCurrentPage; }
|
||||
set { Record.AddCurrentPage = value; }
|
||||
}
|
||||
|
||||
public ContentItemRecord Menu {
|
||||
get { return Record.Menu; }
|
||||
set { Record.Menu = value; }
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,13 @@
|
||||
using Orchard.ContentManagement.Records;
|
||||
|
||||
namespace Orchard.Core.Navigation.Models {
|
||||
public class MenuWidgetPartRecord : ContentPartRecord {
|
||||
public virtual int StartLevel { get; set; }
|
||||
public virtual int Levels { get; set; }
|
||||
public virtual bool Breadcrumb { get; set; }
|
||||
public virtual bool AddHomePage { get; set; }
|
||||
public virtual bool AddCurrentPage { get; set; }
|
||||
|
||||
public virtual ContentItemRecord Menu { get; set; }
|
||||
}
|
||||
}
|
9
src/Orchard.Web/Core/Navigation/Models/NavigationPart.cs
Normal file
9
src/Orchard.Web/Core/Navigation/Models/NavigationPart.cs
Normal file
@ -0,0 +1,9 @@
|
||||
using Orchard.ContentManagement;
|
||||
|
||||
namespace Orchard.Core.Navigation.Models {
|
||||
/// <summary>
|
||||
/// Allows the management of Content Menu Items associated with a Content Item
|
||||
/// </summary>
|
||||
public class NavigationPart : ContentPart {
|
||||
}
|
||||
}
|
@ -2,8 +2,9 @@
|
||||
AntiForgery: enabled
|
||||
Author: The Orchard Team
|
||||
Website: http://orchardproject.net
|
||||
Version: 1.4.2
|
||||
OrchardVersion: 1.4.2
|
||||
Version: 1.5
|
||||
OrchardVersion: 1.5
|
||||
Description: The navigation module creates and manages a simple navigation menu for the front-end of the application and allows you to add content items to the admin menu.
|
||||
FeatureDescription: Menu management.
|
||||
Category: Core
|
||||
FeatureDependencies: Orchard.ContentPicker, Title
|
||||
|
@ -1,4 +1,9 @@
|
||||
<Placement>
|
||||
<Place Parts_Navigation_Menu_Edit="Content:9"/>
|
||||
<Place Parts_Navigation_AdminMenu_Edit="Content:9.1"/>
|
||||
<Place Parts_Navigation_Edit="Content:10"/>
|
||||
<Place Parts_MenuItem_Edit="Content:10"/>
|
||||
<Place Parts_ContentMenuItem_Edit="Content:10"/>
|
||||
<Place Parts_MenuWidget_Edit="Content:10"/>
|
||||
<Place Parts_MenuWidget="Content"/>
|
||||
</Placement>
|
@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<configuration>
|
||||
<appSettings>
|
||||
<add key="webpages:Enabled" value="false" />
|
||||
<configuration>
|
||||
<appSettings>
|
||||
<add key="webpages:Enabled" value="false" />
|
||||
</appSettings>
|
||||
<system.web>
|
||||
<httpHandlers>
|
@ -0,0 +1,400 @@
|
||||
/*
|
||||
* jQuery UI Nested Sortable
|
||||
* v 1.4 / 30 dec 2011
|
||||
* http://mjsarfatti.com/code/nestedSortable
|
||||
*
|
||||
* Depends on:
|
||||
* jquery.ui.sortable.js 1.8+
|
||||
*
|
||||
* Copyright (c) 2010-2012 Manuele J Sarfatti
|
||||
* Licensed under the MIT License
|
||||
* http://www.opensource.org/licenses/mit-license.php
|
||||
*/
|
||||
|
||||
(function ($) {
|
||||
|
||||
$.widget("mjs.nestedSortable", $.extend({}, $.ui.sortable.prototype, {
|
||||
|
||||
options: {
|
||||
tabSize: 20,
|
||||
disableNesting: 'mjs-nestedSortable-no-nesting',
|
||||
errorClass: 'mjs-nestedSortable-error',
|
||||
listType: 'ol',
|
||||
maxLevels: 0,
|
||||
protectRoot: false,
|
||||
rootID: null,
|
||||
rtl: false,
|
||||
isAllowed: function (item, parent) { return true; }
|
||||
},
|
||||
|
||||
_create: function () {
|
||||
this.element.data('sortable', this.element.data('nestedSortable'));
|
||||
|
||||
if (!this.element.is(this.options.listType))
|
||||
throw new Error('nestedSortable: Please check the listType option is set to your actual list type');
|
||||
|
||||
return $.ui.sortable.prototype._create.apply(this, arguments);
|
||||
},
|
||||
|
||||
destroy: function () {
|
||||
this.element
|
||||
.removeData("nestedSortable")
|
||||
.unbind(".nestedSortable");
|
||||
return $.ui.sortable.prototype.destroy.apply(this, arguments);
|
||||
},
|
||||
|
||||
_mouseDrag: function (event) {
|
||||
|
||||
//Compute the helpers position
|
||||
this.position = this._generatePosition(event);
|
||||
this.positionAbs = this._convertPositionTo("absolute");
|
||||
|
||||
if (!this.lastPositionAbs) {
|
||||
this.lastPositionAbs = this.positionAbs;
|
||||
}
|
||||
|
||||
//Do scrolling
|
||||
if (this.options.scroll) {
|
||||
var o = this.options, scrolled = false;
|
||||
if (this.scrollParent[0] != document && this.scrollParent[0].tagName != 'HTML') {
|
||||
|
||||
if ((this.overflowOffset.top + this.scrollParent[0].offsetHeight) - event.pageY < o.scrollSensitivity)
|
||||
this.scrollParent[0].scrollTop = scrolled = this.scrollParent[0].scrollTop + o.scrollSpeed;
|
||||
else if (event.pageY - this.overflowOffset.top < o.scrollSensitivity)
|
||||
this.scrollParent[0].scrollTop = scrolled = this.scrollParent[0].scrollTop - o.scrollSpeed;
|
||||
|
||||
if ((this.overflowOffset.left + this.scrollParent[0].offsetWidth) - event.pageX < o.scrollSensitivity)
|
||||
this.scrollParent[0].scrollLeft = scrolled = this.scrollParent[0].scrollLeft + o.scrollSpeed;
|
||||
else if (event.pageX - this.overflowOffset.left < o.scrollSensitivity)
|
||||
this.scrollParent[0].scrollLeft = scrolled = this.scrollParent[0].scrollLeft - o.scrollSpeed;
|
||||
|
||||
} else {
|
||||
|
||||
if (event.pageY - $(document).scrollTop() < o.scrollSensitivity)
|
||||
scrolled = $(document).scrollTop($(document).scrollTop() - o.scrollSpeed);
|
||||
else if ($(window).height() - (event.pageY - $(document).scrollTop()) < o.scrollSensitivity)
|
||||
scrolled = $(document).scrollTop($(document).scrollTop() + o.scrollSpeed);
|
||||
|
||||
if (event.pageX - $(document).scrollLeft() < o.scrollSensitivity)
|
||||
scrolled = $(document).scrollLeft($(document).scrollLeft() - o.scrollSpeed);
|
||||
else if ($(window).width() - (event.pageX - $(document).scrollLeft()) < o.scrollSensitivity)
|
||||
scrolled = $(document).scrollLeft($(document).scrollLeft() + o.scrollSpeed);
|
||||
|
||||
}
|
||||
|
||||
if (scrolled !== false && $.ui.ddmanager && !o.dropBehaviour)
|
||||
$.ui.ddmanager.prepareOffsets(this, event);
|
||||
}
|
||||
|
||||
//Regenerate the absolute position used for position checks
|
||||
this.positionAbs = this._convertPositionTo("absolute");
|
||||
|
||||
//Set the helper position
|
||||
if (!this.options.axis || this.options.axis != "y") this.helper[0].style.left = this.position.left + 'px';
|
||||
if (!this.options.axis || this.options.axis != "x") this.helper[0].style.top = this.position.top + 'px';
|
||||
|
||||
//Rearrange
|
||||
for (var i = this.items.length - 1; i >= 0; i--) {
|
||||
|
||||
//Cache variables and intersection, continue if no intersection
|
||||
var item = this.items[i], itemElement = item.item[0], intersection = this._intersectsWithPointer(item);
|
||||
if (!intersection) continue;
|
||||
|
||||
if (itemElement != this.currentItem[0] //cannot intersect with itself
|
||||
&& this.placeholder[intersection == 1 ? "next" : "prev"]()[0] != itemElement //no useless actions that have been done before
|
||||
&& !$.contains(this.placeholder[0], itemElement) //no action if the item moved is the parent of the item checked
|
||||
&& (this.options.type == 'semi-dynamic' ? !$.contains(this.element[0], itemElement) : true)
|
||||
//&& itemElement.parentNode == this.placeholder[0].parentNode // only rearrange items within the same container
|
||||
) {
|
||||
|
||||
$(itemElement).mouseenter();
|
||||
|
||||
this.direction = intersection == 1 ? "down" : "up";
|
||||
|
||||
if (this.options.tolerance == "pointer" || this._intersectsWithSides(item)) {
|
||||
$(itemElement).mouseleave();
|
||||
this._rearrange(event, item);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
|
||||
// Clear emtpy ul's/ol's
|
||||
this._clearEmpty(itemElement);
|
||||
|
||||
this._trigger("change", event, this._uiHash());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
var parentItem = (this.placeholder[0].parentNode.parentNode &&
|
||||
$(this.placeholder[0].parentNode.parentNode).closest('.ui-sortable').length)
|
||||
? $(this.placeholder[0].parentNode.parentNode)
|
||||
: null,
|
||||
level = this._getLevel(this.placeholder),
|
||||
childLevels = this._getChildLevels(this.helper),
|
||||
previousItem = this.placeholder[0].previousSibling ? $(this.placeholder[0].previousSibling) : null;
|
||||
|
||||
if (previousItem != null) {
|
||||
while (previousItem[0].nodeName.toLowerCase() != 'li' || previousItem[0] == this.currentItem[0]) {
|
||||
if (previousItem[0].previousSibling) {
|
||||
previousItem = $(previousItem[0].previousSibling);
|
||||
} else {
|
||||
previousItem = null;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var newList = document.createElement(o.listType);
|
||||
|
||||
this.beyondMaxLevels = 0;
|
||||
|
||||
// If the item is moved to the left, send it to its parent level
|
||||
if (parentItem != null &&
|
||||
(o.rtl && (this.positionAbs.left + this.helper.outerWidth() > parentItem.offset().left + parentItem.outerWidth()) ||
|
||||
!o.rtl && (this.positionAbs.left < parentItem.offset().left))) {
|
||||
parentItem.after(this.placeholder[0]);
|
||||
this._clearEmpty(parentItem[0]);
|
||||
this._trigger("change", event, this._uiHash());
|
||||
}
|
||||
// If the item is below another one and is moved to the right, make it a children of it
|
||||
else if (previousItem != null &&
|
||||
(o.rtl && (this.positionAbs.left + this.helper.outerWidth() < previousItem.offset().left + previousItem.outerWidth() - o.tabSize) ||
|
||||
!o.rtl && (this.positionAbs.left > previousItem.offset().left + o.tabSize))) {
|
||||
this._isAllowed(previousItem, level, level + childLevels + 1);
|
||||
if (!previousItem.children(o.listType).length) {
|
||||
previousItem[0].appendChild(newList);
|
||||
}
|
||||
previousItem.children(o.listType)[0].appendChild(this.placeholder[0]);
|
||||
this._trigger("change", event, this._uiHash());
|
||||
}
|
||||
else {
|
||||
this._isAllowed(parentItem, level, level + childLevels);
|
||||
}
|
||||
|
||||
//Post events to containers
|
||||
this._contactContainers(event);
|
||||
|
||||
//Interconnect with droppables
|
||||
if ($.ui.ddmanager) $.ui.ddmanager.drag(this, event);
|
||||
|
||||
//Call callbacks
|
||||
this._trigger('sort', event, this._uiHash());
|
||||
|
||||
this.lastPositionAbs = this.positionAbs;
|
||||
return false;
|
||||
|
||||
},
|
||||
|
||||
_mouseStop: function (event, noPropagation) {
|
||||
|
||||
// If the item is in a position not allowed, send it back
|
||||
if (this.beyondMaxLevels) {
|
||||
|
||||
this.placeholder.removeClass(this.options.errorClass);
|
||||
|
||||
if (this.domPosition.prev) {
|
||||
$(this.domPosition.prev).after(this.placeholder);
|
||||
} else {
|
||||
$(this.domPosition.parent).prepend(this.placeholder);
|
||||
}
|
||||
|
||||
this._trigger("revert", event, this._uiHash());
|
||||
|
||||
}
|
||||
|
||||
// Clean last empty ul/ol
|
||||
for (var i = this.items.length - 1; i >= 0; i--) {
|
||||
var item = this.items[i].item[0];
|
||||
this._clearEmpty(item);
|
||||
}
|
||||
|
||||
$.ui.sortable.prototype._mouseStop.apply(this, arguments);
|
||||
|
||||
},
|
||||
|
||||
serialize: function (options) {
|
||||
|
||||
var o = $.extend({}, this.options, options),
|
||||
items = this._getItemsAsjQuery(o && o.connected),
|
||||
str = [];
|
||||
|
||||
$(items).each(function () {
|
||||
var res = ($(o.item || this).attr(o.attribute || 'id') || '')
|
||||
.match(o.expression || (/(.+)[-=_](.+)/)),
|
||||
pid = ($(o.item || this).parent(o.listType)
|
||||
.parent(o.items)
|
||||
.attr(o.attribute || 'id') || '')
|
||||
.match(o.expression || (/(.+)[-=_](.+)/));
|
||||
|
||||
if (res) {
|
||||
str.push(((o.key || res[1]) + '[' + (o.key && o.expression ? res[1] : res[2]) + ']')
|
||||
+ '='
|
||||
+ (pid ? (o.key && o.expression ? pid[1] : pid[2]) : o.rootID));
|
||||
}
|
||||
});
|
||||
|
||||
if (!str.length && o.key) {
|
||||
str.push(o.key + '=');
|
||||
}
|
||||
|
||||
return str.join('&');
|
||||
|
||||
},
|
||||
|
||||
toHierarchy: function (options) {
|
||||
|
||||
var o = $.extend({}, this.options, options),
|
||||
sDepth = o.startDepthCount || 0,
|
||||
ret = [];
|
||||
|
||||
$(this.element).children(o.items).each(function () {
|
||||
var level = _recursiveItems(this);
|
||||
ret.push(level);
|
||||
});
|
||||
|
||||
return ret;
|
||||
|
||||
function _recursiveItems(item) {
|
||||
var id = ($(item).attr(o.attribute || 'id') || '').match(o.expression || (/(.+)[-=_](.+)/));
|
||||
if (id) {
|
||||
var currentItem = { "id": id[2] };
|
||||
if ($(item).children(o.listType).children(o.items).length > 0) {
|
||||
currentItem.children = [];
|
||||
$(item).children(o.listType).children(o.items).each(function () {
|
||||
var level = _recursiveItems(this);
|
||||
currentItem.children.push(level);
|
||||
});
|
||||
}
|
||||
return currentItem;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
toArray: function (options) {
|
||||
|
||||
var o = $.extend({}, this.options, options),
|
||||
sDepth = o.startDepthCount || 0,
|
||||
ret = [],
|
||||
left = 2;
|
||||
|
||||
ret.push({
|
||||
"item_id": o.rootID,
|
||||
"parent_id": 'none',
|
||||
"depth": sDepth,
|
||||
"left": '1',
|
||||
"right": ($(o.items, this.element).length + 1) * 2
|
||||
});
|
||||
|
||||
$(this.element).children(o.items).each(function () {
|
||||
left = _recursiveArray(this, sDepth + 1, left);
|
||||
});
|
||||
|
||||
ret = ret.sort(function (a, b) { return (a.left - b.left); });
|
||||
|
||||
return ret;
|
||||
|
||||
function _recursiveArray(item, depth, left) {
|
||||
|
||||
var right = left + 1,
|
||||
id,
|
||||
pid;
|
||||
|
||||
if ($(item).children(o.listType).children(o.items).length > 0) {
|
||||
depth++;
|
||||
$(item).children(o.listType).children(o.items).each(function () {
|
||||
right = _recursiveArray($(this), depth, right);
|
||||
});
|
||||
depth--;
|
||||
}
|
||||
|
||||
id = ($(item).attr(o.attribute || 'id')).match(o.expression || (/(.+)[-=_](.+)/));
|
||||
|
||||
if (depth === sDepth + 1) {
|
||||
pid = o.rootID;
|
||||
} else {
|
||||
var parentItem = ($(item).parent(o.listType)
|
||||
.parent(o.items)
|
||||
.attr(o.attribute || 'id'))
|
||||
.match(o.expression || (/(.+)[-=_](.+)/));
|
||||
pid = parentItem[2];
|
||||
}
|
||||
|
||||
if (id) {
|
||||
ret.push({ "item_id": id[2], "parent_id": pid, "depth": depth, "left": left, "right": right });
|
||||
}
|
||||
|
||||
left = right + 1;
|
||||
return left;
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
_clearEmpty: function (item) {
|
||||
|
||||
var emptyList = $(item).children(this.options.listType);
|
||||
if (emptyList.length && !emptyList.children().length) {
|
||||
emptyList.remove();
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
_getLevel: function (item) {
|
||||
|
||||
var level = 1;
|
||||
|
||||
if (this.options.listType) {
|
||||
var list = item.closest(this.options.listType);
|
||||
while (!list.is('.ui-sortable')) {
|
||||
level++;
|
||||
list = list.parent().closest(this.options.listType);
|
||||
}
|
||||
}
|
||||
|
||||
return level;
|
||||
},
|
||||
|
||||
_getChildLevels: function (parent, depth) {
|
||||
var self = this,
|
||||
o = this.options,
|
||||
result = 0;
|
||||
depth = depth || 0;
|
||||
|
||||
$(parent).children(o.listType).children(o.items).each(function (index, child) {
|
||||
result = Math.max(self._getChildLevels(child, depth + 1), result);
|
||||
});
|
||||
|
||||
return depth ? result + 1 : result;
|
||||
},
|
||||
|
||||
_isAllowed: function (parentItem, level, levels) {
|
||||
var o = this.options,
|
||||
isRoot = $(this.domPosition.parent).hasClass('ui-sortable') ? true : false;
|
||||
|
||||
// Is the root protected?
|
||||
// Are we trying to nest under a no-nest?
|
||||
// Are we nesting too deep?
|
||||
if (!o.isAllowed(parentItem, this.placeholder) ||
|
||||
parentItem && parentItem.hasClass(o.disableNesting) ||
|
||||
o.protectRoot && (parentItem == null && !isRoot || isRoot && level > 1)) {
|
||||
this.placeholder.addClass(o.errorClass);
|
||||
if (o.maxLevels < levels && o.maxLevels != 0) {
|
||||
this.beyondMaxLevels = levels - o.maxLevels;
|
||||
} else {
|
||||
this.beyondMaxLevels = 1;
|
||||
}
|
||||
} else {
|
||||
if (o.maxLevels < levels && o.maxLevels != 0) {
|
||||
this.placeholder.addClass(o.errorClass);
|
||||
this.beyondMaxLevels = levels - o.maxLevels;
|
||||
} else {
|
||||
this.placeholder.removeClass(o.errorClass);
|
||||
this.beyondMaxLevels = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}));
|
||||
|
||||
$.mjs.nestedSortable.prototype.options = $.extend({}, $.ui.sortable.prototype.options, $.mjs.nestedSortable.prototype.options);
|
||||
})(jQuery);
|
45
src/Orchard.Web/Core/Navigation/Scripts/navigation-admin.js
Normal file
45
src/Orchard.Web/Core/Navigation/Scripts/navigation-admin.js
Normal file
@ -0,0 +1,45 @@
|
||||
|
||||
(function ($) {
|
||||
|
||||
var populate = function (el, prefix) {
|
||||
var pos = 1;
|
||||
|
||||
// direct children
|
||||
var children = $(el).children('li').each(function (i, child) {
|
||||
if (!prefix) prefix = '';
|
||||
child = $(child);
|
||||
|
||||
// apply positions to all siblings
|
||||
child.find('.navigation-position > input').attr('value', prefix + pos);
|
||||
|
||||
// recurse position for children
|
||||
child.children('ol').each(function (i, item) { populate(item, prefix + pos.toString() + '.') });
|
||||
|
||||
pos++;
|
||||
|
||||
});
|
||||
};
|
||||
|
||||
$('.navigation-menu > ol').nestedSortable({
|
||||
disableNesting: 'no-nest',
|
||||
forcePlaceholderSize: true,
|
||||
handle: 'div',
|
||||
helper: 'clone',
|
||||
items: 'li',
|
||||
maxLevels: 6,
|
||||
opacity: 1,
|
||||
placeholder: 'navigation-placeholder',
|
||||
revert: 50,
|
||||
tabSize: 30,
|
||||
tolerance: 'pointer',
|
||||
toleranceElement: '> div',
|
||||
|
||||
stop: function (event, ui) {
|
||||
// update all positions whenever a menu item was moved
|
||||
populate(this, '');
|
||||
$('#save-message').show();
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
})(jQuery);
|
@ -0,0 +1,28 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Orchard.ContentManagement;
|
||||
|
||||
namespace Orchard.Core.Navigation.Services {
|
||||
/// <summary>
|
||||
/// Implements <see cref="IMenuManager"/> by searching for the <code>MenuItem</code> stereotype in the content type's settings.
|
||||
/// </summary>
|
||||
public class DefaultMenuManager : IMenuManager {
|
||||
private readonly IContentManager _contentManager;
|
||||
|
||||
public DefaultMenuManager(IContentManager contentManager) {
|
||||
_contentManager = contentManager;
|
||||
}
|
||||
|
||||
public IEnumerable<MenuItemDescriptor> GetMenuItemTypes() {
|
||||
return _contentManager.GetContentTypeDefinitions()
|
||||
.Where(contentTypeDefinition => contentTypeDefinition.Settings.ContainsKey("Stereotype") && contentTypeDefinition.Settings["Stereotype"] == "MenuItem")
|
||||
.Select(contentTypeDefinition =>
|
||||
new MenuItemDescriptor {
|
||||
Type = contentTypeDefinition.Name,
|
||||
DisplayName = contentTypeDefinition.DisplayName,
|
||||
Description = contentTypeDefinition.Settings.ContainsKey("Description") ? contentTypeDefinition.Settings["Description"] : null
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,42 @@
|
||||
using System.Web;
|
||||
using Orchard.ContentManagement;
|
||||
using Orchard.ContentManagement.Aspects;
|
||||
using Orchard.Core.Navigation.Models;
|
||||
using Orchard.Localization;
|
||||
using Orchard.UI.Navigation;
|
||||
|
||||
namespace Orchard.Core.Navigation.Services {
|
||||
public class DefaultMenuProvider : IMenuProvider {
|
||||
private readonly IContentManager _contentManager;
|
||||
|
||||
public DefaultMenuProvider(IContentManager contentManager) {
|
||||
_contentManager = contentManager;
|
||||
}
|
||||
|
||||
public void GetMenu(IContent menu, NavigationBuilder builder) {
|
||||
var menuParts = _contentManager
|
||||
.Query<MenuPart, MenuPartRecord>()
|
||||
.Where(x => x.MenuId == menu.Id)
|
||||
.WithQueryHints(new QueryHints().ExpandRecords<MenuItemPartRecord>())
|
||||
.List();
|
||||
|
||||
foreach (var menuPart in menuParts) {
|
||||
if (menuPart != null) {
|
||||
var part = menuPart;
|
||||
|
||||
// fetch the culture of the menu item, if any
|
||||
string culture = null;
|
||||
var localized = part.As<ILocalizableAspect>();
|
||||
if(localized != null) {
|
||||
culture = localized.Culture;
|
||||
}
|
||||
|
||||
if (part.Is<MenuItemPart>())
|
||||
builder.Add(new LocalizedString(HttpUtility.HtmlEncode(part.MenuText)), part.MenuPosition, item => item.Url(part.As<MenuItemPart>().Url).Content(part).Culture(culture));
|
||||
else
|
||||
builder.Add(new LocalizedString(HttpUtility.HtmlEncode(part.MenuText)), part.MenuPosition, item => item.Action(_contentManager.GetItemMetadata(part.ContentItem).DisplayRouteValues).Content(part).Culture(culture));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
18
src/Orchard.Web/Core/Navigation/Services/IMenuManager.cs
Normal file
18
src/Orchard.Web/Core/Navigation/Services/IMenuManager.cs
Normal file
@ -0,0 +1,18 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Orchard.Core.Navigation.Services {
|
||||
public interface IMenuManager : IDependency {
|
||||
|
||||
/// <summary>
|
||||
/// Gets the list of Menu Item content types
|
||||
/// </summary>
|
||||
/// <returns>An IEnumerable{MenuItemDescriptor} containing the menu items content types.</returns>
|
||||
IEnumerable<MenuItemDescriptor> GetMenuItemTypes();
|
||||
}
|
||||
|
||||
public class MenuItemDescriptor {
|
||||
public string Type { get; set; }
|
||||
public string DisplayName { get; set; }
|
||||
public string Description { get; set; }
|
||||
}
|
||||
}
|
@ -1,10 +1,16 @@
|
||||
using System.Collections.Generic;
|
||||
using Orchard.ContentManagement;
|
||||
using Orchard.Core.Navigation.Models;
|
||||
|
||||
namespace Orchard.Core.Navigation.Services {
|
||||
public interface IMenuService : IDependency {
|
||||
IEnumerable<MenuPart> Get();
|
||||
MenuPart Get(int menuPartId);
|
||||
IEnumerable<MenuPart> GetMenuParts(int menuId);
|
||||
MenuPart Get(int id);
|
||||
IContent GetMenu(int menuId);
|
||||
IContent GetMenu(string name);
|
||||
IEnumerable<ContentItem> GetMenus();
|
||||
IContent Create(string name);
|
||||
void Delete(MenuPart menuPart);
|
||||
}
|
||||
}
|
@ -1,33 +0,0 @@
|
||||
using System.Web;
|
||||
using JetBrains.Annotations;
|
||||
using Orchard.ContentManagement;
|
||||
using Orchard.Core.Navigation.Models;
|
||||
using Orchard.Localization;
|
||||
using Orchard.UI.Navigation;
|
||||
|
||||
namespace Orchard.Core.Navigation.Services {
|
||||
[UsedImplicitly]
|
||||
public class MainMenuNavigationProvider : INavigationProvider {
|
||||
private readonly IContentManager _contentManager;
|
||||
|
||||
public MainMenuNavigationProvider(IContentManager contentManager) {
|
||||
_contentManager = contentManager;
|
||||
}
|
||||
|
||||
public string MenuName { get { return "main"; } }
|
||||
|
||||
public void GetNavigation(NavigationBuilder builder) {
|
||||
var menuParts = _contentManager.Query<MenuPart, MenuPartRecord>().Where(x => x.OnMainMenu).WithQueryHints(new QueryHints().ExpandRecords<MenuItemPartRecord>()).List();
|
||||
foreach (var menuPart in menuParts) {
|
||||
if (menuPart != null) {
|
||||
var part = menuPart;
|
||||
|
||||
if (part.Is<MenuItemPart>())
|
||||
builder.Add(new LocalizedString(HttpUtility.HtmlEncode(part.MenuText)), part.MenuPosition, item => item.Url(part.As<MenuItemPart>().Url));
|
||||
else
|
||||
builder.Add(new LocalizedString(HttpUtility.HtmlEncode(part.MenuText)), part.MenuPosition, item => item.Action(_contentManager.GetItemMetadata(part.ContentItem).DisplayRouteValues));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,7 +1,10 @@
|
||||
using System.Collections.Generic;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using JetBrains.Annotations;
|
||||
using Orchard.ContentManagement;
|
||||
using Orchard.Core.Navigation.Models;
|
||||
using Orchard.Core.Title.Models;
|
||||
|
||||
namespace Orchard.Core.Navigation.Services {
|
||||
[UsedImplicitly]
|
||||
@ -13,15 +16,54 @@ namespace Orchard.Core.Navigation.Services {
|
||||
}
|
||||
|
||||
public IEnumerable<MenuPart> Get() {
|
||||
return _contentManager.Query<MenuPart, MenuPartRecord>().Where(x => x.OnMainMenu).List();
|
||||
return _contentManager.Query<MenuPart, MenuPartRecord>().List();
|
||||
}
|
||||
|
||||
public IEnumerable<MenuPart> GetMenuParts(int menuId) {
|
||||
return _contentManager
|
||||
.Query<MenuPart, MenuPartRecord>()
|
||||
.Where( x => x.MenuId == menuId)
|
||||
.List();
|
||||
}
|
||||
|
||||
public IContent GetMenu(string menuName) {
|
||||
if(string.IsNullOrWhiteSpace(menuName)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return _contentManager.Query<TitlePart, TitlePartRecord>()
|
||||
.Where(x => x.Title == menuName)
|
||||
.ForType("Menu")
|
||||
.Slice(0, 1)
|
||||
.FirstOrDefault();
|
||||
}
|
||||
|
||||
public IContent GetMenu(int menuId) {
|
||||
return _contentManager.Get(menuId, VersionOptions.Published, new QueryHints().ExpandRecords<TitlePartRecord>());
|
||||
}
|
||||
|
||||
public MenuPart Get(int menuPartId) {
|
||||
return _contentManager.Get<MenuPart>(menuPartId);
|
||||
}
|
||||
|
||||
public IContent Create(string name) {
|
||||
|
||||
if(string.IsNullOrWhiteSpace(name)) {
|
||||
throw new ArgumentNullException(name);
|
||||
}
|
||||
|
||||
var menu = _contentManager.Create("Menu");
|
||||
menu.As<TitlePart>().Title = name;
|
||||
|
||||
return menu;
|
||||
}
|
||||
|
||||
public void Delete(MenuPart menuPart) {
|
||||
_contentManager.Remove(menuPart.ContentItem);
|
||||
}
|
||||
|
||||
public IEnumerable<ContentItem> GetMenus() {
|
||||
return _contentManager.Query().ForType("Menu").Join<TitlePartRecord>().OrderBy(x => x.Title).List();
|
||||
}
|
||||
}
|
||||
}
|
BIN
src/Orchard.Web/Core/Navigation/Styles/images/move.gif
Normal file
BIN
src/Orchard.Web/Core/Navigation/Styles/images/move.gif
Normal file
Binary file not shown.
After Width: | Height: | Size: 897 B |
145
src/Orchard.Web/Core/Navigation/Styles/navigation-admin.css
Normal file
145
src/Orchard.Web/Core/Navigation/Styles/navigation-admin.css
Normal file
@ -0,0 +1,145 @@
|
||||
#save-message {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.navigation-menu ol ol {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
padding-left: 30px; /* gap between each level */
|
||||
}
|
||||
|
||||
.navigation-menu ol.sortable, .navigation-menu ol.sortable ol {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
list-style-type: none;
|
||||
}
|
||||
|
||||
.navigation-menu ol.sortable {
|
||||
}
|
||||
|
||||
.navigation-menu li {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.navigation-menu li div {
|
||||
border: 1px solid #ccc;
|
||||
cursor: move;
|
||||
padding: 3px 10px 3px 30px;
|
||||
margin: 2px;
|
||||
background: #eee;
|
||||
display: inline-block;
|
||||
min-width: 200px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.navigation-menu li div:hover {
|
||||
background: #eee url(images/move.gif) no-repeat 9px 7px;
|
||||
border: 1px solid #999;
|
||||
}
|
||||
|
||||
.navigation-menu-item h2
|
||||
{
|
||||
display: inline;
|
||||
font-size:1.077em;
|
||||
}
|
||||
|
||||
.navigation-position
|
||||
{
|
||||
display: none;
|
||||
}
|
||||
|
||||
.navigation-url
|
||||
{
|
||||
}
|
||||
|
||||
.navigation-actions
|
||||
{
|
||||
float: right;
|
||||
}
|
||||
|
||||
/* style for the dynamically created placeholder */
|
||||
.navigation-menu li.navigation-placeholder
|
||||
{
|
||||
background: #dadada;
|
||||
}
|
||||
|
||||
|
||||
/* layout */
|
||||
|
||||
#display-menu-controls {
|
||||
display: block;
|
||||
}
|
||||
|
||||
#display-menu-controls form, #display-menu-controls fieldset {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
#navigation-menu-add {
|
||||
display: inline;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.sections {
|
||||
}
|
||||
|
||||
.primary
|
||||
{
|
||||
float: left;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.container
|
||||
{
|
||||
margin-right:350px;
|
||||
}
|
||||
|
||||
.secondary
|
||||
{
|
||||
padding:0;
|
||||
margin:0;
|
||||
margin-top:2px;
|
||||
float:right;
|
||||
width:300px;
|
||||
margin-left: -300px;
|
||||
}
|
||||
|
||||
.menu-items-zone {
|
||||
/*background: #F3F4F5;*/
|
||||
/*border:1px solid #E4E5E6;*/
|
||||
padding:0px;
|
||||
}
|
||||
|
||||
.menu-items-zone h2 {
|
||||
font-size:1.077em;
|
||||
padding:2px 2px;
|
||||
}
|
||||
|
||||
.menu-items-zone li {
|
||||
background:#FFF;
|
||||
border:1px solid #CCC;
|
||||
margin-bottom: 5px;
|
||||
padding: 5px;
|
||||
padding-right:65px;
|
||||
display: block;
|
||||
position:relative;
|
||||
}
|
||||
|
||||
div.menu-item-description {
|
||||
display: block;
|
||||
}
|
||||
|
||||
div.menu-item-actions {
|
||||
display: block;
|
||||
position:absolute;
|
||||
right:10px;
|
||||
top:15px;
|
||||
}
|
||||
|
||||
.menu-items-zone li a {
|
||||
border:1px solid #EAEAEA;
|
||||
}
|
||||
|
||||
.menu-items-zone li a:hover {
|
||||
border-color:#487328;
|
||||
}
|
@ -0,0 +1,8 @@
|
||||
using Orchard.Core.Navigation.Models;
|
||||
|
||||
namespace Orchard.Core.Navigation.ViewModels {
|
||||
public class ContentMenuItemEditViewModel {
|
||||
public int ContentItemId { get; set; }
|
||||
public ContentMenuItemPart Part { get; set; }
|
||||
}
|
||||
}
|
@ -1,4 +1,5 @@
|
||||
using Orchard.UI.Navigation;
|
||||
using Orchard.ContentManagement;
|
||||
|
||||
namespace Orchard.Core.Navigation.ViewModels {
|
||||
public class MenuItemEntry {
|
||||
@ -8,5 +9,7 @@ namespace Orchard.Core.Navigation.ViewModels {
|
||||
public string Text { get; set; }
|
||||
public string Url { get; set; }
|
||||
public string Position { get; set; }
|
||||
|
||||
public ContentItem ContentItem { get; set; }
|
||||
}
|
||||
}
|
@ -0,0 +1,13 @@
|
||||
using System.Collections.Generic;
|
||||
using Orchard.ContentManagement;
|
||||
|
||||
namespace Orchard.Core.Navigation.ViewModels {
|
||||
public class MenuPartViewModel {
|
||||
public IEnumerable<ContentItem> Menus { get; set; }
|
||||
public int CurrentMenuId { get; set; }
|
||||
public bool OnMenu { get; set; }
|
||||
|
||||
public ContentItem ContentItem { get; set; }
|
||||
public string MenuText { get; set; }
|
||||
}
|
||||
}
|
@ -0,0 +1,15 @@
|
||||
using System.Collections.Generic;
|
||||
using Orchard.ContentManagement;
|
||||
|
||||
namespace Orchard.Core.Navigation.ViewModels {
|
||||
public class MenuWidgetViewModel {
|
||||
public IEnumerable<ContentItem> Menus { get; set; }
|
||||
public int CurrentMenuId { get; set; }
|
||||
|
||||
public int StartLevel { get; set; }
|
||||
public int StopLevel { get; set; }
|
||||
public bool Breadcrumb { get; set; }
|
||||
public bool AddHomePage { get; set; }
|
||||
public bool AddCurrentPage { get; set; }
|
||||
}
|
||||
}
|
@ -1,5 +1,7 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Orchard.ContentManagement;
|
||||
using Orchard.Core.Navigation.Services;
|
||||
|
||||
namespace Orchard.Core.Navigation.ViewModels {
|
||||
public class NavigationManagementViewModel {
|
||||
@ -9,5 +11,9 @@ namespace Orchard.Core.Navigation.ViewModels {
|
||||
|
||||
public MenuItemEntry NewMenuItem { get; set; }
|
||||
public IList<MenuItemEntry> MenuItemEntries { get; set; }
|
||||
public IEnumerable<MenuItemDescriptor> MenuItemDescriptors { get; set; }
|
||||
|
||||
public IEnumerable<IContent> Menus { get; set; }
|
||||
public IContent CurrentMenu { get; set; }
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,9 @@
|
||||
using System.Collections.Generic;
|
||||
using Orchard.Core.Navigation.Models;
|
||||
|
||||
namespace Orchard.Core.Navigation.ViewModels {
|
||||
public class NavigationPartViewModel {
|
||||
public IEnumerable<MenuPart> ContentMenuItems { get; set; }
|
||||
public NavigationPart Part { get; set; }
|
||||
}
|
||||
}
|
@ -0,0 +1,7 @@
|
||||
@{ Layout.Title = T("Create Menu Item").ToString(); }
|
||||
|
||||
@using (Html.BeginFormAntiForgeryPost()) {
|
||||
@Html.ValidationSummary()
|
||||
// Model is a Shape, calling Display() so that it is rendered using the most specific template for its Shape type
|
||||
@Display(Model)
|
||||
}
|
@ -1,69 +1,127 @@
|
||||
@model NavigationManagementViewModel
|
||||
@using Orchard.ContentManagement;
|
||||
@using Orchard.Core.Navigation.Models;
|
||||
@using Orchard.Core.Navigation.ViewModels;
|
||||
@using Orchard.Utility.Extensions;
|
||||
|
||||
@{ Layout.Title = T("Navigation").ToString(); }
|
||||
@{
|
||||
Layout.Title = T("Navigation").ToString();
|
||||
Style.Include("navigation-admin.css");
|
||||
|
||||
@using (Html.BeginFormAntiForgeryPost()) {
|
||||
<table class="items">
|
||||
<colgroup>
|
||||
<col id="Text" />
|
||||
<col id="Position" />
|
||||
<col id="Url" />
|
||||
<col id="Actions" />
|
||||
</colgroup>
|
||||
<thead>
|
||||
<tr>
|
||||
<td scope="col">@T("Text")</td>
|
||||
<td scope="col">@T("Position")</td>
|
||||
<td scope="col">@T("Url")</td>
|
||||
<td scope="col"></td>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>@{
|
||||
var menuPartEntryIndex = 0;
|
||||
foreach (var menuPartEntry in Model.MenuItemEntries) {
|
||||
var i = menuPartEntryIndex;
|
||||
<tr>
|
||||
<td><input type="text" class="text-box" name="@Html.NameOf(m => m.MenuItemEntries[i].Text)" value="@menuPartEntry.Text" /></td>
|
||||
<td><input type="text" class="text-box" name="@Html.NameOf(m => m.MenuItemEntries[i].Position)" value="@menuPartEntry.Position" /></td>
|
||||
<td>@if (!menuPartEntry.IsMenuItem) {<input type="text" class="text-box disabled" disabled="disabled" value="@menuPartEntry.Url" /> } else {<input type="text" class="text-box" name="@Html.NameOf(m => m.MenuItemEntries[i].Url)" value="@menuPartEntry.Url" />}</td>
|
||||
<td><input type="hidden" name="@Html.NameOf(m => m.MenuItemEntries[i].MenuItemId)" value="@menuPartEntry.MenuItemId" />@Html.ActionLink(T("Delete").Text, "Delete", new { id = menuPartEntry.MenuItemId }, new { @class="remove", itemprop="RemoveUrl UnsafeUrl" })</td>
|
||||
</tr>
|
||||
++menuPartEntryIndex;
|
||||
}
|
||||
}
|
||||
</tbody>
|
||||
</table>
|
||||
<fieldset class="actions"><button type="submit" class="button">@T("Update All")</button></fieldset>
|
||||
Script.Require("jQueryUI_Sortable");
|
||||
Script.Include("jquery.mjs.nestedSortable.js");
|
||||
Script.Include("navigation-admin.js");
|
||||
}
|
||||
|
||||
<h2>@T("Add New Item")</h2>
|
||||
@using (Html.BeginFormAntiForgeryPost(Url.Action("create"), FormMethod.Post)) {
|
||||
<table class="menu items">
|
||||
<colgroup>
|
||||
<col id="AddText" />
|
||||
<col id="AddPosition" />
|
||||
<col id="AddUrl" />
|
||||
<col id="AddActions" />
|
||||
</colgroup>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>
|
||||
<label for="MenuText">@T("Text")</label>
|
||||
@Html.EditorFor(m => m.NewMenuItem.Text)
|
||||
</td>
|
||||
<td>
|
||||
<label for="MenuPosition">@T("Position")</label>
|
||||
@Html.EditorFor(m => m.NewMenuItem.Position)
|
||||
</td>
|
||||
<td>
|
||||
<label for="Url">@T("Url")</label>
|
||||
@Html.EditorFor(m => m.NewMenuItem.Url)
|
||||
</td>
|
||||
<td><button class="add" type="submit">@T("Add")</button></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
}
|
||||
<div id="save-message" class="message message-Warning">@T("You need to hit \"Save All\" in order to save your changes.")</div>
|
||||
|
||||
<div id="display-menu-controls">
|
||||
@if (Model.Menus.Any()) {
|
||||
using (Html.BeginForm("Index", "Admin", FormMethod.Get, new { area = "Navigation" })) {
|
||||
<fieldset class="bulk-actions-auto">
|
||||
<label for="menuId">@T("Current Menu:")</label>
|
||||
<select id="menuId" name="menuId">
|
||||
@foreach (var menu in Model.Menus) {
|
||||
@Html.SelectOption(Model.CurrentMenu.Id, menu.Id, Html.ItemDisplayText(menu).ToString())
|
||||
}
|
||||
</select>
|
||||
<button type="submit" class="apply-bulk-actions-auto">@T("Show")</button>
|
||||
@Html.ActionLink(T("Edit").Text, "Edit", "Admin", new { area = "Contents", id = Model.CurrentMenu.Id, returnUrl = Url.Action("Index", "Admin", new { area = "Navigation" }) }, new { @class = "button" })
|
||||
</fieldset>
|
||||
}
|
||||
}
|
||||
<div id="navigation-menu-add">
|
||||
@Html.Link(T("Add a new menu...").Text, Url.Action("Create", "Admin", new { area = "Contents", id = "Menu", returnUrl = Request.RawUrl }))
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@using (Html.BeginFormAntiForgeryPost()) {
|
||||
<div class="sections">
|
||||
<div class="primary">
|
||||
<div class="container">
|
||||
<div class="navigation-menu">
|
||||
@if (Model.MenuItemEntries.Any()) {
|
||||
@RenderMenuItems(Model.MenuItemEntries, 0)
|
||||
}
|
||||
else {
|
||||
<h2>@T("The menu is empty")</h2>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="secondary">
|
||||
<ul class="menu-items-zone">
|
||||
@foreach (var descriptor in Model.MenuItemDescriptors.OrderBy(x => x.DisplayName)) {
|
||||
<li>
|
||||
<div class="menu-item-description"><h2>@descriptor.DisplayName.CamelFriendly()</h2>
|
||||
@if (!string.IsNullOrWhiteSpace(descriptor.Description)) {
|
||||
<span class="hint">@descriptor.Description</span>
|
||||
}
|
||||
</div>
|
||||
<div class="menu-item-actions">@Html.ActionLink(T("Add").Text, "CreateMenuItem", "Admin", new { area = "Navigation", id = descriptor.Type, menuId = Model.CurrentMenu.Id, returnUrl = Request.RawUrl }, new { @class = "button grey" })</div>
|
||||
</li>
|
||||
}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<fieldset class="actions">
|
||||
<button type="submit" class="button">@T("Save All")</button>
|
||||
</fieldset>
|
||||
}
|
||||
|
||||
|
||||
@helper RenderMenuItems(IList<MenuItemEntry> menuItems, int index) {
|
||||
|
||||
@:<ol>
|
||||
|
||||
// store current level to detect lowerb or upper level
|
||||
int currentLevel = Model.MenuItemEntries[index].Position.Split('.').Length - 1;
|
||||
bool first = true;
|
||||
|
||||
for (int i = index; i < Model.MenuItemEntries.Count; i++) {
|
||||
|
||||
var menuPartEntry = Model.MenuItemEntries[i];
|
||||
var level = menuPartEntry.Position.Split('.').Length - 1; // 0 is for root level
|
||||
|
||||
if (level > currentLevel) {
|
||||
// render sub level, then continue to next element
|
||||
@RenderMenuItems(menuItems, i)
|
||||
|
||||
var j = i;
|
||||
while (j < Model.MenuItemEntries.Count && Model.MenuItemEntries[j].Position.Split('.').Length - 1 > currentLevel) { j++; };
|
||||
i = j - 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (level == currentLevel) {
|
||||
if (!first) {
|
||||
@:</li>
|
||||
}
|
||||
|
||||
first = false;
|
||||
|
||||
@:<li class="navigation-menu-item" data-index="@i">
|
||||
|
||||
<div>
|
||||
<h2>@menuPartEntry.Text</h2>
|
||||
<span class="navigation-type">(@menuPartEntry.ContentItem.TypeDefinition.DisplayName)</span>
|
||||
<span class="navigation-position"><input type="text" class="text-box" name="@Html.NameOf(m => m.MenuItemEntries[i].Position)" value="@menuPartEntry.Position" /></span>
|
||||
<span class="navigation-actions">
|
||||
<input type="hidden" name="@Html.NameOf(m => m.MenuItemEntries[i].MenuItemId)" value="@menuPartEntry.MenuItemId" />
|
||||
@Html.ItemEditLink(T("Edit").Text, menuPartEntry.ContentItem, new { returnUrl = Request.RawUrl })@T(" | ")
|
||||
@Html.ActionLink(T("Delete").Text, "Delete", new { id = menuPartEntry.MenuItemId }, new { @class = "remove", itemprop = "RemoveUrl UnsafeUrl" })
|
||||
</span>
|
||||
</div>
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
// done with current level
|
||||
if (level < currentLevel) {
|
||||
@:</li>
|
||||
break;
|
||||
}
|
||||
}
|
||||
@:</ol>
|
||||
}
|
||||
|
@ -0,0 +1,25 @@
|
||||
@{
|
||||
Model.Sidebar.Add(New.Menu_DeleteButton().ContentItem(Model.ContentItem), "25");
|
||||
}
|
||||
|
||||
<div class="edit-item">
|
||||
<div class="edit-item-primary">
|
||||
@if (Model.Content != null) {
|
||||
<div class="edit-item-content">
|
||||
@Display(Model.Content)
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
<div class="edit-item-secondary group">
|
||||
@if (Model.Actions != null) {
|
||||
<div class="edit-item-actions">
|
||||
@Display(Model.Actions)
|
||||
</div>
|
||||
}
|
||||
@if (Model.Sidebar != null) {
|
||||
<div class="edit-item-sidebar group">
|
||||
@Display(Model.Sidebar)
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
@ -0,0 +1,36 @@
|
||||
@model Orchard.Core.Navigation.ViewModels.ContentMenuItemEditViewModel
|
||||
@{
|
||||
Script.Require("ContentPicker").AtFoot();
|
||||
var title = Model.Part.Content == null ? new HtmlString(T("Empty").Text) : Html.ItemDisplayText(Model.Part.Content);
|
||||
}
|
||||
<fieldset>
|
||||
<label>@T("Content Item")</label>
|
||||
<span id="title-@Html.FieldIdFor(m => m.ContentItemId)" class="content-picker-title">@title</span>
|
||||
<span id="btn-@Html.FieldIdFor(m => m.ContentItemId)" class="button">@T("Browse")</span>
|
||||
|
||||
@Html.HiddenFor(m => m.ContentItemId)
|
||||
<span class="hint">@T("Select the Content Item to display in the menu.")</span>
|
||||
</fieldset>
|
||||
|
||||
@using(Script.Foot()) {
|
||||
<script type="text/javascript">
|
||||
//<![CDATA[
|
||||
jQuery('#btn-@Html.FieldIdFor(m => m.ContentItemId)').click(function() {
|
||||
jQuery('#btn-@Html.FieldIdFor(m => m.ContentItemId)').trigger("orchard-admin-contentpicker-open", {
|
||||
callback: function(data) {
|
||||
|
||||
jQuery('#@Html.FieldIdFor(m => m.ContentItemId)').val(data.id);
|
||||
|
||||
jQuery('#title-@Html.FieldIdFor(m => m.ContentItemId)').text(data.displayText);
|
||||
|
||||
// define the menu text if it's empty
|
||||
var menuText = jQuery('#MenuText');
|
||||
if (menuText.val().length == 0) {
|
||||
menuText.val(data.displayText);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
//]]>
|
||||
</script>
|
||||
}
|
@ -0,0 +1,8 @@
|
||||
@model MenuItemPart
|
||||
@using Orchard.Core.Navigation.Models;
|
||||
|
||||
<fieldset>
|
||||
<label for="@Html.FieldIdFor(m => m.Url)">@T("Url")</label>
|
||||
@Html.TextBoxFor(m => m.Url, new { @class = "large text" })
|
||||
<span class="hint">@T("A valid url, i.e. ~/my-page, http://orchardproject.net, /content/file.pdf, ...")</span>
|
||||
</fieldset>
|
@ -0,0 +1,45 @@
|
||||
@model Orchard.Core.Navigation.ViewModels.MenuWidgetViewModel
|
||||
@using Orchard.ContentManagement
|
||||
@using Orchard.Core.Navigation.Models;
|
||||
|
||||
<fieldset>
|
||||
@Html.LabelFor(m => m.CurrentMenuId, T("For Menu"))
|
||||
<select id="@Html.FieldIdFor(m => m.CurrentMenuId)" name="@Html.FieldNameFor(m => m.CurrentMenuId)">
|
||||
@foreach(ContentItem menu in Model.Menus) {
|
||||
@Html.SelectOption(Model.CurrentMenuId, menu.Id, Html.ItemDisplayText(menu).ToString())
|
||||
}
|
||||
</select>
|
||||
<span class="hint">@T("Select which menu you want to display")</span>
|
||||
</fieldset>
|
||||
|
||||
<fieldset>
|
||||
<label for="@Html.FieldIdFor(m => m.StartLevel)">@T("Start Level")</label>
|
||||
@Html.TextBoxFor(m => m.StartLevel, new { @class = "text text-small" })
|
||||
<span class="hint">@T("The level the menu should start at.")</span>
|
||||
</fieldset>
|
||||
|
||||
<fieldset>
|
||||
<label for="@Html.FieldIdFor(m => m.StopLevel)">@T("Levels to display")</label>
|
||||
@Html.TextBoxFor(m => m.StopLevel, new { @class = "text text-small" })
|
||||
<span class="hint">@T("The number of levels to display, \"0\" meaning all levels.")</span>
|
||||
</fieldset>
|
||||
|
||||
<fieldset>
|
||||
@Html.EditorFor(m => m.Breadcrumb)
|
||||
<label class="forcheckbox" for="@Html.FieldIdFor(m => m.Breadcrumb)">@T("Display as Breadcrumb")</label>
|
||||
<span class="hint">@T("Check to render the path to the current content item.")</span>
|
||||
</fieldset>
|
||||
|
||||
<div data-controllerid="@Html.FieldIdFor(m => m.Breadcrumb)">
|
||||
<fieldset>
|
||||
@Html.EditorFor(m => m.AddHomePage)
|
||||
<label class="forcheckbox" for="@Html.FieldIdFor(m => m.AddHomePage)">@T("Add the home page as the first element")</label>
|
||||
<span class="hint">@T("Check to render the home page as the first element of the breadcrumb.")</span>
|
||||
</fieldset>
|
||||
|
||||
<fieldset>
|
||||
@Html.EditorFor(m => m.AddCurrentPage)
|
||||
<label class="forcheckbox" for="@Html.FieldIdFor(m => m.AddCurrentPage)">@T("Add the current content item as the last element")</label>
|
||||
<span class="hint">@T("Check to render the current content item as the last element.")</span>
|
||||
</fieldset>
|
||||
</div>
|
@ -0,0 +1,26 @@
|
||||
@model Orchard.Core.Navigation.ViewModels.NavigationPartViewModel
|
||||
@using Orchard.ContentManagement
|
||||
|
||||
@{
|
||||
var contentManager = WorkContext.Resolve<IContentManager>();
|
||||
}
|
||||
<fieldset>
|
||||
<label>@T("Menu Items")</label>
|
||||
<span class="hint">@T("The menu items linking to this content item.")</span>
|
||||
@if(Model.ContentMenuItems.Any()) {
|
||||
<ul>
|
||||
@foreach(var menuPart in Model.ContentMenuItems) {
|
||||
var menuContentItem = contentManager.Get(menuPart.Menu.Id);
|
||||
var menuName = Html.ItemDisplayText(menuContentItem).ToString();
|
||||
<li>
|
||||
<div><span>@menuPart.MenuText</span> @T("on") <span>@Html.ActionLink(menuName, "Index", "Admin", new { area = "Navigation", menuId = menuContentItem.Id }, new {}) </span></div>
|
||||
</li>
|
||||
}
|
||||
</ul>
|
||||
}
|
||||
else {
|
||||
@T("Not displayed in any menu.")
|
||||
}
|
||||
|
||||
|
||||
</fieldset>
|
@ -1,13 +1,36 @@
|
||||
@model MenuPart
|
||||
@model Orchard.Core.Navigation.ViewModels.MenuPartViewModel
|
||||
@using Orchard.ContentManagement
|
||||
@using Orchard.Core.Navigation.Models;
|
||||
@{
|
||||
Script.Require("ShapesBase");
|
||||
|
||||
@if (!Model.ContentItem.TypeDefinition.Settings.ContainsKey("Stereotype") || Model.ContentItem.TypeDefinition.Settings["Stereotype"] != "MenuItem") {
|
||||
|
||||
<fieldset>
|
||||
|
||||
@Html.EditorFor(m => m.OnMenu)
|
||||
<label for="@Html.FieldIdFor(m => m.OnMenu)" class="forcheckbox">@T("Show on a menu")</label>
|
||||
<div data-controllerid="@Html.FieldIdFor(m => m.OnMenu)" class="">
|
||||
<select id="@Html.FieldIdFor(m => m.CurrentMenuId)" name="@Html.FieldNameFor(m => m.CurrentMenuId)">
|
||||
@foreach (ContentItem menu in Model.Menus) {
|
||||
@Html.SelectOption(Model.CurrentMenuId, menu.Id, Html.ItemDisplayText(menu).ToString())
|
||||
}
|
||||
</select>
|
||||
<span class="hint">@T("Select which menu you want the content item to be displayed on.")</span>
|
||||
|
||||
<label for="MenuText">@T("Menu text")</label>
|
||||
@Html.TextBoxFor(m => m.MenuText, new { @class = "text-box single-line" })
|
||||
<span class="hint">@T("The text that should appear in the menu.")</span>
|
||||
</div>
|
||||
</fieldset>
|
||||
|
||||
}
|
||||
<fieldset>
|
||||
@Html.EditorFor(m => m.OnMainMenu)
|
||||
<label for="OnMainMenu" class="forcheckbox">@T("Show on main menu")</label>
|
||||
<div data-controllerid="OnMainMenu" class="">
|
||||
else {
|
||||
|
||||
<fieldset>
|
||||
<label for="MenuText">@T("Menu text")</label>
|
||||
@Html.TextBoxFor(m => m.MenuText, new { @class = "text-box single-line" })
|
||||
</div>
|
||||
</fieldset>
|
||||
@Html.TextBoxFor(m => m.MenuText, new { @class = "textMedium", autofocus = "autofocus" })
|
||||
<span class="hint">@T("The text that should appear in the menu.")</span>
|
||||
@Html.HiddenFor(m => m.OnMenu, true)
|
||||
@Html.HiddenFor(m => m.CurrentMenuId, Request["menuId"])
|
||||
</fieldset>
|
||||
|
||||
}
|
@ -0,0 +1,14 @@
|
||||
@using Orchard.ContentManagement;
|
||||
@using Orchard.Core.Contents
|
||||
@using Orchard.Utility.Extensions;
|
||||
|
||||
@{
|
||||
ContentItem contentItem = Model.ContentItem;
|
||||
string returnUrl = Request["returnUrl"];
|
||||
}
|
||||
|
||||
@if (Authorizer.Authorize(Permissions.DeleteContent, contentItem)) {
|
||||
<fieldset class="delete-button">
|
||||
@Html.Link(T("Delete").Text, Url.ItemRemoveUrl(contentItem, new {returnUrl}), new { @class = "button", itemprop = "RemoveUrl UnsafeUrl"})
|
||||
</fieldset>
|
||||
}
|
26
src/Orchard.Web/Core/Navigation/Views/Menu.Edit.cshtml
Normal file
26
src/Orchard.Web/Core/Navigation/Views/Menu.Edit.cshtml
Normal file
@ -0,0 +1,26 @@
|
||||
@{
|
||||
Model.Sidebar.Add("Foo");
|
||||
}
|
||||
|
||||
<div class="edit-item">
|
||||
<div class="edit-item-primary">
|
||||
@if (Model.Content != null) {
|
||||
<div class="edit-item-content">
|
||||
@Display(Model.Content)
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
<div class="edit-item-secondary group">
|
||||
@if (Model.Actions != null) {
|
||||
<div class="edit-item-actions">
|
||||
@Display(Model.Actions)
|
||||
</div>
|
||||
}
|
||||
@if (Model.Sidebar != null) {
|
||||
<div class="edit-item-sidebar group">
|
||||
@Display(Model.Sidebar)
|
||||
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
@ -0,0 +1,8 @@
|
||||
<div class="sections">
|
||||
<div class="primary">
|
||||
@Display(Model.Content)
|
||||
</div>
|
||||
<div class="secondary">
|
||||
@Display(Model.Sidebar)
|
||||
</div>
|
||||
</div>
|
1
src/Orchard.Web/Core/Navigation/Views/MenuItem.cshtml
Normal file
1
src/Orchard.Web/Core/Navigation/Views/MenuItem.cshtml
Normal file
@ -0,0 +1 @@
|
||||
@Display(Model.Content)
|
@ -0,0 +1,8 @@
|
||||
@using Orchard.ContentManagement
|
||||
@{
|
||||
ContentItem contentItem = Model.Content.ContentItem.ContentMenuItemPart.Content;
|
||||
}
|
||||
|
||||
@if (contentItem != null) {
|
||||
<a href="@Model.Href">@Model.Text</a>
|
||||
}
|
@ -0,0 +1 @@
|
||||
<span class="raw">@Html.Raw(Model.Content.BodyPart.Text)</span>
|
@ -0,0 +1 @@
|
||||
@Display(Model.Menu)
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user