Skip to content

Commit 4420679

Browse files
Move category to settings (#23)
* move to settings * save solution * add css and js * move to settings * fix loading scripts * fix loading scripts * fix css * update nugets * fix location * add advanced security
1 parent 4a4d828 commit 4420679

File tree

15 files changed

+257
-151
lines changed

15 files changed

+257
-151
lines changed

.github/dependabot.yml

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
version: 2
2+
updates:
3+
# Enable version updates for NuGet
4+
- package-ecosystem: "nuget"
5+
directory: "/"
6+
schedule:
7+
interval: "weekly"
8+
open-pull-requests-limit: 10
9+
labels:
10+
- "dependencies"
11+
- "dotnet"
12+
13+
# Enable version updates for npm (Blazor WebAssembly)
14+
- package-ecosystem: "npm"
15+
directory: "/"
16+
schedule:
17+
interval: "weekly"
18+
open-pull-requests-limit: 5
19+
labels:
20+
- "dependencies"
21+
- "javascript"
22+
23+
# Enable version updates for GitHub Actions
24+
- package-ecosystem: "github-actions"
25+
directory: "/"
26+
schedule:
27+
interval: "monthly"
28+
labels:
29+
- "dependencies"
30+
- "github-actions"
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
name: "CodeQL"
2+
3+
on:
4+
push:
5+
branches: [ "main", "feature/*" ]
6+
pull_request:
7+
branches: [ "main" ]
8+
schedule:
9+
- cron: '0 0 * * 1' # Run weekly on Mondays
10+
11+
jobs:
12+
analyze:
13+
name: Analyze
14+
runs-on: ubuntu-latest
15+
permissions:
16+
actions: read
17+
contents: read
18+
security-events: write
19+
20+
strategy:
21+
fail-fast: false
22+
matrix:
23+
language: [ 'csharp', 'javascript' ]
24+
25+
steps:
26+
- name: Checkout repository
27+
uses: actions/checkout@v4
28+
29+
- name: Setup .NET
30+
uses: actions/setup-dotnet@v4
31+
with:
32+
dotnet-version: '9.0.x'
33+
34+
- name: Initialize CodeQL
35+
uses: github/codeql-action/init@v3
36+
with:
37+
languages: ${{ matrix.language }}
38+
queries: security-extended,security-and-quality
39+
40+
- name: Autobuild
41+
uses: github/codeql-action/autobuild@v3
42+
43+
- name: Perform CodeQL Analysis
44+
uses: github/codeql-action/analyze@v3
45+
with:
46+
category: "/language:${{matrix.language}}"

Client/Modules/FileHub/Category.razor

Lines changed: 50 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,7 @@
44
<h3>Categories</h3>
55

66
<RadzenTheme Theme="material" />
7-
<RadzenContextMenu />
8-
<RadzenDialog />
7+
<RadzenComponents />
98

109
@if (IsLoading)
1110
{
@@ -17,58 +16,54 @@ else if (!string.IsNullOrEmpty(ErrorMessage))
1716
}
1817
else
1918
{
20-
<div style="width: 100%; height: 500px; position: relative; margin-bottom: 20px;">
21-
<RadzenTree Data="@(new List<ListCategoryDto> { _rootNode })"
22-
Style="width: 100%; height: 100%;"
23-
Expand="@OnNodeExpand"
24-
Collapse="@OnNodeCollapse">
25-
<RadzenTreeLevel TextProperty="@(nameof(ListCategoryDto.Name))"
26-
ChildrenProperty="@(nameof(ListCategoryDto.Children))"
27-
HasChildren=@(e => ((ListCategoryDto)e).Children?.Any() == true)
28-
Expanded="@(e => ((ListCategoryDto)e).IsExpanded)">
29-
<Template>
30-
@{
31-
var category = (context.Value as ListCategoryDto);
32-
var isEditing = IsInlineEditing && EditingNode != null && EditingNode.Id == category?.Id;
33-
var isRootNode = category?.Id == 0;
34-
}
19+
<RadzenTree Data="@(new List<ListCategoryDto> { _rootNode })"
20+
Style="width: 100%; height: 100%;"
21+
Expand="@OnNodeExpand"
22+
Collapse="@OnNodeCollapse">
23+
<RadzenTreeLevel TextProperty="@(nameof(ListCategoryDto.Name))"
24+
ChildrenProperty="@(nameof(ListCategoryDto.Children))"
25+
HasChildren=@(e => ((ListCategoryDto)e).Children?.Any() == true)
26+
Expanded="@(e => ((ListCategoryDto)e).IsExpanded)">
27+
<Template>
28+
@{
29+
var category = (context.Value as ListCategoryDto);
30+
var isEditing = IsInlineEditing && EditingNode != null && EditingNode.Id == category?.Id;
31+
var isRootNode = category?.Id == 0;
32+
}
3533

36-
@if (isEditing)
37-
{
38-
<div style="display: inline-flex; align-items: center; gap: 4px;">
39-
<RadzenTextBox @bind-Value="@EditingNodeName"
40-
@onkeydown="HandleKeyPress"
41-
Style="width: 200px; height: 24px; font-size: 14px;"
42-
AutoComplete="false" />
43-
<RadzenButton Icon="check"
44-
ButtonStyle="ButtonStyle.Success"
45-
Size="ButtonSize.ExtraSmall"
46-
Click="@SaveInlineEdit"
47-
title="Save (Enter)" />
48-
<RadzenButton Icon="close"
49-
ButtonStyle="ButtonStyle.Light"
50-
Size="ButtonSize.ExtraSmall"
51-
Click="@CancelInlineEdit"
52-
title="Cancel (Esc)" />
53-
</div>
54-
}
55-
else
56-
{
57-
<span @oncontextmenu="@(args => ShowContextMenu(args, category))"
58-
@oncontextmenu:preventDefault="true"
59-
@ondblclick="@(() => OnNodeDoubleClick(category))"
60-
style="cursor: pointer; font-weight: @(isRootNode ? "bold" : "normal");">
61-
@if (isRootNode)
62-
{
63-
<i class="oi oi-folder" style="margin-right: 4px;"></i>
64-
}
65-
@category?.Name
66-
</span>
67-
}
68-
</Template>
69-
</RadzenTreeLevel>
70-
</RadzenTree>
71-
</div>
72-
34+
@if (isEditing)
35+
{
36+
<div style="display: inline-flex; align-items: center; gap: 4px;">
37+
<RadzenTextBox @bind-Value="@EditingNodeName"
38+
@onkeydown="HandleKeyPress"
39+
Style="width: 200px; height: 24px; font-size: 14px;"
40+
AutoCompleteType="AutoCompleteType.Off" />
41+
<RadzenButton Icon="check"
42+
ButtonStyle="ButtonStyle.Success"
43+
Size="ButtonSize.ExtraSmall"
44+
Click="@SaveInlineEdit"
45+
title="Save (Enter)" />
46+
<RadzenButton Icon="close"
47+
ButtonStyle="ButtonStyle.Light"
48+
Size="ButtonSize.ExtraSmall"
49+
Click="@CancelInlineEdit"
50+
title="Cancel (Esc)" />
51+
</div>
52+
}
53+
else
54+
{
55+
<span @oncontextmenu="@(args => ShowContextMenu(args, category))"
56+
@oncontextmenu:preventDefault="true"
57+
@ondblclick="@(() => OnNodeDoubleClick(category))"
58+
style="cursor: pointer; font-weight: @(isRootNode ? "bold" : "normal");">
59+
@if (isRootNode)
60+
{
61+
<i class="oi oi-folder" style="margin-right: 4px;"></i>
62+
}
63+
@category?.Name
64+
</span>
65+
}
66+
</Template>
67+
</RadzenTreeLevel>
68+
</RadzenTree>
7369
}
74-

Client/Modules/FileHub/Category.razor.cs

Lines changed: 34 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@ public partial class Category : ModuleBase
1616
[Inject]
1717
private Radzen.DialogService DialogService { get; set; } = default!;
1818

19+
[Parameter]
20+
public int ModuleId { get; set; }
21+
1922
private const string SuccessNotificationMessage = "Success";
2023
private const string ErrorNotificationMessage = "Error";
2124
private List<ListCategoryDto> _treeData = [];
@@ -41,7 +44,7 @@ protected override async Task OnInitializedAsync()
4144
ErrorMessage = null;
4245
try
4346
{
44-
Categories = await CategoryService.ListAsync(ModuleState.ModuleId, pageNumber: 1, pageSize: int.MaxValue);
47+
Categories = await CategoryService.ListAsync(ModuleId, pageNumber: 1, pageSize: int.MaxValue);
4548
CreateTreeStructure();
4649
}
4750
catch (Exception ex)
@@ -56,7 +59,10 @@ protected override async Task OnInitializedAsync()
5659

5760
private void ShowContextMenu(MouseEventArgs args, ListCategoryDto? category)
5861
{
59-
if (category == null) return;
62+
if (category == null)
63+
{
64+
return;
65+
}
6066

6167
SelectedCategory = category;
6268

@@ -69,7 +75,7 @@ private void ShowContextMenu(MouseEventArgs args, ListCategoryDto? category)
6975
Text = "Add Category",
7076
Value = "add",
7177
Icon = "add",
72-
}
78+
},
7379
};
7480

