Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,11 +1,17 @@
using Volo.Abp.Reflection;
using Volo.Abp.Reflection;

namespace Unity.Flex.Permissions;

public static class FlexPermissions
{
public const string GroupName = "Flex";

public static class Worksheets
{
public const string Default = GroupName + ".Worksheets";
public const string Delete = GroupName + ".Worksheets.Delete";
}

public static string[] GetAll()
{
return ReflectionHelper.GetPublicConstantsRecursively(typeof(FlexPermissions));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ public interface IWorksheetAppService : IApplicationService
Task<WorksheetDto> CloneAsync(Guid id);
Task<bool> PublishAsync(Guid id);
Task DeleteAsync(Guid id);
Task<WorksheetLinkedFormsDto> GetLinkedFormsAsync(Guid worksheetId);
Task ResequenceSectionsAsync(Guid id, uint oldIndex, uint newIndex);
Task<bool> ExistsAsync(Guid worksheetId);
Task<ExportWorksheetDto> ExportWorksheet(Guid worksheetId);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
using System;
using System.Collections.Generic;

namespace Unity.Flex.Worksheets
{
public class WorksheetLinkedFormsDto
{
public List<Guid> FormVersionIdsWithInstances { get; set; } = [];
public List<Guid> LinkedFormVersionIds { get; set; } = [];
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,6 @@ public interface IWorksheetInstanceRepository : IBasicRepository<WorksheetInstan
Task<List<WorksheetInstance>> GetByWorksheetCorrelationAsync(Guid worksheetId, string uiAnchor, Guid worksheetCorrelationId, string worksheetCorrelationProvider);
Task<WorksheetInstance?> GetWithValuesAsync(Guid worksheetInstanceId);
Task<bool> ExistsAsync(Guid worksheetId, Guid instanceCorrelationId, string instanceCorrelationProvider, Guid sheetCorrelationId, string sheetCorrelationProvider, string? uiAnchor);
Task<bool> AnyByWorksheetAndFormVersionAsync(Guid worksheetId, Guid formVersionId);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using System.Linq;
using System.Threading.Tasks;
using Unity.Flex.Domain.WorksheetInstances;
using Unity.Modules.Shared.Correlation;
using Volo.Abp.Domain.Repositories.EntityFrameworkCore;
using Volo.Abp.EntityFrameworkCore;

Expand Down Expand Up @@ -50,11 +51,11 @@ public async Task<List<WorksheetInstance>> GetByWorksheetCorrelationAsync(Guid w
.FirstOrDefaultAsync(wi => wi.Id == worksheetInstanceId);
}

public async Task<bool> ExistsAsync(Guid worksheetId,
Guid instanceCorrelationId,
string instanceCorrelationProvider,
Guid sheetCorrelationId,
string sheetCorrelationProvider,
public async Task<bool> ExistsAsync(Guid worksheetId,
Guid instanceCorrelationId,
string instanceCorrelationProvider,
Guid sheetCorrelationId,
string sheetCorrelationProvider,
string? uiAnchor)
{
var dbSet = await GetDbSetAsync();
Expand All @@ -67,5 +68,13 @@ public async Task<bool> ExistsAsync(Guid worksheetId,
&& s.WorksheetCorrelationProvider == sheetCorrelationProvider
&& s.UiAnchor == uiAnchor);
}

public async Task<bool> AnyByWorksheetAndFormVersionAsync(Guid worksheetId, Guid formVersionId)
{
var dbSet = await GetDbSetAsync();
return await dbSet.AnyAsync(s => s.WorksheetId == worksheetId
&& s.WorksheetCorrelationId == formVersionId
&& s.WorksheetCorrelationProvider == CorrelationConsts.FormVersion);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,19 @@ public class FlexPermissionDefinitionProvider : PermissionDefinitionProvider
public override void Define(IPermissionDefinitionContext context)
{
context.AddGroup(FlexPermissions.GroupName, L("Permission:Flex"));

var settingsMgmt = context.GetGroupOrNull("SettingManagement");
if (settingsMgmt != null)
{
var configureWorksheet = settingsMgmt.AddPermission(
FlexPermissions.Worksheets.Default,
L("Permission:Flex.Worksheets")
);
configureWorksheet.AddChild(
FlexPermissions.Worksheets.Delete,
L("Permission:Flex.Worksheets.Delete")
);
}
}

private static LocalizableString L(string name)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,12 @@
using Unity.Flex.Domain.Services;
using Unity.Flex.Domain.Settings;
using Unity.Flex.Domain.Utils;
using Unity.Flex.Domain.WorksheetInstances;
using Unity.Flex.Domain.WorksheetLinks;
using Unity.Flex.Domain.Worksheets;
using Unity.Flex.Permissions;
using Unity.Flex.Reporting.FieldGenerators;
using Unity.Modules.Shared.Correlation;
using Unity.Modules.Shared.Features;
using Volo.Abp;
using Volo.Abp.Features;
Expand All @@ -19,7 +23,9 @@ namespace Unity.Flex.Worksheets
public partial class WorksheetAppService(IWorksheetRepository worksheetRepository,
WorksheetsManager worksheetsManager,
IReportingFieldsGeneratorService<Worksheet> reportingFieldsGeneratorService,
IFeatureChecker featureChecker) : FlexAppService, IWorksheetAppService
IFeatureChecker featureChecker,
IWorksheetLinkRepository worksheetLinkRepository,
IWorksheetInstanceRepository worksheetInstanceRepository) : FlexAppService, IWorksheetAppService
{
public virtual async Task<WorksheetDto> GetAsync(Guid id)
{
Expand Down Expand Up @@ -118,11 +124,41 @@ public virtual async Task<bool> PublishAsync(Guid id)
return await Task.FromResult(true);
}

[Authorize(FlexPermissions.Worksheets.Delete)]
public virtual async Task DeleteAsync(Guid id)
{
var linkedForms = await GetLinkedFormsAsync(id);

if (linkedForms.FormVersionIdsWithInstances.Count > 0)
{
throw new UserFriendlyException("This worksheet cannot be deleted because it has existing instances.");
}

if (linkedForms.LinkedFormVersionIds.Count > 0)
{
throw new UserFriendlyException("This worksheet cannot be deleted because it is still linked to one or more forms. Unlink it first.");
}

await worksheetRepository.DeleteAsync(id);
}

public virtual async Task<WorksheetLinkedFormsDto> GetLinkedFormsAsync(Guid worksheetId)
{
var links = await worksheetLinkRepository.GetListByWorksheetAsync(worksheetId, CorrelationConsts.FormVersion);
var result = new WorksheetLinkedFormsDto();

foreach (var correlationId in links.Select(link => link.CorrelationId))
{
bool hasInstances = await worksheetInstanceRepository.AnyByWorksheetAndFormVersionAsync(worksheetId, correlationId);
if (hasInstances)
result.FormVersionIdsWithInstances.Add(correlationId);
else
result.LinkedFormVersionIds.Add(correlationId);
}

return result;
}

public virtual async Task ResequenceSectionsAsync(Guid id, uint oldIndex, uint newIndex)
{
if (oldIndex == newIndex) return;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@
"Worksheet:Configuration:AddColumnOptionText": "Add Column",
"DataGrids:DynamicColumnsHeader": "Dynamic Columns",
"DataGrids:CustomColumnsHeader": "Custom Columns",
"DataGrids:PredefinedColumn": "Predefined column"
"DataGrids:PredefinedColumn": "Predefined column",
"Permission:Flex.Worksheets": "Configure Worksheet",
"Permission:Flex.Worksheets.Delete": "Delete Worksheet"
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
@using Microsoft.AspNetCore.Mvc.Localization
@using Unity.Flex.Localization;
@using Unity.Flex.Permissions;
@using Unity.Flex.Web.Views.Shared.Components.Worksheets;
@using Volo.Abp.Authorization.Permissions;

Expand Down Expand Up @@ -31,6 +32,12 @@
<button data-worksheet-id="@worksheet.Id" data-worksheet-title="@worksheet.Title" data-worksheet-name="@worksheet.Name" class="btn btn-light export-worksheet-btn worksheet-btn" type="button">
<i class="fl fl-export"></i> <span>@L["Worksheet:Configuration:ExportWorksheetButtonText"].Value</span>
</button>
@if (await PermissionChecker.IsGrantedAsync(FlexPermissions.Worksheets.Delete))
{
<button data-worksheet-id="@worksheet.Id" data-worksheet-title="@worksheet.Title" data-worksheet-name="@worksheet.Name" class="btn btn-light delete-worksheet-btn worksheet-btn" type="button">
<i class="fl fl-delete"></i> <span>@L["Worksheet:Configuration:DeleteWorksheetButtonText"].Value</span>
</button>
}
</div>
</div>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,15 @@ $(function () {
});
}

let deleteWorksheetButtons = $(".delete-worksheet-btn");

if (deleteWorksheetButtons) {
deleteWorksheetButtons.on("click", function (event) {
let btn = event.currentTarget;
handleDeleteWorksheet(btn.dataset.worksheetId, btn.dataset.worksheetTitle, btn.dataset.worksheetName);
});
}

setupTooltips();
}

Expand Down Expand Up @@ -223,3 +232,46 @@ $(function () {
}
);
});

function handleDeleteWorksheet(worksheetId, worksheetTitle, worksheetName) {
unity.grantManager.settingManagement.worksheetConfiguration.getDeletionCheck(worksheetId)
.done(function (result) {
if (result.blockingFormNames && result.blockingFormNames.length > 0) {
abp.message.error(
'This worksheet cannot be deleted because it is already used by the following forms:\n' + result.blockingFormNames.join('\n'),
'Delete Worksheet'
);
} else if (result.linkedFormNames && result.linkedFormNames.length > 0) {
abp.message.error(
'Unlink the worksheet (' + worksheetTitle + ' \u2013 ' + worksheetName + ') from the following forms before deletion:\n' + result.linkedFormNames.join('\n'),
'Delete Worksheet'
);
} else {
abp.message.confirm(
'Are you sure you want to delete the worksheet "' + worksheetTitle + '"?',
'Delete Worksheet',
function (confirmed) {
if (confirmed) {
executeWorksheetDelete(worksheetId);
}
}
);
}
})
.fail(function (e) {
abp.notify.error('Failed to check worksheet deletion status.');
console.warn('Worksheet deletion check failed:', e);
});
}

function executeWorksheetDelete(worksheetId) {
unity.flex.worksheets.worksheet.delete(worksheetId)
.done(function () {
PubSub.publish('refresh_worksheet_list', { worksheetId: worksheetId, action: 'Delete' });
abp.notify.success('Worksheet deleted successfully.', 'Delete Worksheet');
})
.fail(function (e) {
abp.notify.error('Failed to delete worksheet.');
console.warn('Worksheet deletion failed:', e);
});
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
using System;
using System.Threading.Tasks;
using Volo.Abp.Application.Services;

namespace Unity.GrantManager.SettingManagement;

public interface IWorksheetConfigurationAppService : IApplicationService
{
Task<WorksheetDeletionCheckDto> GetDeletionCheckAsync(Guid worksheetId);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
using System.Collections.Generic;

namespace Unity.GrantManager.SettingManagement;

public class WorksheetDeletionCheckDto
{
public List<string> BlockingFormNames { get; set; } = [];
public List<string> LinkedFormNames { get; set; } = [];
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
using System;
using System.Threading.Tasks;
using Unity.Flex.Worksheets;
using Unity.GrantManager.Applications;

namespace Unity.GrantManager.SettingManagement;

public class WorksheetConfigurationAppService(
IWorksheetAppService worksheetAppService,
IApplicationFormVersionRepository formVersionRepository,
IApplicationFormRepository formRepository
) : GrantManagerAppService, IWorksheetConfigurationAppService
{
public async Task<WorksheetDeletionCheckDto> GetDeletionCheckAsync(Guid worksheetId)
{
var linkedForms = await worksheetAppService.GetLinkedFormsAsync(worksheetId);
var result = new WorksheetDeletionCheckDto();

foreach (var formVersionId in linkedForms.FormVersionIdsWithInstances)
{
var formName = await ResolveFormNameAsync(formVersionId);
result.BlockingFormNames.Add(formName);
}

foreach (var formVersionId in linkedForms.LinkedFormVersionIds)
{
var formName = await ResolveFormNameAsync(formVersionId);
result.LinkedFormNames.Add(formName);
}

return result;
}

private async Task<string> ResolveFormNameAsync(Guid formVersionId)
{
var formVersion = await formVersionRepository.FindAsync(formVersionId);
if (formVersion == null) return formVersionId.ToString();

var form = await formRepository.FindAsync(formVersion.ApplicationFormId);
if (form == null) return formVersionId.ToString();

return formVersion.Version.HasValue
? $"{form.ApplicationFormName} – v{formVersion.Version}"
: $"{form.ApplicationFormName}";
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System.Collections.Generic;
using System.Threading.Tasks;
using Unity.Flex.Permissions;
using Unity.GrantManager.Identity;
using Unity.Modules.Shared;
using Unity.Notifications.Permissions;
Expand Down Expand Up @@ -131,7 +132,8 @@ await _permissionDataSeeder.SeedAsync(RolePermissionValueProvider.ProviderName,
UnitySelector.Payment.Supplier.Update,
.. Notifications_CommonPermissions,
.. Dashboard_CommonPermissions,
.. Tags_CommonPermissions
.. Tags_CommonPermissions,
FlexPermissions.Worksheets.Delete
], context.TenantId);

// - Reviewer
Expand Down
Loading