Skip to content
Open
Show file tree
Hide file tree
Changes from 24 commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
8801b88
fix database inheritance
Behnam-Emamian Nov 29, 2025
341162f
add radzen
Behnam-Emamian Nov 29, 2025
41991d8
abstract class ModuleService
Behnam-Emamian Nov 30, 2025
5849071
Enhance category management with tree view and context menu #5
mirza-developer Nov 30, 2025
79eeca6
fix merge conflicts #5
mirza-developer Nov 30, 2025
a079b3c
add radzen tree for categories #5
mirza-developer Nov 30, 2025
23dc877
Integrate Radzen components and improve category tree #5
mirza-developer Dec 2, 2025
0da65db
fix conflict
Behnam-Emamian Dec 3, 2025
b6af827
File Entity
Behnam-Emamian Dec 7, 2025
848355f
merge main changes
Behnam-Emamian Dec 18, 2025
0644985
Add File management CRUD API and client service
mirza-developer Dec 18, 2025
8fafbb9
Enhance file edit UI, add metadata & category selection #18
mirza-developer Dec 19, 2025
dc7b0c0
Merge branch 'main' of https://github.com/ICTAce/FileHub into feature…
mirza-developer Dec 19, 2025
61dd919
Update FileCategory FKs and fix ImageName column mapping
mirza-developer Dec 22, 2025
90a9498
Add file upload support to file edit form and backend #18
mirza-developer Dec 22, 2025
cb64fe8
Switch to RadzenUpload for file uploads with progress #18
mirza-developer Dec 22, 2025
2111b48
Refactor file/image upload to use Blazor InputFile
mirza-developer Dec 24, 2025
47b6533
Add support for multi-category file associations
mirza-developer Dec 26, 2025
33c5f53
Add ModuleId to FileCategory entity and schema #18
mirza-developer Dec 26, 2025
f44978a
update nugets
Behnam-Emamian Dec 28, 2025
3c4fa74
Refactor file listing to use Radzen cards and controls for a more att…
mirza-developer Dec 28, 2025
d0c5787
Merge branch 'feature/filehub' of https://github.com/ICTAce/FileHub i…
mirza-developer Dec 28, 2025
477b065
Refactor file form and card UI for clarity and usability #18
mirza-developer Dec 29, 2025
266c2bf
Add file download endpoint and UI; improve file serving #18
mirza-developer Dec 31, 2025
6a48124
Update file download handling and UI counter feedback #18
mirza-developer Dec 31, 2025
9f35c3a
Add download param & atomic download counter increment #18
mirza-developer Dec 31, 2025
4e73cab
Refactor file deletion to Edit page, remove from Index #18
mirza-developer Jan 1, 2026
0b4e4f2
Remove SampleModule feature and all related code #18
mirza-developer Jan 2, 2026
7bda640
Add FileHub module manager with install, export, search #18
mirza-developer Jan 3, 2026
a96abb7
delete log
Behnam-Emamian Jan 4, 2026
6390b60
add fallback to ApplicationQueryContext
Behnam-Emamian Jan 4, 2026
0780530
remove sample module
Behnam-Emamian Jan 4, 2026
8a71e2e
remove last samplemodule
Behnam-Emamian Jan 4, 2026
5bc25fd
server content is local files
Behnam-Emamian Jan 4, 2026
9000bc0
merge from main
Behnam-Emamian Jan 4, 2026
aaeb401
add RadzenThemeManager
Behnam-Emamian Jan 4, 2026
06a2a7c
Improve file/image upload UX and update file save logic #18
mirza-developer Jan 5, 2026
b05f885
Add mock IFileService and FileHub client-side test suites #18
mirza-developer Jan 8, 2026
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
1 change: 1 addition & 0 deletions Client/GlobalUsings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
global using ICTAce.FileHub.Services;
global using ICTAce.FileHub.Services.Common;
global using Microsoft.AspNetCore.Components;
global using Microsoft.AspNetCore.Components.Forms;
global using Microsoft.AspNetCore.Components.Web;
global using Microsoft.Extensions.DependencyInjection;
global using Microsoft.Extensions.Localization;
Expand Down
160 changes: 153 additions & 7 deletions Client/Modules/FileHub/Edit.razor
Original file line number Diff line number Diff line change
@@ -1,20 +1,166 @@
@namespace ICTAce.FileHub
@inherits ModuleBase

<form @ref="form" class="@(_validated ? " was-validated" : "needs-validation" )" novalidate>
<RadzenTheme Theme="material" />

<form @ref="form" class="@(_validated ? " was-validated" : "needs-validation")" novalidate>
<div class="container">
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="name" HelpText="Enter a name" ResourceKey="Name">Name: </Label>
<div class="row mb-3">
<div class="col-md-12">
<h4>@(PageState.Action == "Add" ? "Add New File" : "Edit File")</h4>
</div>
</div>

<div class="row mb-3">
<Label Class="col-sm-3" For="fileUpload" HelpText="Upload a file" ResourceKey="FileUpload">File Upload: </Label>
<div class="col-sm-9">
<div class="input-group">
<InputFile id="fileUpload"
class="form-control"
OnChange="@OnFileSelected"
accept="*/*"
disabled="@_isUploading" />
<label class="input-group-text" for="fileUpload">
@if (_isUploading)
{
<span class="spinner-border spinner-border-sm me-2" role="status" aria-hidden="true"></span>
<text>@_uploadProgress%</text>
}
else
{
<i class="oi oi-cloud-upload"></i>
}
</label>
</div>
@if (!string.IsNullOrEmpty(_uploadedFileName))
{
<div class="form-text text-success mt-2">
<i class="oi oi-check"></i> Uploaded
</div>
}
<div class="form-text">Maximum file size: 100MB</div>
</div>
</div>