7581
ContextMenuService.Open(args, rootMenuItems, OnContextMenuClick);
@@ -117,8 +123,10 @@ private void ShowContextMenu(MouseEventArgs args, ListCategoryDto? category)
117123
ContextMenuService.Open(args, menuItems, OnContextMenuClick);
118124
}
119125

120-
private void OnContextMenuClick(Radzen.MenuItemEventArgs args)
126+
private async void OnContextMenuClick(Radzen.MenuItemEventArgs args)
121127
{
128+
ContextMenuService.Close();
129+
122130
var action = args.Value?.ToString();
123131

124132
switch (action)
@@ -130,17 +138,15 @@ private void OnContextMenuClick(Radzen.MenuItemEventArgs args)
130138
EditCategoryInline();
131139
break;
132140
case "moveup":
133-
_ = MoveUp();
141+
await MoveUp();
134142
break;
135143
case "movedown":
136-
_ = MoveDown();
144+
await MoveDown();
137145
break;
138146
case "delete":
139-
PromptDeleteCategory();
147+
await PromptDeleteCategory();
140148
break;
141149
}
142-
143-
ContextMenuService.Close();
144150
}
145151

146152
private bool CanMoveUp(ListCategoryDto category)
@@ -283,7 +289,7 @@ private async Task SaveInlineEdit()
283289
ParentId = EditingNode.ParentId,
284290
};
285291

