Skip to content

Commit

Permalink
Merge pull request #32 from EasyAbp/custom-actions
Browse files Browse the repository at this point in the history
Support for custom actions
  • Loading branch information
gdlcf88 authored Jul 9, 2024
2 parents db282ac + cd44447 commit cd90e1e
Show file tree
Hide file tree
Showing 14 changed files with 206 additions and 30 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,14 @@
"State:FailedToStartExporting": "Failed",
"State:Exporting": "Exporting",
"State:ExportFailed": "Failed",
"State:Succeeded": "Succeeded"
"State:Succeeded": "Succeeded",
"Action:Retry": "Retry",
"Action:Ping": "Ping",
"SureToRetry": "Are you sure to retry this process?",
"Success": "Success",
"SuccessToRetry": "The process has restarted running.",
"Permission:Demo": "Demo",
"Permission:Exporting": "Exporting",
"Permission:Retry": "Retry"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
using EasyAbp.ProcessManagement.Localization;
using Volo.Abp.Authorization.Permissions;
using Volo.Abp.Localization;

namespace EasyAbp.ProcessManagement.Permissions;

public class DemoPermissionDefinitionProvider : PermissionDefinitionProvider
{
public override void Define(IPermissionDefinitionContext context)
{
var demoGroup = context.AddGroup(DemoPermissions.GroupName, L("Permission:Demo"));

var exportingPermission =
demoGroup.AddPermission(DemoPermissions.Exporting.Default, L("Permission:Exporting"));

exportingPermission.AddChild(DemoPermissions.Exporting.Retry, L("Permission:Retry"));
}

private static LocalizableString L(string name)
{
return LocalizableString.Create<DemoResource>(name);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
using Volo.Abp.Reflection;

namespace EasyAbp.ProcessManagement.Permissions;

public class DemoPermissions
{
public const string GroupName = "Demo";

public static string[] GetAll()
{
return ReflectionHelper.GetPublicConstantsRecursively(typeof(DemoPermissions));
}

public class Exporting
{
public const string Default = GroupName + ".Exporting";
public const string Retry = Default + ".Retry";
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
using EasyAbp.ProcessManagement.Options;
using EasyAbp.ProcessManagement.Processes;
using EasyAbp.ProcessManagement.Web;
using EasyAbp.ProcessManagement.Web.Options;
using Microsoft.OpenApi.Models;
using Volo.Abp;
using Volo.Abp.Account;
Expand Down Expand Up @@ -134,6 +135,19 @@ public override void ConfigureServices(ServiceConfigurationContext context)
options.AddOrUpdateProcessDefinition(definition);
});

Configure<ProcessManagementWebOptions>(options =>
{
options.Actions.Add(new ProcessStateActionDefinition("FakeExport", "ExportFailed",
new LocalizableString("Action:Retry"),
"abp.message.confirm(l('SureToRetry')).then(function(confirmed){if(confirmed){abp.notify.success(l('SuccessToRetry'),l('Success'));if(alertNode){var alert=new bootstrap.Alert(alertNode);alert.close();}}})",
"abp.auth.isGranted('Demo.Exporting.Retry')"));
options.Actions.Add(new ProcessStateActionDefinition("FakeExport", "ExportFailed",
new LocalizableString("Action:Ping"),
"alert('Pong')",
null));
});

Configure<AbpDbContextOptions>(options => { options.UseSqlServer(); });

if (hostingEnvironment.IsDevelopment())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
"ProcessStateSummaryText": "Summary",
"ProcessStateUpdateTime": "Updated",
"ProcessUserName": "Username",
"TableFilter": "TableFilter"
"TableFilter": "TableFilter",
"MoreProcesses": "More processes →"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
"ProcessStateSummaryText": "概述",
"ProcessStateUpdateTime": "更新时间",
"ProcessUserName": "用户名",
"TableFilter": "筛选器"
"TableFilter": "筛选器",
"MoreProcesses": "查看更多流程 →"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
"ProcessStateSummaryText": "概述",
"ProcessStateUpdateTime": "更新時間",
"ProcessUserName": "使用者名",
"TableFilter": "篩選器"
"TableFilter": "篩選器",
"MoreProcesses": "查看更多流程 →"
}
}
Original file line number Diff line number Diff line change
@@ -1,26 +1,50 @@
@using EasyAbp.ProcessManagement.Localization
@using EasyAbp.ProcessManagement.Web.Options
@using Microsoft.AspNetCore.Mvc.Localization
@using Microsoft.Extensions.Localization
@using Microsoft.Extensions.Options
@inject IHtmlLocalizer<ProcessManagementResource> L
@inject IOptions<ProcessManagementWebOptions> Options
@inject IStringLocalizerFactory StringLocalizerFactory
@model EasyAbp.ProcessManagement.Web.Components.NotificationsOffcanvasWidget.NotificationsOffcanvasWidgetViewModel

