mirror of
https://github.com/OrchardCMS/Orchard.git
synced 2025-09-19 18:27:55 +08:00
Refactored ImportExport to support extensible, configurable export steps.
This commit is contained in:
@@ -1,9 +1,11 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using Orchard.Commands;
|
||||
using Orchard.ContentManagement.MetaData;
|
||||
using Orchard.ImportExport.Models;
|
||||
using Orchard.ImportExport.Providers;
|
||||
using Orchard.ImportExport.Services;
|
||||
using Orchard.Security;
|
||||
using Orchard.Settings;
|
||||
@@ -15,18 +17,22 @@ namespace Orchard.ImportExport.Commands {
|
||||
private readonly ISiteService _siteService;
|
||||
private readonly IMembershipService _membershipService;
|
||||
private readonly IAuthenticationService _authenticationService;
|
||||
private readonly IOrchardServices _orchardServices;
|
||||
|
||||
public ImportExportCommands(
|
||||
IImportExportService importExportService,
|
||||
IContentDefinitionManager contentDefinitionManager,
|
||||
ISiteService siteService,
|
||||
IMembershipService membershipService,
|
||||
IAuthenticationService authenticationService) {
|
||||
IAuthenticationService authenticationService,
|
||||
IOrchardServices orchardServices) {
|
||||
|
||||
_importExportService = importExportService;
|
||||
_contentDefinitionManager = contentDefinitionManager;
|
||||
_siteService = siteService;
|
||||
_membershipService = membershipService;
|
||||
_authenticationService = authenticationService;
|
||||
_orchardServices = orchardServices;
|
||||
}
|
||||
|
||||
[OrchardSwitch]
|
||||
@@ -65,10 +71,10 @@ namespace Orchard.ImportExport.Commands {
|
||||
}
|
||||
|
||||
[CommandName("export file")]
|
||||
[CommandHelp("export file [/Types:<type-name-1>, ... ,<type-name-n>] [/Metadata:true|false] [/Data:true|false] [/Version:Published|Draft] [/SiteSettings:true|false] [/Steps:<custom-step-1>, ... ,<custom-step-n>]\r\n\t" + "Create an export file according to the specified options.")]
|
||||
[CommandHelp("export file [/Types:<type-name-1>, ... ,<type-name-n>] [/Metadata:true|false] [/Data:true|false] [/Version:Published|Draft|Latest] [/SiteSettings:true|false] [/Steps:<custom-step-1>, ... ,<custom-step-n>]\r\n\t" + "Create an export file according to the specified options.")]
|
||||
[OrchardSwitches("Types,Metadata,Data,Version,SiteSettings,Steps")]
|
||||
public void ExportFile() {
|
||||
// impersonate the Site owner
|
||||
// Impersonate the Site owner.
|
||||
var superUser = _siteService.GetSiteSettings().SuperUser;
|
||||
var owner = _membershipService.GetUser(superUser);
|
||||
_authenticationService.SetAuthenticatedUserForRequest(owner);
|
||||
@@ -82,23 +88,39 @@ namespace Orchard.ImportExport.Commands {
|
||||
|
||||
var enteredTypes = (Types ?? String.Empty).Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
|
||||
|
||||
var exportTypes = _contentDefinitionManager.ListTypeDefinitions()
|
||||
.Where(contentType => enteredTypes.Contains(contentType.Name))
|
||||
.Select(contentType => contentType.Name);
|
||||
var exportTypes = _contentDefinitionManager
|
||||
.ListTypeDefinitions()
|
||||
.Where(contentType => enteredTypes.Contains(contentType.Name))
|
||||
.Select(contentType => contentType.Name)
|
||||
.ToList();
|
||||
|
||||
var enteredSteps = (Steps ?? String.Empty).Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
|
||||
|
||||
var exportSteps = new List<IExportStepProvider>();
|
||||
var exportOptions = new ExportOptions {
|
||||
ExportMetadata = Metadata,
|
||||
ExportData = Data,
|
||||
VersionHistoryOptions = versionOption,
|
||||
ExportSiteSettings = SiteSettings,
|
||||
CustomSteps = enteredSteps
|
||||
};
|
||||
|
||||
if (Metadata || Data) {
|
||||
var dataStep = _orchardServices.WorkContext.Resolve<DataExportStep>();
|
||||
|
||||
if(Data)
|
||||
dataStep.DataContentTypes = exportTypes;
|
||||
|
||||
if(Metadata)
|
||||
dataStep.SchemaContentTypes = exportTypes;
|
||||
|
||||
dataStep.VersionHistoryOptions = versionOption;
|
||||
exportSteps.Add(dataStep);
|
||||
}
|
||||
|
||||
if (SiteSettings) {
|
||||
var siteSettingsStep = _orchardServices.WorkContext.Resolve<SiteSettingsExportStep>();
|
||||
exportSteps.Add(siteSettingsStep);
|
||||
}
|
||||
|
||||
Context.Output.WriteLine(T("Export starting..."));
|
||||
|
||||
var exportFilePath = _importExportService.Export(exportTypes, exportOptions);
|
||||
var exportFilePath = _importExportService.Export(exportSteps, exportOptions);
|
||||
|
||||
Context.Output.WriteLine(T("Export completed at {0}", exportFilePath));
|
||||
}
|
||||
|
@@ -3,18 +3,17 @@ using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Web.Mvc;
|
||||
using Orchard.ContentManagement;
|
||||
using Orchard.ContentManagement.MetaData;
|
||||
using Orchard.DisplayManagement;
|
||||
using Orchard.ImportExport.Models;
|
||||
using Orchard.ImportExport.Services;
|
||||
using Orchard.ImportExport.ViewModels;
|
||||
using Orchard.Localization;
|
||||
using Orchard.Recipes.Services;
|
||||
using Orchard.UI.Notify;
|
||||
using Orchard.ImportExport.Models;
|
||||
using Orchard.Utility.Extensions;
|
||||
|
||||
namespace Orchard.ImportExport.Controllers {
|
||||
public class AdminController : Controller {
|
||||
public class AdminController : Controller, IUpdateModel {
|
||||
private readonly IImportExportService _importExportService;
|
||||
private readonly IContentDefinitionManager _contentDefinitionManager;
|
||||
private readonly ICustomExportStep _customExportStep;
|
||||
@@ -79,25 +78,18 @@ namespace Orchard.ImportExport.Controllers {
|
||||
var customSteps = new List<string>();
|
||||
_customExportStep.Register(customSteps);
|
||||
|
||||
var exportSteps = _exportStepProviders.Select(x => {
|
||||
var editor = x.BuildEditor(Services.New);
|
||||
editor.Provider = x;
|
||||
editor.Name = x.Name;
|
||||
editor.DisplayName = x.DisplayName;
|
||||
return editor;
|
||||
var exportSteps = _exportStepProviders.OrderBy(x => x.Position).Select(x => new ExportStepViewModel {
|
||||
Name = x.Name,
|
||||
DisplayName = x.DisplayName,
|
||||
Description = x.Description,
|
||||
Editor = x.BuildEditor(Services.New)
|
||||
}).Where(x => x != null);
|
||||
|
||||
var viewModel = new ExportViewModel {
|
||||
RecipeVersion = "1.0",
|
||||
ContentTypes = new List<ContentTypeEntry>(),
|
||||
CustomSteps = customSteps.Select(x => new CustomStepEntry { CustomStep = x }).ToList(),
|
||||
ExportSteps = exportSteps.ToList()
|
||||
};
|
||||
|
||||
foreach (var contentType in _contentDefinitionManager.ListTypeDefinitions().OrderBy(c => c.Name)) {
|
||||
viewModel.ContentTypes.Add(new ContentTypeEntry { ContentTypeName = contentType.Name });
|
||||
}
|
||||
|
||||
return View(viewModel);
|
||||
}
|
||||
|
||||
@@ -107,37 +99,39 @@ namespace Orchard.ImportExport.Controllers {
|
||||
return new HttpUnauthorizedResult();
|
||||
|
||||
var viewModel = new ExportViewModel {
|
||||
ContentTypes = new List<ContentTypeEntry>(),
|
||||
CustomSteps = new List<CustomStepEntry>()
|
||||
CustomSteps = new List<CustomStepEntry>(),
|
||||
ExportSteps = new List<ExportStepViewModel>()
|
||||
};
|
||||
|
||||
UpdateModel(viewModel);
|
||||
var contentTypesToExport = viewModel.ContentTypes.Where(c => c.IsChecked).Select(c => c.ContentTypeName).ToList();
|
||||
var exportStepNames = viewModel.ExportSteps.Where(x => x.IsSelected).Select(x => x.Name);
|
||||
var exportStepsQuery = from name in exportStepNames
|
||||
let provider = _exportStepProviders.SingleOrDefault(x => x.Name == name)
|
||||
where provider != null
|
||||
select provider;
|
||||
var exportSteps = exportStepsQuery.ToArray();
|
||||
var customSteps = viewModel.CustomSteps.Where(c => c.IsChecked).Select(c => c.CustomStep);
|
||||
|
||||
var exportOptions = new ExportOptions {
|
||||
ExportMetadata = viewModel.Metadata,
|
||||
ExportSiteSettings = viewModel.SiteSettings,
|
||||
SetupRecipe = viewModel.SetupRecipe,
|
||||
RecipeName = viewModel.RecipeName,
|
||||
RecipeDescription = viewModel.RecipeDescription,
|
||||
RecipeWebsite = viewModel.RecipeWebsite,
|
||||
RecipeTags = viewModel.RecipeTags,
|
||||
RecipeVersion = viewModel.RecipeVersion,
|
||||
CustomSteps = customSteps
|
||||
};
|
||||
|
||||
if (viewModel.Data) {
|
||||
exportOptions.ExportData = true;
|
||||
exportOptions.VersionHistoryOptions = (VersionHistoryOptions)Enum.Parse(typeof(VersionHistoryOptions), viewModel.DataImportChoice, true);
|
||||
exportOptions.ImportBatchSize = viewModel.ImportBatchSize;
|
||||
foreach (var exportStep in exportSteps) {
|
||||
exportStep.UpdateEditor(Services.New, this);
|
||||
}
|
||||
var exportFilePath = _importExportService.Export(contentTypesToExport, exportOptions);
|
||||
var exportFileName = exportOptions.SetupRecipe && !String.IsNullOrWhiteSpace(exportOptions.RecipeName)
|
||||
? String.Format("{0}.recipe.xml", exportOptions.RecipeName.HtmlClassify())
|
||||
: "export.xml";
|
||||
|
||||
var exportFilePath = _importExportService.Export(exportSteps, exportOptions);
|
||||
var exportFileName = "export.xml";
|
||||
|
||||
return File(exportFilePath, "text/xml", exportFileName);
|
||||
}
|
||||
|
||||
bool IUpdateModel.TryUpdateModel<TModel>(TModel model, string prefix, string[] includeProperties, string[] excludeProperties) {
|
||||
return TryUpdateModel(model, prefix, includeProperties, excludeProperties);
|
||||
}
|
||||
|
||||
void IUpdateModel.AddModelError(string key, LocalizedString errorMessage) {
|
||||
ModelState.AddModelError(key, errorMessage.ToString());
|
||||
}
|
||||
}
|
||||
}
|
@@ -2,22 +2,12 @@
|
||||
|
||||
namespace Orchard.ImportExport.Models {
|
||||
public class ExportOptions {
|
||||
public bool ExportMetadata { get; set; }
|
||||
public bool ExportData { get; set; }
|
||||
public int? ImportBatchSize { get; set; }
|
||||
public VersionHistoryOptions VersionHistoryOptions { get; set; }
|
||||
public bool ExportSiteSettings { get; set; }
|
||||
public IEnumerable<string> CustomSteps { get; set; }
|
||||
public bool SetupRecipe { get; set; }
|
||||
public string RecipeName { get; set; }
|
||||
public string RecipeDescription { get; set; }
|
||||
public string RecipeWebsite { get; set; }
|
||||
public string RecipeTags { get; set; }
|
||||
public string RecipeVersion { get; set; }
|
||||
}
|
||||
|
||||
public enum VersionHistoryOptions {
|
||||
Published,
|
||||
Draft,
|
||||
Latest
|
||||
}
|
||||
}
|
@@ -71,7 +71,15 @@
|
||||
<Compile Include="Models\ExportOptions.cs" />
|
||||
<Compile Include="Permissions.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="Providers\SetupRecipeExportStep.cs" />
|
||||
<Compile Include="Providers\SiteSettingsExportStep.cs" />
|
||||
<Compile Include="Providers\DataExportStep.cs" />
|
||||
<Compile Include="ViewModels\ContentTypeEntry.cs" />
|
||||
<Compile Include="ViewModels\CustomStepEntry.cs" />
|
||||
<Compile Include="ViewModels\ExportStepViewModel.cs" />
|
||||
<Compile Include="ViewModels\SetupRecipeStepViewModel.cs" />
|
||||
<Compile Include="ViewModels\SiteSettingsStepViewModel.cs" />
|
||||
<Compile Include="ViewModels\DataExportStepViewModel.cs" />
|
||||
<Compile Include="Services\ICustomExportStep.cs" />
|
||||
<Compile Include="Services\IExportEventHandler.cs" />
|
||||
<Compile Include="Services\IImportExportService.cs" />
|
||||
@@ -101,6 +109,7 @@
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Content Include="Styles\images\menu.importexport.png" />
|
||||
<Content Include="Styles\exportstep-data.css" />
|
||||
<Content Include="Styles\menu.importexport-admin.css" />
|
||||
<Content Include="Web.config" />
|
||||
</ItemGroup>
|
||||
@@ -121,6 +130,12 @@
|
||||
<ItemGroup>
|
||||
<Content Include="Views\EditorTemplates\ExportSteps\Data.cshtml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Content Include="Views\EditorTemplates\ExportSteps\SiteSettings.cshtml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Content Include="Views\EditorTemplates\ExportSteps\SetupRecipe.cshtml" />
|
||||
</ItemGroup>
|
||||
<PropertyGroup>
|
||||
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">10.0</VisualStudioVersion>
|
||||
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
|
||||
|
@@ -1,27 +1,153 @@
|
||||
using Orchard.ContentManagement;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Xml.Linq;
|
||||
using Orchard.ContentManagement;
|
||||
using Orchard.ContentManagement.MetaData;
|
||||
using Orchard.ContentManagement.MetaData.Models;
|
||||
using Orchard.ImportExport.Models;
|
||||
using Orchard.ImportExport.Services;
|
||||
using Orchard.ImportExport.ViewModels;
|
||||
using Orchard.Localization;
|
||||
|
||||
namespace Orchard.ImportExport.Providers {
|
||||
public class DataExportStep : ExportStepProvider {
|
||||
private readonly IContentDefinitionManager _contentDefinitionManager;
|
||||
private readonly IOrchardServices _orchardServices;
|
||||
private readonly IContentDefinitionWriter _contentDefinitionWriter;
|
||||
|
||||
public DataExportStep(
|
||||
IContentDefinitionManager contentDefinitionManager,
|
||||
IOrchardServices orchardServices,
|
||||
IContentDefinitionWriter contentDefinitionWriter) {
|
||||
|
||||
_contentDefinitionManager = contentDefinitionManager;
|
||||
_orchardServices = orchardServices;
|
||||
_contentDefinitionWriter = contentDefinitionWriter;
|
||||
}
|
||||
|
||||
public override string Name {
|
||||
get { return "Data"; }
|
||||
}
|
||||
|
||||
public override LocalizedString DisplayName {
|
||||
get { return T("Data"); }
|
||||
get { return T("Content Items and Definitions"); }
|
||||
}
|
||||
|
||||
public override LocalizedString Description {
|
||||
get { return T("Exports content items and content item definitions."); }
|
||||
}
|
||||
|
||||
public override int Position { get { return 10; } }
|
||||
|
||||
public IList<string> SchemaContentTypes { get; set; }
|
||||
public IList<string> DataContentTypes { get; set; }
|
||||
public int? ImportBatchSize { get; set; }
|
||||
public VersionHistoryOptions VersionHistoryOptions { get; set; }
|
||||
|
||||
public override dynamic BuildEditor(dynamic shapeFactory) {
|
||||
return UpdateEditor(shapeFactory, null);
|
||||
}
|
||||
|
||||
public override dynamic UpdateEditor(dynamic shapeFactory, IUpdateModel updater) {
|
||||
if (updater != null) {
|
||||
var contentTypeViewModels = _contentDefinitionManager.ListTypeDefinitions()
|
||||
.OrderBy(x => x.Name)
|
||||
.Select(x => new ContentTypeEntry { Name = x.Name, DisplayName = x.DisplayName })
|
||||
.ToList();
|
||||
|
||||
var viewModel = new DataExportStepViewModel {
|
||||
ContentTypes = contentTypeViewModels
|
||||
};
|
||||
|
||||
if (updater != null && updater.TryUpdateModel(viewModel, Prefix, null, null)) {
|
||||
DataContentTypes = viewModel.ContentTypes.Where(x => x.ExportData).Select(x => x.Name).ToList();
|
||||
SchemaContentTypes = viewModel.ContentTypes.Where(x => x.ExportSchema).Select(x => x.Name).ToList();
|
||||
VersionHistoryOptions = viewModel.VersionHistoryOptions;
|
||||
}
|
||||
|
||||
return shapeFactory.EditorTemplate(TemplateName: "ExportSteps/Data");
|
||||
return shapeFactory.EditorTemplate(TemplateName: "ExportSteps/Data", Model: viewModel, Prefix: Prefix);
|
||||
}
|
||||
|
||||
public override void Export(ExportContext context) {
|
||||
var dataContentTypes = DataContentTypes;
|
||||
var schemaContentTypes = SchemaContentTypes;
|
||||
var exportVersionOptions = GetContentExportVersionOptions(VersionHistoryOptions);
|
||||
var contentItems = dataContentTypes.Any()
|
||||
? _orchardServices.ContentManager.Query(exportVersionOptions, dataContentTypes.ToArray()).List().ToArray()
|
||||
: Enumerable.Empty<ContentItem>();
|
||||
|
||||
if(schemaContentTypes.Any())
|
||||
context.Document.Element("Orchard").Add(ExportMetadata(schemaContentTypes));
|
||||
|
||||
if(contentItems.Any())
|
||||
context.Document.Element("Orchard").Add(ExportData(dataContentTypes, contentItems, ImportBatchSize));
|
||||
}
|
||||
|
||||
private XElement ExportMetadata(IEnumerable<string> contentTypes) {
|
||||
var typesElement = new XElement("Types");
|
||||
var partsElement = new XElement("Parts");
|
||||
var typesToExport = _contentDefinitionManager.ListTypeDefinitions()
|
||||
.Where(typeDefinition => contentTypes.Contains(typeDefinition.Name))
|
||||
.ToList();
|
||||
var partsToExport = new Dictionary<string, ContentPartDefinition>();
|
||||
|
||||
foreach (var contentTypeDefinition in typesToExport.OrderBy(x => x.Name)) {
|
||||
foreach (var contentPartDefinition in contentTypeDefinition.Parts) {
|
||||
if (partsToExport.ContainsKey(contentPartDefinition.PartDefinition.Name)) {
|
||||
continue;
|
||||
}
|
||||
partsToExport.Add(contentPartDefinition.PartDefinition.Name, contentPartDefinition.PartDefinition);
|
||||
}
|
||||
typesElement.Add(_contentDefinitionWriter.Export(contentTypeDefinition));
|
||||
}
|
||||
|
||||
foreach (var part in partsToExport.Values.OrderBy(x => x.Name)) {
|
||||
partsElement.Add(_contentDefinitionWriter.Export(part));
|
||||
}
|
||||
|
||||
return new XElement("Metadata", typesElement, partsElement);
|
||||
}
|
||||
|
||||
private XElement ExportData(IEnumerable<string> contentTypes, IEnumerable<ContentItem> contentItems, int? batchSize) {
|
||||
var data = new XElement("Data");
|
||||
|
||||
if (batchSize.HasValue && batchSize.Value > 0)
|
||||
data.SetAttributeValue("BatchSize", batchSize);
|
||||
|
||||
var orderedContentItemsQuery =
|
||||
from contentItem in contentItems
|
||||
let identity = _orchardServices.ContentManager.GetItemMetadata(contentItem).Identity.ToString()
|
||||
orderby identity
|
||||
select contentItem;
|
||||
|
||||
var orderedContentItems = orderedContentItemsQuery.ToList();
|
||||
|
||||
foreach (var contentType in contentTypes.OrderBy(x => x)) {
|
||||
var type = contentType;
|
||||
var items = orderedContentItems.Where(i => i.ContentType == type);
|
||||
foreach (var contentItem in items) {
|
||||
var contentItemElement = ExportContentItem(contentItem);
|
||||
if (contentItemElement != null)
|
||||
data.Add(contentItemElement);
|
||||
}
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
private VersionOptions GetContentExportVersionOptions(VersionHistoryOptions versionHistoryOptions) {
|
||||
switch (versionHistoryOptions) {
|
||||
case VersionHistoryOptions.Draft:
|
||||
return VersionOptions.Draft;
|
||||
case VersionHistoryOptions.Latest:
|
||||
return VersionOptions.Latest;
|
||||
case VersionHistoryOptions.Published:
|
||||
default:
|
||||
return VersionOptions.Published;
|
||||
}
|
||||
}
|
||||
|
||||
private XElement ExportContentItem(ContentItem contentItem) {
|
||||
return _orchardServices.ContentManager.Export(contentItem);
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,69 @@
|
||||
using Orchard.ContentManagement;
|
||||
using Orchard.ImportExport.Services;
|
||||
using Orchard.ImportExport.ViewModels;
|
||||
using Orchard.Localization;
|
||||
|
||||
namespace Orchard.ImportExport.Providers {
|
||||
public class SetupRecipeExportStep : ExportStepProvider {
|
||||
private readonly IOrchardServices _orchardServices;
|
||||
public SetupRecipeExportStep(IOrchardServices orchardServices) {
|
||||
_orchardServices = orchardServices;
|
||||
}
|
||||
|
||||
public override string Name {
|
||||
get { return "SetupRecipe"; }
|
||||
}
|
||||
|
||||
public override LocalizedString DisplayName {
|
||||
get { return T("Setup Recipe"); }
|
||||
}
|
||||
|
||||
public override LocalizedString Description {
|
||||
get { return T("Turns the export file into a Setup recipe."); }
|
||||
}
|
||||
|
||||
public override int Position { get { return -10; } }
|
||||
|
||||
public string RecipeName { get; set; }
|
||||
public string RecipeDescription { get; set; }
|
||||
public string RecipeAuthor { get; set; }
|
||||
public string RecipeWebsite { get; set; }
|
||||
public string RecipeTags { get; set; }
|
||||
public string RecipeVersion { get; set; }
|
||||
public bool IsSetupRecipe { get; set; }
|
||||
|
||||
public override dynamic BuildEditor(dynamic shapeFactory) {
|
||||
return UpdateEditor(shapeFactory, null);
|
||||
}
|
||||
|
||||
public override dynamic UpdateEditor(dynamic shapeFactory, IUpdateModel updater) {
|
||||
var viewModel = new SetupRecipeStepViewModel {
|
||||
RecipeAuthor = _orchardServices.WorkContext.CurrentUser.UserName
|
||||
};
|
||||
|
||||
if (updater != null && updater.TryUpdateModel(viewModel, Prefix, null, null)) {
|
||||
RecipeName = viewModel.RecipeName;
|
||||
RecipeDescription = viewModel.RecipeDescription;
|
||||
RecipeAuthor = viewModel.RecipeAuthor;
|
||||
RecipeWebsite = viewModel.RecipeWebsite;
|
||||
RecipeTags = viewModel.RecipeTags;
|
||||
RecipeVersion = viewModel.RecipeVersion;
|
||||
IsSetupRecipe = true;
|
||||
}
|
||||
|
||||
return shapeFactory.EditorTemplate(TemplateName: "ExportSteps/SetupRecipe", Model: viewModel, Prefix: Prefix);
|
||||
}
|
||||
|
||||
public override void Export(ExportContext context) {
|
||||
var recipeElement = context.Document.Element("Orchard").Element("Recipe");
|
||||
|
||||
recipeElement.SetElementValue("Name", RecipeName);
|
||||
recipeElement.SetElementValue("Description", RecipeDescription);
|
||||
recipeElement.SetElementValue("Author", RecipeAuthor);
|
||||
recipeElement.SetElementValue("WebSite", RecipeWebsite);
|
||||
recipeElement.SetElementValue("Tags", RecipeTags);
|
||||
recipeElement.SetElementValue("Version", RecipeVersion);
|
||||
recipeElement.SetElementValue("IsSetupRecipe", IsSetupRecipe);
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,95 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Xml.Linq;
|
||||
using Orchard.ContentManagement;
|
||||
using Orchard.ImportExport.Services;
|
||||
using Orchard.ImportExport.ViewModels;
|
||||
using Orchard.Localization;
|
||||
|
||||
namespace Orchard.ImportExport.Providers {
|
||||
public class SiteSettingsExportStep : ExportStepProvider {
|
||||
private readonly IOrchardServices _orchardServices;
|
||||
|
||||
public SiteSettingsExportStep(IOrchardServices orchardServices) {
|
||||
_orchardServices = orchardServices;
|
||||
}
|
||||
|
||||
public override string Name {
|
||||
get { return "SiteSettings"; }
|
||||
}
|
||||
|
||||
public override LocalizedString DisplayName {
|
||||
get { return T("Site Settings"); }
|
||||
}
|
||||
|
||||
public override LocalizedString Description {
|
||||
get { return T("Exports site settings."); }
|
||||
}
|
||||
|
||||
public override int Position { get { return 20; } }
|
||||
|
||||
public override dynamic BuildEditor(dynamic shapeFactory) {
|
||||
return UpdateEditor(shapeFactory, null);
|
||||
}
|
||||
|
||||
public override dynamic UpdateEditor(dynamic shapeFactory, IUpdateModel updater) {
|
||||
var viewModel = new SiteSettingsStepViewModel();
|
||||
return shapeFactory.EditorTemplate(TemplateName: "ExportSteps/SiteSettings", Model: viewModel, Prefix: Prefix);
|
||||
}
|
||||
|
||||
public override void Export(ExportContext context) {
|
||||
context.Document.Element("Orchard").Add(ExportSiteSettings());
|
||||
}
|
||||
|
||||
private XElement ExportSiteSettings() {
|
||||
var siteContentItem = _orchardServices.WorkContext.CurrentSite.ContentItem;
|
||||
var exportedElements = ExportContentItem(siteContentItem).Elements().ToList();
|
||||
|
||||
foreach (var contentPart in siteContentItem.Parts.OrderBy(x => x.PartDefinition.Name)) {
|
||||
var exportedElement = exportedElements.FirstOrDefault(element => element.Name == contentPart.PartDefinition.Name);
|
||||
|
||||
// Get all simple attributes if exported element is null.
|
||||
// Get exclude the simple attributes that already exist if element is not null.
|
||||
var simpleAttributes =
|
||||
ExportSettingsPartAttributes(contentPart)
|
||||
.Where(attribute => exportedElement == null || exportedElement.Attributes().All(xAttribute => xAttribute.Name != attribute.Name))
|
||||
.OrderBy(x => x.Name.LocalName)
|
||||
.ToList();
|
||||
|
||||
if (simpleAttributes.Any()) {
|
||||
if (exportedElement == null) {
|
||||
exportedElement = new XElement(contentPart.PartDefinition.Name);
|
||||
exportedElements.Add(exportedElement);
|
||||
}
|
||||
|
||||
exportedElement.Add(simpleAttributes);
|
||||
}
|
||||
}
|
||||
|
||||
exportedElements = exportedElements.OrderBy(x => x.Name.LocalName).ToList();
|
||||
return new XElement("Settings", exportedElements);
|
||||
}
|
||||
|
||||
private XElement ExportContentItem(ContentItem contentItem) {
|
||||
return _orchardServices.ContentManager.Export(contentItem);
|
||||
}
|
||||
|
||||
private IEnumerable<XAttribute> ExportSettingsPartAttributes(ContentPart sitePart) {
|
||||
foreach (var property in sitePart.GetType().GetProperties().OrderBy(x => x.Name)) {
|
||||
var propertyType = property.PropertyType;
|
||||
|
||||
// Supported types (we also know they are not indexed properties).
|
||||
if (propertyType == typeof(string) || propertyType == typeof(bool) || propertyType == typeof(int)) {
|
||||
// Exclude read-only properties.
|
||||
if (property.GetSetMethod() != null) {
|
||||
var value = property.GetValue(sitePart, null);
|
||||
if (value == null)
|
||||
continue;
|
||||
|
||||
yield return new XAttribute(property.Name, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -5,6 +5,8 @@ namespace Orchard.ImportExport.Services {
|
||||
public abstract class ExportStepProvider : Component, IExportStepProvider {
|
||||
public abstract string Name { get; }
|
||||
public abstract LocalizedString DisplayName { get; }
|
||||
public abstract LocalizedString Description { get; }
|
||||
public virtual int Position { get { return 0; } }
|
||||
|
||||
protected virtual string Prefix {
|
||||
get { return GetType().Name; }
|
||||
@@ -17,5 +19,7 @@ namespace Orchard.ImportExport.Services {
|
||||
public virtual dynamic UpdateEditor(dynamic shapeFactory, IUpdateModel updater) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public virtual void Export(ExportContext context) {}
|
||||
}
|
||||
}
|
@@ -1,12 +1,10 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Xml.Linq;
|
||||
using System.Xml.Linq;
|
||||
using Orchard.Events;
|
||||
using Orchard.ImportExport.Models;
|
||||
|
||||
namespace Orchard.ImportExport.Services {
|
||||
public class ExportContext {
|
||||
public XDocument Document { get; set; }
|
||||
public IEnumerable<string> ContentTypes { get; set; }
|
||||
public ExportOptions ExportOptions { get; set; }
|
||||
}
|
||||
|
||||
|
@@ -5,7 +5,10 @@ namespace Orchard.ImportExport.Services {
|
||||
public interface IExportStepProvider : IDependency {
|
||||
string Name { get; }
|
||||
LocalizedString DisplayName { get; }
|
||||
LocalizedString Description { get; }
|
||||
int Position { get; }
|
||||
dynamic BuildEditor(dynamic shapeFactory);
|
||||
dynamic UpdateEditor(dynamic shapeFactory, IUpdateModel updater);
|
||||
void Export(ExportContext context);
|
||||
}
|
||||
}
|
@@ -1,12 +1,10 @@
|
||||
using System.Collections.Generic;
|
||||
using Orchard.ContentManagement;
|
||||
using Orchard.ImportExport.Models;
|
||||
|
||||
namespace Orchard.ImportExport.Services {
|
||||
public interface IImportExportService : IDependency {
|
||||
string Import(string recipeText);
|
||||
string Export(IEnumerable<string> contentTypes, IEnumerable<ContentItem> contentItems, ExportOptions exportOptions);
|
||||
string Export(IEnumerable<string> contentTypes, ExportOptions exportOptions);
|
||||
string Export(IEnumerable<IExportStepProvider> steps, ExportOptions exportOptions);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -1,11 +1,8 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Xml;
|
||||
using System.Xml.Linq;
|
||||
using Orchard.ContentManagement;
|
||||
using Orchard.ContentManagement.MetaData;
|
||||
using Orchard.ContentManagement.MetaData.Models;
|
||||
using Orchard.Environment.Descriptor;
|
||||
using Orchard.FileSystems.AppData;
|
||||
using Orchard.ImportExport.Models;
|
||||
@@ -17,8 +14,6 @@ using Orchard.Services;
|
||||
namespace Orchard.ImportExport.Services {
|
||||
public class ImportExportService : IImportExportService {
|
||||
private readonly IOrchardServices _orchardServices;
|
||||
private readonly IContentDefinitionManager _contentDefinitionManager;
|
||||
private readonly IContentDefinitionWriter _contentDefinitionWriter;
|
||||
private readonly IAppDataFolder _appDataFolder;
|
||||
private readonly IRecipeParser _recipeParser;
|
||||
private readonly IRecipeManager _recipeManager;
|
||||
@@ -29,8 +24,6 @@ namespace Orchard.ImportExport.Services {
|
||||
|
||||
public ImportExportService(
|
||||
IOrchardServices orchardServices,
|
||||
IContentDefinitionManager contentDefinitionManager,
|
||||
IContentDefinitionWriter contentDefinitionWriter,
|
||||
IAppDataFolder appDataFolder,
|
||||
IRecipeParser recipeParser,
|
||||
IRecipeManager recipeManager,
|
||||
@@ -39,8 +32,6 @@ namespace Orchard.ImportExport.Services {
|
||||
IEnumerable<IExportEventHandler> exportEventHandlers) {
|
||||
|
||||
_orchardServices = orchardServices;
|
||||
_contentDefinitionManager = contentDefinitionManager;
|
||||
_contentDefinitionWriter = contentDefinitionWriter;
|
||||
_appDataFolder = appDataFolder;
|
||||
_recipeParser = recipeParser;
|
||||
_recipeManager = recipeManager;
|
||||
@@ -61,37 +52,18 @@ namespace Orchard.ImportExport.Services {
|
||||
return executionId;
|
||||
}
|
||||
|
||||
public string Export(IEnumerable<string> contentTypes, ExportOptions exportOptions) {
|
||||
//items need to be retrieved
|
||||
IEnumerable<ContentItem> contentItems = null;
|
||||
if (exportOptions.ExportData) {
|
||||
contentItems = _orchardServices.ContentManager.Query(GetContentExportVersionOptions(exportOptions.VersionHistoryOptions), contentTypes.ToArray()).List().ToArray();
|
||||
}
|
||||
|
||||
return Export(contentTypes, contentItems, exportOptions);
|
||||
}
|
||||
|
||||
public string Export(IEnumerable<string> contentTypes, IEnumerable<ContentItem> contentItems, ExportOptions exportOptions) {
|
||||
var exportDocument = CreateExportRoot(exportOptions);
|
||||
public string Export(IEnumerable<IExportStepProvider> steps, ExportOptions exportOptions) {
|
||||
var exportDocument = CreateExportRoot();
|
||||
|
||||
var context = new ExportContext {
|
||||
Document = exportDocument,
|
||||
ContentTypes = contentTypes,
|
||||
ExportOptions = exportOptions
|
||||
};
|
||||
|
||||
_exportEventHandlers.Invoke(x => x.Exporting(context), Logger);
|
||||
|
||||
if (exportOptions.ExportMetadata && (!exportOptions.ExportData || contentItems.Any())) {
|
||||
exportDocument.Element("Orchard").Add(ExportMetadata(contentTypes));
|
||||
}
|
||||
|
||||
if (exportOptions.ExportSiteSettings) {
|
||||
exportDocument.Element("Orchard").Add(ExportSiteSettings());
|
||||
}
|
||||
|
||||
if (exportOptions.ExportData && contentItems.Any()) {
|
||||
exportDocument.Element("Orchard").Add(ExportData(contentTypes, contentItems, exportOptions.ImportBatchSize));
|
||||
foreach (var step in steps) {
|
||||
step.Export(context);
|
||||
}
|
||||
|
||||
_exportEventHandlers.Invoke(x => x.Exported(context), Logger);
|
||||
@@ -99,23 +71,12 @@ namespace Orchard.ImportExport.Services {
|
||||
return WriteExportFile(exportDocument.ToString());
|
||||
}
|
||||
|
||||
private XDocument CreateExportRoot(ExportOptions exportOptions) {
|
||||
var recipeName = !String.IsNullOrWhiteSpace(exportOptions.RecipeName)
|
||||
? exportOptions.RecipeName
|
||||
: T("Generated by Orchard.ImportExport").ToString();
|
||||
|
||||
private XDocument CreateExportRoot() {
|
||||
var exportRoot = new XDocument(
|
||||
new XDeclaration("1.0", "", "yes"),
|
||||
new XComment("Exported from Orchard"),
|
||||
new XElement("Orchard",
|
||||
new XElement("Recipe",
|
||||
new XElement("Name", recipeName),
|
||||
new XElement("Description", exportOptions.RecipeDescription),
|
||||
new XElement("Author", _orchardServices.WorkContext.CurrentUser.UserName),
|
||||
new XElement("WebSite", exportOptions.RecipeWebsite),
|
||||
new XElement("Tags", exportOptions.RecipeTags),
|
||||
new XElement("Version", exportOptions.RecipeVersion),
|
||||
new XElement("IsSetupRecipe", exportOptions.SetupRecipe),
|
||||
new XElement("ExportUtc", XmlConvert.ToString(_clock.UtcNow, XmlDateTimeSerializationMode.Utc))
|
||||
)
|
||||
)
|
||||
@@ -123,119 +84,8 @@ namespace Orchard.ImportExport.Services {
|
||||
return exportRoot;
|
||||
}
|
||||
|
||||
private XElement ExportMetadata(IEnumerable<string> contentTypes) {
|
||||
var typesElement = new XElement("Types");
|
||||
var partsElement = new XElement("Parts");
|
||||
var typesToExport = _contentDefinitionManager.ListTypeDefinitions()
|
||||
.Where(typeDefinition => contentTypes.Contains(typeDefinition.Name))
|
||||
.ToList();
|
||||
var partsToExport = new Dictionary<string, ContentPartDefinition>();
|
||||
|
||||
foreach (var contentTypeDefinition in typesToExport.OrderBy(x => x.Name)) {
|
||||
foreach (var contentPartDefinition in contentTypeDefinition.Parts) {
|
||||
if (partsToExport.ContainsKey(contentPartDefinition.PartDefinition.Name)) {
|
||||
continue;
|
||||
}
|
||||
partsToExport.Add(contentPartDefinition.PartDefinition.Name, contentPartDefinition.PartDefinition);
|
||||
}
|
||||
typesElement.Add(_contentDefinitionWriter.Export(contentTypeDefinition));
|
||||
}
|
||||
|
||||
foreach (var part in partsToExport.Values.OrderBy(x => x.Name)) {
|
||||
partsElement.Add(_contentDefinitionWriter.Export(part));
|
||||
}
|
||||
|
||||
return new XElement("Metadata", typesElement, partsElement);
|
||||
}
|
||||
|
||||
private XElement ExportSiteSettings() {
|
||||
var siteContentItem = _orchardServices.WorkContext.CurrentSite.ContentItem;
|
||||
var exportedElements = ExportContentItem(siteContentItem).Elements().ToList();
|
||||
|
||||
foreach (var contentPart in siteContentItem.Parts.OrderBy(x => x.PartDefinition.Name)) {
|
||||
var exportedElement = exportedElements.FirstOrDefault(element => element.Name == contentPart.PartDefinition.Name);
|
||||
|
||||
//Get all simple attributes if exported element is null
|
||||
//Get exclude the simple attributes that already exist if element is not null
|
||||
var simpleAttributes =
|
||||
ExportSettingsPartAttributes(contentPart)
|
||||
.Where(attribute => exportedElement == null || exportedElement.Attributes().All(xAttribute => xAttribute.Name != attribute.Name))
|
||||
.OrderBy(x => x.Name.LocalName)
|
||||
.ToList();
|
||||
|
||||
if (simpleAttributes.Any()) {
|
||||
if (exportedElement == null) {
|
||||
exportedElement = new XElement(contentPart.PartDefinition.Name);
|
||||
exportedElements.Add(exportedElement);
|
||||
}
|
||||
|
||||
exportedElement.Add(simpleAttributes);
|
||||
}
|
||||
}
|
||||
|
||||
exportedElements = exportedElements.OrderBy(x => x.Name.LocalName).ToList();
|
||||
return new XElement("Settings", exportedElements);
|
||||
}
|
||||
|
||||
private IEnumerable<XAttribute> ExportSettingsPartAttributes(ContentPart sitePart) {
|
||||
foreach (var property in sitePart.GetType().GetProperties().OrderBy(x => x.Name)) {
|
||||
var propertyType = property.PropertyType;
|
||||
|
||||
// Supported types (we also know they are not indexed properties).
|
||||
if (propertyType == typeof(string) || propertyType == typeof(bool) || propertyType == typeof(int)) {
|
||||
// Exclude read-only properties.
|
||||
if (property.GetSetMethod() != null) {
|
||||
var value = property.GetValue(sitePart, null);
|
||||
if (value == null)
|
||||
continue;
|
||||
|
||||
yield return new XAttribute(property.Name, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private XElement ExportData(IEnumerable<string> contentTypes, IEnumerable<ContentItem> contentItems, int? batchSize) {
|
||||
var data = new XElement("Data");
|
||||
|
||||
if (batchSize.HasValue && batchSize.Value > 0)
|
||||
data.SetAttributeValue("BatchSize", batchSize);
|
||||
|
||||
var orderedContentItemsQuery =
|
||||
from contentItem in contentItems
|
||||
let identity = _orchardServices.ContentManager.GetItemMetadata(contentItem).Identity.ToString()
|
||||
orderby identity
|
||||
select contentItem;
|
||||
|
||||
var orderedContentItems = orderedContentItemsQuery.ToList();
|
||||
|
||||
foreach (var contentType in contentTypes.OrderBy(x => x)) {
|
||||
var type = contentType;
|
||||
var items = orderedContentItems.Where(i => i.ContentType == type);
|
||||
foreach (var contentItem in items) {
|
||||
var contentItemElement = ExportContentItem(contentItem);
|
||||
if (contentItemElement != null)
|
||||
data.Add(contentItemElement);
|
||||
}
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
private XElement ExportContentItem(ContentItem contentItem) {
|
||||
// Call export handler for the item.
|
||||
return _orchardServices.ContentManager.Export(contentItem);
|
||||
}
|
||||
|
||||
private static VersionOptions GetContentExportVersionOptions(VersionHistoryOptions versionHistoryOptions) {
|
||||
if (versionHistoryOptions.HasFlag(VersionHistoryOptions.Draft)) {
|
||||
return VersionOptions.Draft;
|
||||
}
|
||||
return VersionOptions.Published;
|
||||
}
|
||||
|
||||
private string WriteExportFile(string exportDocument) {
|
||||
var exportFile = string.Format("Export-{0}-{1}.xml", _orchardServices.WorkContext.CurrentUser.UserName, DateTime.UtcNow.Ticks);
|
||||
var exportFile = String.Format("Export-{0}-{1}.xml", _orchardServices.WorkContext.CurrentUser.UserName, DateTime.UtcNow.Ticks);
|
||||
if (!_appDataFolder.DirectoryExists(ExportsDirectory)) {
|
||||
_appDataFolder.CreateDirectory(ExportsDirectory);
|
||||
}
|
||||
|
@@ -0,0 +1,9 @@
|
||||
fieldset.export-step-data table.items {
|
||||
width: 500px;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
fieldset.export-step-data table.items td,
|
||||
fieldset.export-step-data table.items thead tr.sub th {
|
||||
padding: 0 12px;
|
||||
}
|
@@ -0,0 +1,8 @@
|
||||
namespace Orchard.ImportExport.ViewModels {
|
||||
public class ContentTypeEntry {
|
||||
public string Name { get; set; }
|
||||
public string DisplayName { get; set; }
|
||||
public bool ExportSchema { get; set; }
|
||||
public bool ExportData { get; set; }
|
||||
}
|
||||
}
|
@@ -0,0 +1,6 @@
|
||||
namespace Orchard.ImportExport.ViewModels {
|
||||
public class CustomStepEntry {
|
||||
public string CustomStep { get; set; }
|
||||
public bool IsChecked { get; set; }
|
||||
}
|
||||
}
|
@@ -0,0 +1,14 @@
|
||||
using System.Collections.Generic;
|
||||
using Orchard.ImportExport.Models;
|
||||
|
||||
namespace Orchard.ImportExport.ViewModels {
|
||||
public class DataExportStepViewModel {
|
||||
public DataExportStepViewModel() {
|
||||
ContentTypes = new List<ContentTypeEntry>();
|
||||
}
|
||||
|
||||
public IList<ContentTypeEntry> ContentTypes { get; set; }
|
||||
public VersionHistoryOptions VersionHistoryOptions { get; set; }
|
||||
public int? ImportBatchSize { get; set; }
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
using Orchard.Localization;
|
||||
|
||||
namespace Orchard.ImportExport.ViewModels {
|
||||
public class ExportStepViewModel {
|
||||
public string Name { get; set; }
|
||||
public LocalizedString DisplayName { get; set; }
|
||||
public LocalizedString Description { get; set; }
|
||||
public bool IsSelected { get; set; }
|
||||
public dynamic Editor { get; set; }
|
||||
}
|
||||
}
|
@@ -2,29 +2,7 @@
|
||||
|
||||
namespace Orchard.ImportExport.ViewModels {
|
||||
public class ExportViewModel {
|
||||
public IList<ContentTypeEntry> ContentTypes { get; set; }
|
||||
public IList<CustomStepEntry> CustomSteps { get; set; }
|
||||
public IList<dynamic> ExportSteps { get; set; }
|
||||
public bool Metadata { get; set; }
|
||||
public bool Data { get; set; }
|
||||
public int? ImportBatchSize { get; set; }
|
||||
public string DataImportChoice { get; set; }
|
||||
public bool SiteSettings { get; set; }
|
||||
public bool SetupRecipe { get; set; }
|
||||
public string RecipeName { get; set; }
|
||||
public string RecipeDescription { get; set; }
|
||||
public string RecipeWebsite { get; set; }
|
||||
public string RecipeTags { get; set; }
|
||||
public string RecipeVersion { get; set; }
|
||||
}
|
||||
|
||||
public class ContentTypeEntry {
|
||||
public string ContentTypeName { get; set; }
|
||||
public bool IsChecked { get; set; }
|
||||
}
|
||||
|
||||
public class CustomStepEntry {
|
||||
public string CustomStep { get; set; }
|
||||
public bool IsChecked { get; set; }
|
||||
public IList<ExportStepViewModel> ExportSteps { get; set; }
|
||||
}
|
||||
}
|
||||
|
@@ -0,0 +1,10 @@
|
||||
namespace Orchard.ImportExport.ViewModels {
|
||||
public class SetupRecipeStepViewModel {
|
||||
public string RecipeName { get; set; }
|
||||
public string RecipeDescription { get; set; }
|
||||
public string RecipeAuthor { get; set; }
|
||||
public string RecipeWebsite { get; set; }
|
||||
public string RecipeTags { get; set; }
|
||||
public string RecipeVersion { get; set; }
|
||||
}
|
||||
}
|
@@ -0,0 +1,3 @@
|
||||
namespace Orchard.ImportExport.ViewModels {
|
||||
public class SiteSettingsStepViewModel {}
|
||||
}
|
@@ -1,114 +1,44 @@
|
||||
@using Orchard.Localization
|
||||
@using Orchard.Utility.Extensions
|
||||
@using Orchard.Utility.Extensions
|
||||
@model Orchard.ImportExport.ViewModels.ExportViewModel
|
||||
@{ Layout.Title = T("Export").ToString(); }
|
||||
@using (Html.BeginFormAntiForgeryPost()) {
|
||||
Html.ValidationSummary();
|
||||
var exportStepIndex = 0;
|
||||
foreach (var exportStep in Model.ExportSteps) {
|
||||
var displayName = (LocalizedString)exportStep.DisplayName;
|
||||
var stepId = String.Format("step-{0}", displayName.ToString().HtmlClassify());
|
||||
<fieldset>
|
||||
<legend><label><input type="checkbox" id="@stepId" />@displayName</label></legend>
|
||||
<div data-controllerid="@stepId">
|
||||
@Display(exportStep)
|
||||
</div>
|
||||
</fieldset>
|
||||
}
|
||||
<fieldset>
|
||||
<legend>@T("Choose the types to include in the export file:")</legend>
|
||||
<label><input type="checkbox" class="check-all" />@T("Select all")</label>
|
||||
<ol>
|
||||
@for (var contentTypeIndex = 0; contentTypeIndex < Model.ContentTypes.Count; contentTypeIndex++) {
|
||||
<li>
|
||||
<input type="hidden" value="@Model.ContentTypes[contentTypeIndex].ContentTypeName" name="@Html.NameOf(m => m.ContentTypes[contentTypeIndex].ContentTypeName)"/>
|
||||
<input type="checkbox" value="true" name="@Html.NameOf(m => m.ContentTypes[contentTypeIndex].IsChecked)" id="@Html.NameOf(m => m.ContentTypes[contentTypeIndex].IsChecked)" />
|
||||
<label class="forcheckbox" for="@Html.NameOf(m => m.ContentTypes[contentTypeIndex].IsChecked)">@Model.ContentTypes[contentTypeIndex].ContentTypeName.CamelFriendly()</label>
|
||||
</li>
|
||||
}
|
||||
</ol>
|
||||
</fieldset>
|
||||
<hr />
|
||||
<fieldset>
|
||||
<legend>@T("Choose what to save for these types:")</legend>
|
||||
<div>
|
||||
@Html.EditorFor(m => m.Metadata)
|
||||
@Html.LabelFor(m => m.Metadata, T("Metadata").ToString(), new { @class = "forcheckbox" })
|
||||
@Html.Hint(T("Metadata is the definition of your content types: what parts and fields they have, with what settings."))
|
||||
</div>
|
||||
<div>
|
||||
@Html.EditorFor(m => m.Data)
|
||||
@Html.LabelFor(m => m.Data, T("Data").ToString(), new { @class = "forcheckbox" })
|
||||
@Html.Hint(T("Data is the actual content of your site."))
|
||||
</div>
|
||||
<div>
|
||||
@Html.LabelFor(m => m.ImportBatchSize, T("Batch Size"))
|
||||
@Html.TextBoxFor(m => m.ImportBatchSize, new {@class = "text small"})
|
||||
@Html.Hint(T("The batch size to use when importing the data. Leave empty to disable batched imports."))
|
||||
</div>
|
||||
<div>
|
||||
<p>@T("Version History")</p>
|
||||
@Html.RadioButtonFor(m => m.DataImportChoice, "Published", new {id = "Published", Checked = "Checked"})
|
||||
<label for="Published" class="forcheckbox">@T("Only Published Versions")</label>
|
||||
<br/>
|
||||
@Html.RadioButtonFor(m => m.DataImportChoice, "Draft", new {id = "Draft"})
|
||||
<label for="Draft" class="forcheckbox">@T("Only Drafts")</label>
|
||||
</div>
|
||||
<div>
|
||||
@Html.EditorFor(m => m.SiteSettings)
|
||||
<label class="forcheckbox" for="@Html.FieldIdFor(m => m.SiteSettings)">@T("Site Settings")</label><br/>
|
||||
@Html.Hint(T("Please verify that you are not exporting confidential information, such as passwords or application keys."))
|
||||
</div>
|
||||
</fieldset>
|
||||
<fieldset>
|
||||
<legend>@T("Setup")</legend>
|
||||
<div>
|
||||
@Html.CheckBoxFor(m => m.SetupRecipe)
|
||||
@Html.LabelFor(m => m.SetupRecipe, T("Setup Recipe").ToString(), new {@class = "forcheckbox"})
|
||||
@Html.Hint(T("Check this option if you want to use the generated recipe as a setup recipe."))
|
||||
</div>
|
||||
<div data-controllerid="@Html.FieldIdFor(m => m.SetupRecipe)">
|
||||
<div>
|
||||
@Html.LabelFor(m => m.RecipeName, T("Name"))
|
||||
@Html.TextBoxFor(m => m.RecipeName, new { @class = "text medium" })
|
||||
@Html.Hint(T("Optionally provide a name for the setup recipe."))
|
||||
var stepName = Html.NameFor(m => m.ExportSteps[exportStepIndex].IsSelected).ToString();
|
||||
var stepId = stepName.HtmlClassify();
|
||||
|
||||
<fieldset class="export-step export-step-@exportStep.Name.HtmlClassify()">
|
||||
<legend>
|
||||
<input type="hidden" name="@Html.NameFor(m => m.ExportSteps[exportStepIndex].Name)" value="@Model.ExportSteps[exportStepIndex].Name"/>
|
||||
<input type="checkbox" id="@stepId" name="@stepName" value="true"/>
|
||||
<label for="@stepId" class="forcheckbox">@exportStep.DisplayName</label>
|
||||
</legend>
|
||||
@Html.Hint(@exportStep.Description)
|
||||
<div data-controllerid="@stepId">
|
||||
@Display(exportStep.Editor)
|
||||
</div>
|
||||
<div>
|
||||
@Html.LabelFor(m => m.RecipeDescription, T("Description"))
|
||||
@Html.TextBoxFor(m => m.RecipeDescription, new {@class = "text large"})
|
||||
@Html.Hint(T("Optionally provide a description for the setup recipe."))
|
||||
</div>
|
||||
<div>
|
||||
@Html.LabelFor(m => m.RecipeWebsite, T("Website"))
|
||||
@Html.TextBoxFor(m => m.RecipeWebsite, new {@class = "text large"})
|
||||
@Html.Hint(T("Optionally provide a website URL for the setup recipe."))
|
||||
</div>
|
||||
<div>
|
||||
@Html.LabelFor(m => m.RecipeTags, T("Tags"))
|
||||
@Html.TextBoxFor(m => m.RecipeTags, new {@class = "text large"})
|
||||
@Html.Hint(T("Optionally provide tags for the setup recipe."))
|
||||
</div>
|
||||
<div>
|
||||
@Html.LabelFor(m => m.RecipeVersion, T("Version"))
|
||||
@Html.TextBoxFor(m => m.RecipeVersion, new {@class = "text small"})
|
||||
@Html.Hint(T("Optionally provide a version for the setup recipe."))
|
||||
</div>
|
||||
</div>
|
||||
</fieldset>
|
||||
</fieldset>
|
||||
exportStepIndex++;
|
||||
if (exportStepIndex < Model.ExportSteps.Count) {
|
||||
<hr />
|
||||
}
|
||||
}
|
||||
|
||||
if (Model.CustomSteps.Any()) {
|
||||
<fieldset>
|
||||
<legend>@T("Choose the custom steps to execute in the export file:")</legend>
|
||||
<ol>
|
||||
@for (var customStepIndex = 0; customStepIndex < Model.CustomSteps.Count; customStepIndex++) {
|
||||
<li>
|
||||
<input type="hidden" value="@Model.CustomSteps[customStepIndex].CustomStep" name="@Html.NameOf(m => m.CustomSteps[customStepIndex].CustomStep)"/>
|
||||
<input type="checkbox" value="true" name="@Html.NameOf(m => m.CustomSteps[customStepIndex].IsChecked)" id="@Html.NameOf(m => m.CustomSteps[customStepIndex].IsChecked)" />
|
||||
<label class="forcheckbox" for="@Html.NameOf(m => m.CustomSteps[customStepIndex].IsChecked)">@Model.CustomSteps[customStepIndex].CustomStep.CamelFriendly()</label>
|
||||
</li>
|
||||
}
|
||||
</ol>
|
||||
</fieldset>
|
||||
}
|
||||
<fieldset>
|
||||
<legend>@T("Choose the custom steps to execute in the export file:")</legend>
|
||||
<ol>
|
||||
@for (var customStepIndex = 0; customStepIndex < Model.CustomSteps.Count; customStepIndex++) {
|
||||
<li>
|
||||
<input type="hidden" value="@Model.CustomSteps[customStepIndex].CustomStep" name="@Html.NameOf(m => m.CustomSteps[customStepIndex].CustomStep)" />
|
||||
<input type="checkbox" value="true" name="@Html.NameOf(m => m.CustomSteps[customStepIndex].IsChecked)" id="@Html.NameOf(m => m.CustomSteps[customStepIndex].IsChecked)" />
|
||||
<label class="forcheckbox" for="@Html.NameOf(m => m.CustomSteps[customStepIndex].IsChecked)">@Model.CustomSteps[customStepIndex].CustomStep.CamelFriendly()</label>
|
||||
</li>
|
||||
}
|
||||
</ol>
|
||||
</fieldset>
|
||||
}
|
||||
|
||||
<button type="submit" class="primaryAction">@T("Export")</button>
|
||||
}
|
||||
|
@@ -1,5 +1,57 @@
|
||||
<table>
|
||||
<thead>
|
||||
@model Orchard.ImportExport.ViewModels.DataExportStepViewModel
|
||||
@{
|
||||
Style.Include("exportstep-data.css");
|
||||
}
|
||||
<div>
|
||||
<table class="items">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>@T("Content Type")</th>
|
||||
<th>@T("Schema")</th>
|
||||
<th>@T("Data")</th>
|
||||
<th>@T("Both")</th>
|
||||
</tr>
|
||||
<tr class="sub">
|
||||
<th> </th>
|
||||
<th><input type="checkbox"/></th>
|
||||
<th><input type="checkbox"/></th>
|
||||
<th><input type="checkbox"/></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@{ var contentTypeIndex = 0;}
|
||||
@foreach (var contentType in Model.ContentTypes) {
|
||||
<tr>
|
||||
<td>@contentType.DisplayName</td>
|
||||
<td>
|
||||
<input type="hidden" name="@Html.NameFor(m => m.ContentTypes[contentTypeIndex].Name)" value="@Model.ContentTypes[contentTypeIndex].Name"/>
|
||||
<input type="checkbox" name="@Html.NameFor(m => m.ContentTypes[contentTypeIndex].ExportSchema)" value="true"/>
|
||||
</td>
|
||||
<td>
|
||||
<input type="checkbox" name="@Html.NameFor(m => m.ContentTypes[contentTypeIndex].ExportData)" value="true"/>
|
||||
</td>
|
||||
<td><input type="checkbox"/></td>
|
||||
</tr>
|
||||
contentTypeIndex++;
|
||||
}
|
||||
</tbody>
|
||||
</table>
|
||||
@Html.Hint(T("Choose the types to include in the export file"))
|
||||
</div>
|
||||
|
||||
</thead>
|
||||
</table>
|
||||
<div>
|
||||
@Html.LabelFor(m => m.ImportBatchSize, T("Batch Size"))
|
||||
@Html.TextBoxFor(m => m.ImportBatchSize, new { @class = "text small" })
|
||||
@Html.Hint(T("The batch size to use when importing the data. Leave empty to disable batched imports."))
|
||||
</div>
|
||||
<div>
|
||||
<p>@T("Version History")</p>
|
||||
@Html.RadioButtonFor(m => m.VersionHistoryOptions, "Published", new { id = "Published", Checked = "Checked" })
|
||||
<label for="Published" class="forcheckbox">@T("Only Published Versions")</label>
|
||||
<br />
|
||||
@Html.RadioButtonFor(m => m.VersionHistoryOptions, "Draft", new { id = "Draft" })
|
||||
<label for="Draft" class="forcheckbox">@T("Only Drafts")</label>
|
||||
<br />
|
||||
@Html.RadioButtonFor(m => m.VersionHistoryOptions, "Latest", new { id = "Latest" })
|
||||
<label for="Latest" class="forcheckbox">@T("Latest Versions")</label>
|
||||
</div>
|
@@ -0,0 +1,31 @@
|
||||
@model Orchard.ImportExport.ViewModels.SetupRecipeStepViewModel
|
||||
<div>
|
||||
@Html.LabelFor(m => m.RecipeName, T("Name"))
|
||||
@Html.TextBoxFor(m => m.RecipeName, new { @class = "text medium" })
|
||||
@Html.Hint(T("Optionally provide a name for the setup recipe."))
|
||||
</div>
|
||||
<div>
|
||||
@Html.LabelFor(m => m.RecipeDescription, T("Description"))
|
||||
@Html.TextBoxFor(m => m.RecipeDescription, new {@class = "text large"})
|
||||
@Html.Hint(T("Optionally provide a description for the setup recipe."))
|
||||
</div>
|
||||
<div>
|
||||
@Html.LabelFor(m => m.RecipeAuthor, T("Author"))
|
||||
@Html.TextBoxFor(m => m.RecipeAuthor, new { @class = "text large" })
|
||||
@Html.Hint(T("Optionally provide the name of the author for the setup recipe."))
|
||||
</div>
|
||||
<div>
|
||||
@Html.LabelFor(m => m.RecipeWebsite, T("Website"))
|
||||
@Html.TextBoxFor(m => m.RecipeWebsite, new { @class = "text large" })
|
||||
@Html.Hint(T("Optionally provide a website URL for the setup recipe."))
|
||||
</div>
|
||||
<div>
|
||||
@Html.LabelFor(m => m.RecipeTags, T("Tags"))
|
||||
@Html.TextBoxFor(m => m.RecipeTags, new { @class = "text large" })
|
||||
@Html.Hint(T("Optionally provide tags for the setup recipe."))
|
||||
</div>
|
||||
<div>
|
||||
@Html.LabelFor(m => m.RecipeVersion, T("Version"))
|
||||
@Html.TextBoxFor(m => m.RecipeVersion, new { @class = "text small" })
|
||||
@Html.Hint(T("Optionally provide a version for the setup recipe."))
|
||||
</div>
|
@@ -0,0 +1,2 @@
|
||||
@model Orchard.ImportExport.ViewModels.SiteSettingsStepViewModel
|
||||
@Html.Hint(T("Please verify that you are not exporting confidential information, such as passwords or application keys."))
|
Reference in New Issue
Block a user