286-
var id = await CategoryService.CreateAsync(ModuleState.ModuleId, createDto);
292+
var id = await CategoryService.CreateAsync(ModuleId, createDto);
287293
await logger.LogInformation("Category Created {Id}", id);
288294

289295
// Update the temporary node in-place with the real ID and name
@@ -308,7 +314,7 @@ private async Task SaveInlineEdit()
308314
ParentId = EditingNode.ParentId,
309315
};
310316

311-
await CategoryService.UpdateAsync(EditingNode.Id, ModuleState.ModuleId, updateDto);
317+
await CategoryService.UpdateAsync(EditingNode.Id, ModuleId, updateDto);
312318
await logger.LogInformation("Category Updated {Id}", EditingNode.Id);
313319

314320
// Update the node name in-place
@@ -405,7 +411,7 @@ private async Task MoveUp()
405411
var previous = siblings[currentIndex - 1];
406412

407413
// Update on server using dedicated move endpoint
408-
await CategoryService.MoveUpAsync(current.Id, ModuleState.ModuleId);
414+
await CategoryService.MoveUpAsync(current.Id, ModuleId);
409415

410416
// Swap ViewOrder values locally
411417
(current.ViewOrder, previous.ViewOrder) = (previous.ViewOrder, current.ViewOrder);
@@ -460,7 +466,7 @@ private async Task MoveDown()
460466
var next = siblings[currentIndex + 1];
461467