<div class="row mb-3">
<Label Class="col-sm-3" For="name" HelpText="Enter file name" ResourceKey="Name">Name: </Label>
<div class="col-sm-9">
<input id="name" class="form-control" @bind="@_name" maxlength="100" required />
<div class="invalid-feedback">Name is required (max 100 characters)</div>
</div>
</div>
<input id="fileName" class="form-control" @bind="@_fileName" maxlength="255" type="hidden" />
<div class="row mb-3">
<Label Class="col-sm-3" For="imageName" HelpText="Upload thumbnail/preview image" ResourceKey="ImageName">Thumbnail Image: </Label>
<div class="col-sm-9">
<input id="name" class="form-control" @bind="@_name" required />
<div class="input-group mb-2">
<InputFile id="imageUpload"
class="form-control"
OnChange="@OnImageSelected"
accept="image/*"
disabled="@_isUploadingImage" />
<label class="input-group-text" for="imageUpload">
@if (_isUploadingImage)
{
<span class="spinner-border spinner-border-sm me-2" role="status" aria-hidden="true"></span>
<text>@_imageUploadProgress%</text>
}
else
{
<i class="oi oi-image"></i>
}
</label>
</div>
@if (!string.IsNullOrEmpty(_uploadedImageName))
{
<div class="form-text text-success mb-2">
<i class="oi oi-check"></i> Uploaded - size: @_fileSize
</div>
}
<input id="imageName" type="hidden" @bind="@_imageName" />
<div class="form-text">Optional - Upload thumbnail/preview image (JPG, PNG, GIF - Max 10MB)</div>
</div>
</div>
<div class="row mb-3">
<Label Class="col-sm-3" For="description" HelpText="Enter a description (optional)" ResourceKey="Description">Description: </Label>
<div class="col-sm-9">
<textarea id="description" class="form-control" @bind="@_description" maxlength="1000" rows="4"></textarea>
<div class="form-text">Optional - max 1000 characters</div>
</div>
</div>
@if (string.Equals(PageState.Action, "Edit", StringComparison.Ordinal))
{
<div class="row mb-3">
<Label Class="col-sm-3" For="downloads" HelpText="Number of downloads" ResourceKey="Downloads">Downloads: </Label>
<div class="col-sm-9">
<input id="downloads" type="number" class="form-control" @bind="@_downloads" min="0" readonly />
<div class="invalid-feedback">Downloads must be 0 or greater</div>
</div>
</div>
}
<div class="row mb-3">
<Label Class="col-sm-3" For="categories" HelpText="Select categories for this file" ResourceKey="Categories">Categories: </Label>
<div class="col-sm-9">
@if (_isLoadingCategories)
{
<p><em>Loading categories...</em></p>
}
else
{
<div style="border: 1px solid #dee2e6; border-radius: 4px; padding: 10px; max-height: 300px; overflow-y: auto;">
<RadzenTree Data="@(new List<ListCategoryDto> { _rootNode })"
@bind-CheckedValues="@_selectedCategories"
Style="width: 100%;"
AllowCheckBoxes="true"
AllowCheckChildren="true"
AllowCheckParents="true">
<RadzenTreeLevel TextProperty="@(nameof(ListCategoryDto.Name))"
ChildrenProperty="@(nameof(ListCategoryDto.Children))"
HasChildren="@(e => ((ListCategoryDto)e).Children?.Any() == true)"
Expanded="@(e => ((ListCategoryDto)e).IsExpanded)">
<Template>
@{
var category = (context.Value as ListCategoryDto);
var isRootNode = category?.Id == 0;
}
<span style="font-weight: @(isRootNode ? "bold" : "normal");">
@if (isRootNode)
{
<i class="oi oi-folder" style="margin-right: 4px;"></i>
}
@category?.Name
</span>
</Template>
</RadzenTreeLevel>
</RadzenTree>
</div>
<div class="form-text mt-2">
@if (_selectedCategories != null && _selectedCategories.Any())
{
<span>Selected: @string.Join(", ", _selectedCategories.OfType<ListCategoryDto>().Where(c => c.Id > 0).Select(c => c.Name))</span>
}
else
{
<span>No categories selected</span>
}
</div>
}
</div>
</div>
</div>
<button type="button" class="btn btn-success" @onclick="Save">@Localizer["Save"]</button>
<NavLink class="btn btn-secondary" href="@NavigateUrl()">@Localizer["Cancel"]</NavLink>

<div class="mt-4">
<button type="button" class="btn btn-success" @onclick="Save" disabled="@_isUploading">
<i class="oi oi-check"></i> @Localizer["Save"]
</button>
<NavLink class="btn btn-secondary" href="@NavigateUrl()">
<i class="oi oi-x"></i> @Localizer["Cancel"]
</NavLink>
</div>

<br /><br />
@if (PageState.Action == "Edit")
{
<AuditInfo CreatedBy="@_createdby" CreatedOn="@_createdon" ModifiedBy="@_modifiedby" ModifiedOn="@_modifiedon"></AuditInfo>
<AuditInfo CreatedBy="@_createdby" CreatedOn="@_createdon" ModifiedBy="@_modifiedby" ModifiedOn="@_modifiedon"></AuditInfo>
}
</form>
Loading
Loading