Skip to content

Commit

Permalink
Export specific workflow (#11939)
Browse files Browse the repository at this point in the history
  • Loading branch information
hyzx86 committed Apr 25, 2024
1 parent 9cf1f78 commit f15ccb7
Show file tree
Hide file tree
Showing 7 changed files with 90 additions and 27 deletions.
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.IO.Compression;
using System.Linq;
using System.Text.Json;
using System.Text.Json.Nodes;
Expand All @@ -13,12 +14,17 @@
using Microsoft.Extensions.Localization;
using Microsoft.Extensions.Options;
using OrchardCore.Admin;
using OrchardCore.Deployment;
using OrchardCore.Deployment.Core.Services;
using OrchardCore.DisplayManagement;
using OrchardCore.DisplayManagement.ModelBinding;
using OrchardCore.DisplayManagement.Notify;
using OrchardCore.Json;
using OrchardCore.Navigation;
using OrchardCore.Recipes.Models;
using OrchardCore.Routing;
using OrchardCore.Workflows.Activities;
using OrchardCore.Workflows.Deployment;
using OrchardCore.Workflows.Helpers;
using OrchardCore.Workflows.Indexes;
using OrchardCore.Workflows.Models;
Expand All @@ -41,9 +47,9 @@ public class WorkflowTypeController : Controller
private readonly IAuthorizationService _authorizationService;
private readonly IActivityDisplayManager _activityDisplayManager;
private readonly INotifier _notifier;
private readonly ISecurityTokenService _securityTokenService;
private readonly IUpdateModelAccessor _updateModelAccessor;
private readonly IShapeFactory _shapeFactory;
private readonly JsonSerializerOptions _documentJsonSerializerOptions;

protected readonly IStringLocalizer S;
protected readonly IHtmlLocalizer H;
Expand All @@ -60,10 +66,10 @@ public WorkflowTypeController
IActivityDisplayManager activityDisplayManager,
IShapeFactory shapeFactory,
INotifier notifier,
ISecurityTokenService securityTokenService,
IStringLocalizer<WorkflowTypeController> stringLocalizer,
IHtmlLocalizer<WorkflowTypeController> htmlLocalizer,
IUpdateModelAccessor updateModelAccessor)
IUpdateModelAccessor updateModelAccessor,
IOptions<DocumentJsonSerializerOptions> jsonSerializerOptions)
{
_pagerOptions = pagerOptions.Value;
_session = session;
Expand All @@ -74,11 +80,11 @@ public WorkflowTypeController
_authorizationService = authorizationService;
_activityDisplayManager = activityDisplayManager;
_notifier = notifier;
_securityTokenService = securityTokenService;
_updateModelAccessor = updateModelAccessor;
_shapeFactory = shapeFactory;
S = stringLocalizer;
H = htmlLocalizer;
_documentJsonSerializerOptions = jsonSerializerOptions.Value.SerializerOptions;
}