462468
// Update on server using dedicated move endpoint
463-
await CategoryService.MoveDownAsync(current.Id, ModuleState.ModuleId);
469+
await CategoryService.MoveDownAsync(current.Id, ModuleId);
464470

465471
// Swap ViewOrder values locally
466472
(current.ViewOrder, next.ViewOrder) = (next.ViewOrder, current.ViewOrder);
@@ -534,7 +540,7 @@ private async Task DeleteCategory()
534540
{
535541
var categoryToDelete = SelectedCategory;
536542

537-
await CategoryService.DeleteAsync(categoryToDelete.Id, ModuleState.ModuleId);
543+
await CategoryService.DeleteAsync(categoryToDelete.Id, ModuleId);
538544
await logger.LogInformation("Category Deleted {Id}", categoryToDelete.Id);
539545

540546
if (categoryToDelete.ParentId is null)
@@ -545,10 +551,7 @@ private async Task DeleteCategory()
545551
else
546552
{
547553
var parent = FindCategoryById([_rootNode], categoryToDelete.ParentId.Value);
548-
if (parent != null)
549-
{
550-
parent.Children.Remove(categoryToDelete);
551-
}
554+
parent?.Children.Remove(categoryToDelete);
552555
}
553556

554557
NotificationService.Notify(new Radzen.NotificationMessage
@@ -577,7 +580,7 @@ private async Task DeleteCategory()
577580

578581
private void CreateTreeStructure()
579582
{
580-
if (Categories.Items is null || !Categories.Items.Any())
583+
if (Categories.Items?.Any() != true)
581584
{
582585
_treeData = [];
583586

@@ -589,7 +592,7 @@ private void CreateTreeStructure()
589592
ParentId = -1,
590593
ViewOrder = 0,
591594
IsExpanded = true,
592-
Children = []
595+
Children = [],
593596
};
594597
return;
595598
}
@@ -625,23 +628,26 @@ private void CreateTreeStructure()
625628
ParentId = null,
626629
ViewOrder = 0,
627630
IsExpanded = true,
628-
Children = _treeData
631+
Children = _treeData,
629632
};
630633
}
631634

632635
private static void SortChildren(List<ListCategoryDto> categories)
633636
{
634637
foreach (var category in categories)
635638
{
636-
if (category.Children.Any())
639+
if (category.Children.Count == 0)
637640
{
638-
category.Children = category.Children
639-
.OrderBy(c => c.ViewOrder)
640-
.ThenBy(c => c.Name, StringComparer.Ordinal)
641-
.ToList();
642-
643-
SortChildren(category.Children.ToList());
641+
continue;
644642
}
643+
644+
var sortedChildren = category.Children
645+
.OrderBy(c => c.ViewOrder)
646+
.ThenBy(c => c.Name, StringComparer.Ordinal)
647+
.ToList();
648+
649+
category.Children = sortedChildren;
650+
SortChildren(sortedChildren);
645651
}
646652
}
647653

Client/Modules/FileHub/Index.razor

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,4 @@ else
2929
{
3030
<p>@Localizer["Message.DisplayNone"]</p>
3131
}
32-
33-
<ICTAce.FileHub.Category />
3432
}

Client/Modules/FileHub/Index.razor.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ public partial class Index
1212
[
1313
new Stylesheet(ModulePath() + "Module.css"),
1414
new Script(ModulePath() + "Module.js"),
15-
new Script("_content/Radzen.Blazor/Radzen.Blazor.js"),
1615
];
1716

1817
private List<ListSampleModuleDto>? _filehubs;

0 commit comments

Comments
 (0)