@{
var customActions = "[" + Options.Value.Actions.Select(x =>
$"{{text:'{x.DisplayName.Localize(StringLocalizerFactory)}',action:function(data){{{x.OnClickCallbackCode}}},visible:function(data){{return data.processName==='{x.ProcessName}'&&data.stateName==='{x.StateName}'&&({x.VisibleCheckCode ?? "true"})}}}}")
.JoinAsString(",") + "]";
}
<script>
const notificationLifetimeMilliseconds = @Model.Options.NotificationLifetime.TotalMilliseconds;
var notificationOffcanvasAlertActions = @Html.Raw(customActions);
</script>

<style>
.clear-all-area {
.notification-offcanvas-action-area {
height: 40px;
display: none;
.more-processes-btn {
float: left;
padding: 0;
text-decoration: none;
color: var(--bs-offcanvas-color);
}
.clear-all-btn {
float: right;
padding: 0;
text-decoration: none;
color: var(--bs-offcanvas-color);
}
}
.clear-all-btn {
float: right;
padding: 0;
text-decoration: none;
color: var(--bs-offcanvas-color);
.alert-content-area {
.process-action-btn {
padding-top: 0;
padding-bottom: 0;
padding-left: 0;
color: var(--bs-offcanvas-color);
}
}
.no-notification-text {
text-align: center;
margin-top: 30px;
margin-top: 10px;
}
.svg-icon {
width: 24px;
Expand Down Expand Up @@ -61,10 +85,17 @@
<button type="button" class="btn-close text-reset" data-bs-dismiss="offcanvas" aria-label="Close"></button>
</div>
<div class="offcanvas-body" style="padding-top: 0">
<div class="clear-all-area">
<button type="button" id="notification-offcanvas-clear-all-btn" class="clear-all-btn btn btn-link"><small>@L["ClearAllNotifications"]</small></button>
<div class="notification-offcanvas-action-area">
<button type="button" id="notification-offcanvas-more-processes-btn" class="more-processes-btn btn btn-link">
<small>@L["MoreProcesses"]</small>
</button>
<button type="button" id="notification-offcanvas-clear-all-btn" class="clear-all-btn btn btn-link">
<small>@L["ClearAllNotifications"]</small>
</button>
</div>
<div id="no-notification-text" class="no-notification-text">
<small>@L["NoNotification"]</small>
</div>
<div id="no-notification-text" class="no-notification-text"><small>@L["NoNotification"]</small></div>
<div id="alert-placeholder"></div>
</div>
</div>
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
abp.widgets.NotificationsOffcanvasWidget = function ($widget) {

var intervalId;

function fetchAndShowAlerts() {
easyAbp.processManagement.notifications.notification.getList({
fromCreationTime: new Date(abp.clock.now() - notificationLifetimeMilliseconds),
Expand All @@ -25,7 +25,7 @@
removeAlert(alert)
}
});

res.items.forEach(function (item) {
if (!existingAlertIds.has(item.id)) {
var newAlert = createAlert(item);
Expand Down Expand Up @@ -68,15 +68,23 @@
}

function createAlert(item) {
var actionBtns = "";
for (var i in notificationOffcanvasAlertActions) {
var action = notificationOffcanvasAlertActions[i];
if (!action.visible(item)) continue;
var actionBtn = `<button type="button" id="action-btn-${i}-${item.id}" class="process-action-btn btn btn-link btn-sm">${action.text}</button><script>var actionBtn = document.getElementById('action-btn-${i}-${item.id}');actionBtn.addEventListener('click', function () {var l = abp.localization.getResource();var alertNode = document.getElementById('${item.id}');return ${action.action}(${JSON.stringify(item)});});</script>`
actionBtns += actionBtn;
}
return $(`
<div class="alert ${getAlertColorClassName(item.stateFlag)} alert-dismissible fade-in" role="alert">
<div class="d-flex">
<div class="d-flex mb-4">
<img src="/images/process-management/icons/${item.stateFlag}.svg" class="svg-icon" alt=""/>
<div>
<div class="alert-content-area">
<strong>${item.actionName ? item.actionName : item.stateDisplayName}</strong>
<p class="small mb-4">
<p class="small mb-0">
${item.stateSummaryText}
</p>
${actionBtns}
</div>
</div>
<div class="state-update-time">
Expand All @@ -90,7 +98,7 @@
function tryCreateInterval() {
intervalId = setInterval(fetchAndShowAlerts, 5000);
}

function tryClearInterval() {
if (intervalId) clearInterval(intervalId);
}
Expand All @@ -101,15 +109,13 @@
refreshBaseUiElements()
});
}
function refreshBaseUiElements(){

function refreshBaseUiElements() {
var alertPlaceholder = $('#alert-placeholder');
if (alertPlaceholder.find('.alert').length) {
$('#no-notification-text').hide();
$('.clear-all-area').show();
} else {
$('#no-notification-text').show();
$('.clear-all-area').hide();
}
}

Expand All @@ -125,9 +131,15 @@
tryClearInterval();
});

var moreProcessesBtn = document.getElementById('notification-offcanvas-more-processes-btn');
var clearAllBtn = document.getElementById('notification-offcanvas-clear-all-btn');

clearAllBtn.addEventListener('click', function() {
moreProcessesBtn.addEventListener('click', function () {
var url = abp.appPath + 'ProcessManagement/Processes/Process';
window.open(url, '_blank');
});

clearAllBtn.addEventListener('click', function () {
tryClearInterval();
var alertPlaceholder = $('#alert-placeholder');
var existingAlerts = alertPlaceholder.find('.alert');
Expand All @@ -137,7 +149,7 @@
var id = $(this).attr('id');
existingAlertIds.set(id, $(this));
});

easyAbp.processManagement.notifications.notification.dismiss({
notificationIds: existingAlertIds.keys().toArray()
}).then(function () {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,14 @@
using System;
using System.Collections.Generic;

namespace EasyAbp.ProcessManagement.Web.Options;

public class ProcessManagementWebOptions
{
public TimeSpan NotificationLifetime { get; set; } = TimeSpan.FromDays(7);

/// <summary>
/// Defined actions for users to initiate.
/// </summary>
public List<ProcessStateActionDefinition> Actions { get; } = new();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
using Volo.Abp.Localization;

namespace EasyAbp.ProcessManagement.Web.Options;

public class ProcessStateActionDefinition
{
/// <summary>
/// The hardcoded Name value from ProcessDefinition.
/// </summary>
public string ProcessName { get; set; } = null!;

/// <summary>
/// The hardcoded state name defined by the backend.
/// </summary>
public string StateName { get; set; } = null!;

/// <summary>
/// Display name.
/// </summary>
public ILocalizableString DisplayName { get; set; } = null!;

/// <summary>
/// JS code that is executed when the action button is clicked.
/// </summary>
/// <example>detailsModal.open({id: data.record.id});</example>
public string OnClickCallbackCode { get; set; } = null!;

/// <summary>
/// JS code for the action visible check. Skip checking if null.
/// </summary>
/// <example>abp.auth.isGranted('MyPermissionName')</example>
public string? VisibleCheckCode { get; set; }

public ProcessStateActionDefinition(string processName, string stateName, ILocalizableString displayName,
string onClickCallbackCode, string? visibleCheckCode)
{
ProcessName = processName;
StateName = stateName;
DisplayName = displayName;
OnClickCallbackCode = onClickCallbackCode;
VisibleCheckCode = visibleCheckCode;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
@using Volo.Abp.AspNetCore.Mvc.UI.Layout
@using EasyAbp.ProcessManagement.Web.Pages.ProcessManagement.Processes.Process
@using EasyAbp.ProcessManagement.Localization
@using EasyAbp.ProcessManagement.Web.Menus
@model IndexModel
@inject IPageLayout PageLayout
@inject IHtmlLocalizer<ProcessManagementResource> L
Expand All @@ -23,6 +22,10 @@
<abp-style src="/Pages/ProcessManagement/Processes/Process/index.css"/>
}

<script>
var customActions = @Html.Raw(Model.CustomActions);
</script>

<abp-card>
<abp-card-header>
<abp-row>
Expand Down
Loading

0 comments on commit cd90e1e

Please sign in to comment.