[Admin("Workflows/Types", "WorkflowTypes")]
Expand Down Expand Up @@ -192,6 +198,9 @@ public async Task<IActionResult> BulkEdit(WorkflowTypeIndexOptions options, IEnu
{
case WorkflowTypeBulkAction.None:
break;
case WorkflowTypeBulkAction.Export:
return await ExportWorkflows(itemIds.ToArray());

case WorkflowTypeBulkAction.Delete:
foreach (var entry in checkedEntries)
{
Expand All @@ -213,7 +222,19 @@ public async Task<IActionResult> BulkEdit(WorkflowTypeIndexOptions options, IEnu
return RedirectToAction(nameof(Index));
}

public async Task<IActionResult> EditProperties(long? id, string returnUrl = null)
[HttpPost]
public async Task<IActionResult> Export(int id)
{
if (!await _authorizationService.AuthorizeAsync(User, Permissions.ManageWorkflows))
{
return Forbid();
}

return await ExportWorkflows(id);
}

public async Task<IActionResult> EditProperties(int? id, string returnUrl = null)

{
if (!await _authorizationService.AuthorizeAsync(User, Permissions.ManageWorkflows))
{
Expand Down Expand Up @@ -546,5 +567,28 @@ public async Task<IActionResult> Delete(long id)

return activityShape;
}

private async Task<IActionResult> ExportWorkflows(params long[] itemIds)
{
using var fileBuilder = new TemporaryFileBuilder();
var archiveFileName = fileBuilder.Folder + ".zip";
var recipeDescriptor = new RecipeDescriptor();
var deploymentPlanResult = new DeploymentPlanResult(fileBuilder, recipeDescriptor);
var workflowTypes = await _workflowTypeStore.GetAsync(itemIds);

AllWorkflowTypeDeploymentSource.ProcessWorkflowType(deploymentPlanResult, workflowTypes, _documentJsonSerializerOptions);

await deploymentPlanResult.FinalizeAsync();
ZipFile.CreateFromDirectory(fileBuilder.Folder, archiveFileName);

var packageName = itemIds.Length == 1
? workflowTypes.FirstOrDefault().Name
: S["Workflow Types"];

return new PhysicalFileResult(archiveFileName, "application/zip")
{
FileDownloadName = packageName + ".zip",
};
}
}
}
@@ -1,9 +1,11 @@
using System.Collections.Generic;
using System.Text.Json;
using System.Text.Json.Nodes;
using System.Threading.Tasks;
using Microsoft.Extensions.Options;
using OrchardCore.Deployment;
using OrchardCore.Json;
using OrchardCore.Workflows.Models;
using OrchardCore.Workflows.Services;

namespace OrchardCore.Workflows.Deployment
Expand All @@ -28,23 +30,27 @@ public async Task ProcessDeploymentStepAsync(DeploymentStep step, DeploymentPlan
return;
}

var data = new JsonArray();
result.Steps.Add(new JsonObject
{
["name"] = "WorkflowType",
["data"] = data,
});
ProcessWorkflowType(result, await _workflowTypeStore.ListAsync(), _jsonSerializerOptions);
}

foreach (var workflow in await _workflowTypeStore.ListAsync())
public static void ProcessWorkflowType(DeploymentPlanResult result, IEnumerable<WorkflowType> workflowTypes, JsonSerializerOptions jsonSerializerOptions)
{
var data = new JsonArray();

foreach (var workflowType in workflowTypes)
{
var objectData = JObject.FromObject(workflow, _jsonSerializerOptions);
var objectData = JObject.FromObject(workflowType, jsonSerializerOptions);

// Don't serialize the Id as it could be interpreted as an updated object when added back to YesSql
objectData.Remove(nameof(workflow.Id));
objectData.Remove(nameof(workflowType.Id));
data.Add(objectData);
}

return;
result.Steps.Add(new JsonObject
{
["name"] = "WorkflowType",
["data"] = data,
});
}
}
}
Expand Up @@ -25,7 +25,7 @@
<ProjectReference Include="..\..\OrchardCore\OrchardCore.ContentManagement.Display\OrchardCore.ContentManagement.Display.csproj" />
<ProjectReference Include="..\..\OrchardCore\OrchardCore.Data.Abstractions\OrchardCore.Data.Abstractions.csproj" />
<ProjectReference Include="..\..\OrchardCore\OrchardCore.Data.YesSql\OrchardCore.Data.YesSql.csproj" />
<ProjectReference Include="..\..\OrchardCore\OrchardCore.Deployment.Abstractions\OrchardCore.Deployment.Abstractions.csproj" />
<ProjectReference Include="..\..\OrchardCore\OrchardCore.Deployment.Core\OrchardCore.Deployment.Core.csproj" />
<ProjectReference Include="..\..\OrchardCore\OrchardCore.DisplayManagement.Liquid\OrchardCore.DisplayManagement.Liquid.csproj" />
<ProjectReference Include="..\..\OrchardCore\OrchardCore.DisplayManagement\OrchardCore.DisplayManagement.csproj" />
<ProjectReference Include="..\..\OrchardCore\OrchardCore.Navigation.Core\OrchardCore.Navigation.Core.csproj" />
Expand Down
Expand Up @@ -28,7 +28,7 @@ public WorkflowMethodsProvider(WorkflowExecutionContext workflowContext)
_workflowIdMethod = new GlobalMethod
{
Name = "workflowId",
Method = serviceProvider => (Func<string>)(() => workflowContext.Workflow.WorkflowId),
Method = serviceProvider => () => workflowContext.Workflow.WorkflowId,
};

