Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
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
179 changes: 173 additions & 6 deletions Client/Modules/FileHub/Edit.razor
Original file line number Diff line number Diff line change
@@ -1,20 +1,187 @@
@namespace ICTAce.FileHub
@inherits ModuleBase

<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: @_uploadedFileName
</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>

<div class="row mb-3">
<Label Class="col-sm-3" For="fileName" HelpText="Enter the actual file name" ResourceKey="FileName">File Name: </Label>
<div class="col-sm-9">
<input id="name" class="form-control" @bind="@_name" required />
<input id="fileName" class="form-control" @bind="@_fileName" maxlength="255" required readonly />
<div class="invalid-feedback">File name is required (max 255 characters)</div>
<div class="form-text">Auto-filled from uploaded file</div>
</div>
</div>

<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">
<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: @_uploadedImageName
</div>
<div class="mb-2">
<img src="@GetImageUrl()" alt="Thumbnail preview" class="img-thumbnail" style="max-width: 200px; max-height: 200px;" />
</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="fileSize" HelpText="File size" ResourceKey="FileSize">File Size: </Label>
<div class="col-sm-9">
<input id="fileSize" class="form-control" @bind="@_fileSize" maxlength="12" readonly />
<div class="invalid-feedback">File size is required (max 12 characters)</div>
<div class="form-text">Auto-filled from uploaded file</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>

<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" />
<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>

<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>
<button type="button" class="btn btn-success" @onclick="Save">@Localizer["Save"]</button>
<NavLink class="btn btn-secondary" href="@NavigateUrl()">@Localizer["Cancel"]</NavLink>

<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