_inputMethod = new GlobalMethod
Expand Down Expand Up @@ -58,13 +58,13 @@ public WorkflowMethodsProvider(WorkflowExecutionContext workflowContext)
_resultMethod = new GlobalMethod
{
Name = "lastResult",
Method = serviceProvider => (Func<object>)(() => workflowContext.LastResult),
Method = serviceProvider => () => workflowContext.LastResult,
};

_correlationIdMethod = new GlobalMethod
{
Name = "correlationId",
Method = serviceProvider => (Func<string>)(() => workflowContext.Workflow.CorrelationId),
Method = serviceProvider => () => workflowContext.Workflow.CorrelationId,
};

_setCorrelationIdMethod = new GlobalMethod
Expand Down
Expand Up @@ -46,6 +46,7 @@ public enum WorkflowTypeFilter
public enum WorkflowTypeBulkAction
{
None,
Export,
Delete
}
}
Expand Up @@ -11,6 +11,7 @@
</ol>
</nav>
</zone>

<div class="card text-bg-theme mb-3">
<div class="card-body">
<div class="d-flex justify-content-between">
Expand All @@ -23,6 +24,7 @@
</button>
</div>
<div>
<a class="btn btn-sm btn-secondary" asp-action="Export" data-url-af="UnsafeUrl" asp-route-id="@Model.WorkflowType.Id" asp-route-returnUrl="@FullRequestPath">@T["Export"]</a>
<a class="btn btn-sm btn-secondary" asp-action="EditProperties" asp-route-id="@Model.WorkflowType.Id" asp-route-returnUrl="@FullRequestPath">@T["Properties"]</a>
<a class="btn btn-sm btn-secondary" asp-action="Index" asp-controller="Workflow" asp-route-workflowtypeid="@Model.WorkflowType.Id" asp-route-returnUrl="@FullRequestPath">@T["Instances"] <span class="badge ta-badge">@Model.WorkflowCount</span></a>
</div>
Expand Down
Expand Up @@ -48,6 +48,7 @@
@T["Actions"]
</button>
<ul class="dropdown-menu dropdown-menu-end" aria-labelledby="bulk-action-menu-button">
<li><a class="dropdown-item" href="javascript:void(0)" data-action="Export" data-title="@T["Bulk Action"]">Export</a></li>
@foreach (var item in Model.Options.WorkflowTypesBulkAction)
{
<li><a class="dropdown-item" href="javascript:void(0)" data-action="@item.Value" data-title="@T["Bulk Action"]" data-message="@T["Are you sure you want to {0} these items?", @item.Text.ToLower()]">@item.Text</a></li>
Expand All @@ -63,6 +64,7 @@
<li class="list-group-item">
<div class="properties">
<div class="float-end">
<a asp-action="Export" data-url-af="UnsafeUrl" asp-route-id="@entry.WorkflowType.Id" asp-route-returnUrl="@FullRequestPath" class="btn btn-sm btn-secondary">@T["Export"]</a>
<a asp-action="Edit" asp-route-id="@entry.WorkflowType.Id" asp-route-returnUrl="@FullRequestPath" class="btn btn-primary btn-sm">@T["Edit"]</a>
<a asp-action="EditProperties" asp-route-id="@entry.WorkflowType.Id" asp-route-returnUrl="@FullRequestPath" class="btn btn-success btn-sm">@T["Properties"]</a>
<a asp-action="Delete" asp-route-id="@entry.WorkflowType.Id" class="btn btn-danger btn-sm" data-url-af="RemoveUrl UnsafeUrl">@T["Delete"]</a>
Expand Down Expand Up @@ -121,14 +123,22 @@
}).on("click", function () {
if ($(":checkbox[name='itemIds']:checked").length > 1) {
var $this = $(this);
confirmDialog({
title: $this.data('title'), message: $this.data('message'), callback: function (r) {
if (r) {
$("[name='Options.BulkAction']").val($this.data("action"));
$("[name='submit.BulkAction']").click();
}
}
});
switch ($this.data("action")) {
case "Delete":
confirmDialog({
title: $this.data('title'), message: $this.data('message'), callback: function (r) {
if (r) {
$("[name='Options.BulkAction']").val($this.data("action"));
$("[name='submit.BulkAction']").click();
}
}
});
break;
case "Export":
$("[name='Options.BulkAction']").val($this.data("action"));
$("[name='submit.BulkAction']").click();
break;
}
}
});
Expand Down

0 comments on commit f15ccb7

Please sign in to comment.