Add Team Meeting History functionality with dialog and badge components
This commit introduces a new feature to display meeting history for teams. It adds a `TeamMeetingHistoryDialog` component that shows the meeting history in a dialog format, including a loading state and error handling. Additionally, a `TeamMeetingHistoryBadge` component is created to display the count of meetings for each team, enhancing the user interface with tooltips for better interaction. The `Details` and `Index` components are updated to integrate these new features, allowing users to view meeting history directly from the team details and index pages. These changes improve the overall functionality and user experience in managing team meetings.
This commit is contained in:
@@ -0,0 +1,108 @@
|
||||
@namespace WebApp.Components.Features.Teams.Components
|
||||
@using Core.Entities
|
||||
@using WebApp.Services
|
||||
@using MudBlazor
|
||||
@inject ITeamMeetingHistoryService TeamMeetingHistoryService
|
||||
@inject IDialogService DialogService
|
||||
@implements IAsyncDisposable
|
||||
|
||||
@if (_meetingCount.HasValue && _meetingCount.Value > 0)
|
||||
{
|
||||
<MudTooltip Text="View Meeting History">
|
||||
<MudBadge Content="@_meetingCount.Value.ToString()"
|
||||
Color="Color.Primary"
|
||||
Overlap="true">
|
||||
<MudIconButton Icon="@Icons.Material.Filled.History"
|
||||
Size="Size.Small"
|
||||
Color="Color.Default"
|
||||
OnClick="OpenMeetingHistoryDialog"
|
||||
Variant="Variant.Text" />
|
||||
</MudBadge>
|
||||
</MudTooltip>
|
||||
}
|
||||
|
||||
@code {
|
||||
[Parameter]
|
||||
public int TeamId { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public string TeamName { get; set; } = string.Empty;
|
||||
|
||||
private int? _meetingCount;
|
||||
private CancellationTokenSource? _cancellationTokenSource;
|
||||
private bool _isDisposed = false;
|
||||
|
||||
protected override void OnInitialized()
|
||||
{
|
||||
_cancellationTokenSource = new CancellationTokenSource();
|
||||
}
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
await LoadMeetingCount();
|
||||
}
|
||||
|
||||
private async Task LoadMeetingCount()
|
||||
{
|
||||
if (_isDisposed) return;
|
||||
|
||||
try
|
||||
{
|
||||
var cancellationToken = _cancellationTokenSource?.Token ?? CancellationToken.None;
|
||||
_meetingCount = await TeamMeetingHistoryService.GetMeetingHistoryCountForTeamAsync(TeamId);
|
||||
}
|
||||
catch (TaskCanceledException)
|
||||
{
|
||||
// Component was disposed, ignore
|
||||
}
|
||||
catch (JSDisconnectedException)
|
||||
{
|
||||
// JS connection lost, ignore
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
// Ignore errors - just don't show the badge
|
||||
_meetingCount = null;
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (!_isDisposed)
|
||||
{
|
||||
StateHasChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private async Task OpenMeetingHistoryDialog()
|
||||
{
|
||||
if (_isDisposed) return;
|
||||
|
||||
var parameters = new DialogParameters
|
||||
{
|
||||
["TeamId"] = TeamId,
|
||||
["TeamName"] = TeamName
|
||||
};
|
||||
|
||||
var options = new DialogOptions
|
||||
{
|
||||
CloseOnEscapeKey = true,
|
||||
CloseButton = true,
|
||||
MaxWidth = MaxWidth.Medium,
|
||||
FullWidth = true
|
||||
};
|
||||
|
||||
await DialogService.ShowAsync<TeamMeetingHistoryDialog>($"{TeamName} Meeting History", parameters, options);
|
||||
}
|
||||
|
||||
public async ValueTask DisposeAsync()
|
||||
{
|
||||
if (!_isDisposed)
|
||||
{
|
||||
_isDisposed = true;
|
||||
_cancellationTokenSource?.Cancel();
|
||||
_cancellationTokenSource?.Dispose();
|
||||
_cancellationTokenSource = null;
|
||||
}
|
||||
await ValueTask.CompletedTask;
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
@using WebApp.Models
|
||||
@using Core.Utility
|
||||
@using WebApp.Components.Features.Teams.Components
|
||||
|
||||
@if (Title != null)
|
||||
{
|
||||
@@ -28,14 +29,17 @@
|
||||
@if (IsSelected(team))
|
||||
{
|
||||
var isExtended = IsExtended(team);
|
||||
<MudTooltip Text="@(isExtended ? "Remove from extended teams" : "Extend to 2 time slots")">
|
||||
<MudIconButton Icon="@(isExtended ? Icons.Material.Filled.AddCircle : Icons.Material.Filled.Add)"
|
||||
Size="Size.Small"
|
||||
Color="@(isExtended ? Color.Primary : Color.Default)"
|
||||
Variant="@(isExtended ? Variant.Filled : Variant.Text)"
|
||||
OnClick="@(() => ToggleExtended(team))"
|
||||
Style="margin-left: 4px; padding: 2px;" />
|
||||
</MudTooltip>
|
||||
<MudStack Row="true" AlignItems="AlignItems.Center" Spacing="1">
|
||||
<MudTooltip Text="@(isExtended ? "Remove from extended teams" : "Extend to 2 time slots")">
|
||||
<MudIconButton Icon="@(isExtended ? Icons.Material.Filled.AddCircle : Icons.Material.Filled.Add)"
|
||||
Size="Size.Small"
|
||||
Color="@(isExtended ? Color.Primary : Color.Default)"
|
||||
Variant="@(isExtended ? Variant.Filled : Variant.Text)"
|
||||
OnClick="@(() => ToggleExtended(team))"
|
||||
Style="margin-left: 4px; padding: 2px;" />
|
||||
</MudTooltip>
|
||||
<TeamMeetingHistoryBadge TeamId="@team.Id" TeamName="@team.ToString()" />
|
||||
</MudStack>
|
||||
}
|
||||
@if (ShowEventAttributes)
|
||||
{
|
||||
|
||||
@@ -3,9 +3,11 @@
|
||||
@using Microsoft.EntityFrameworkCore
|
||||
@using WebApp.Components.Shared.Components
|
||||
@using WebApp.Components.Features.Teams.Components
|
||||
@using MudBlazor
|
||||
@inject AppDbContext Context
|
||||
@inject NavigationManager NavigationManager
|
||||
@inject IJSRuntime JSRuntime
|
||||
@inject IDialogService DialogService
|
||||
|
||||
@if (Team is null)
|
||||
{
|
||||
@@ -29,6 +31,11 @@
|
||||
Href="@($"/teams/edit?id={Team.Id}&returnUrl={ReturnUrl ?? "/teams"}")"
|
||||
Variant="Variant.Outlined">Edit</MudButton>
|
||||
</MudTooltip>
|
||||
<MudTooltip Text="View Meeting History">
|
||||
<MudButton StartIcon="@Icons.Material.Filled.History"
|
||||
OnClick="ShowMeetingHistory"
|
||||
Variant="Variant.Outlined">Meeting History</MudButton>
|
||||
</MudTooltip>
|
||||
</div>
|
||||
</ActionButtons>
|
||||
</PageHeader>
|
||||
@@ -86,4 +93,26 @@
|
||||
{
|
||||
await JSRuntime.InvokeVoidAsync("window.print");
|
||||
}
|
||||
|
||||
private async Task ShowMeetingHistory()
|
||||
{
|
||||
if (Team == null) return;
|
||||
|
||||
var teamName = Team.ToString();
|
||||
var parameters = new DialogParameters
|
||||
{
|
||||
["TeamId"] = Team.Id,
|
||||
["TeamName"] = teamName
|
||||
};
|
||||
|
||||
var options = new DialogOptions
|
||||
{
|
||||
CloseOnEscapeKey = true,
|
||||
CloseButton = true,
|
||||
MaxWidth = MaxWidth.Medium,
|
||||
FullWidth = true
|
||||
};
|
||||
|
||||
await DialogService.ShowAsync<TeamMeetingHistoryDialog>($"{teamName} Meeting History", parameters, options);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -47,11 +47,12 @@
|
||||
<CellTemplate>
|
||||
<MudStack Row="true" AlignItems="AlignItems.Center" Justify="Justify.SpaceBetween" Spacing="1">
|
||||
<MudLink Href="@($"/teams/details?id={context.Item.Id}&returnUrl=/teams")"
|
||||
Underline="Underline.Hover"
|
||||
Color="Color.Primary">
|
||||
Underline="Underline.Hover"
|
||||
Color="Color.Primary">
|
||||
@context.Item.ToString()
|
||||
</MudLink>
|
||||
<MudStack Row="true" AlignItems="AlignItems.Center" Spacing="1">
|
||||
<TeamMeetingHistoryBadge TeamId="@context.Item.Id" TeamName="@context.Item.ToString()" />
|
||||
<IconButtonWithTooltip Icon="@Icons.Material.Filled.Edit"
|
||||
TooltipText="Edit"
|
||||
Href="@($"/teams/edit?id={context.Item.Id}&returnUrl=/teams")" />
|
||||
|
||||
@@ -0,0 +1,127 @@
|
||||
@namespace WebApp.Components.Features.Teams
|
||||
@using Core.Entities
|
||||
@using WebApp.Services
|
||||
@using Microsoft.AspNetCore.Components
|
||||
@inject ITeamMeetingHistoryService TeamMeetingHistoryService
|
||||
@implements IAsyncDisposable
|
||||
|
||||
<MudDialog>
|
||||
<TitleContent>
|
||||
<MudText Typo="Typo.h6">@TeamName Meeting History</MudText>
|
||||
</TitleContent>
|
||||
<DialogContent>
|
||||
@if (_isLoading)
|
||||
{
|
||||
<MudProgressLinear Color="Color.Primary" Indeterminate="true" Class="my-4" />
|
||||
}
|
||||
else if (!_meetingHistories.Any())
|
||||
{
|
||||
<MudAlert Severity="Severity.Info">No meeting history found for this team.</MudAlert>
|
||||
}
|
||||
else
|
||||
{
|
||||
<MudTable Items="_meetingHistories" Hover="true" Dense="true">
|
||||
<HeaderContent>
|
||||
<MudTh>Date</MudTh>
|
||||
<MudTh>Status</MudTh>
|
||||
</HeaderContent>
|
||||
<RowTemplate>
|
||||
@{
|
||||
var teamWasInMeeting = context.Teams.Any(t => t.Id == TeamId);
|
||||
}
|
||||
<MudTd>@context.MeetingDate.ToString("MM/dd/yyyy")</MudTd>
|
||||
<MudTd>
|
||||
<MudChip T="string" Size="Size.Small"
|
||||
Color="@(teamWasInMeeting ? Color.Success : Color.Default)"
|
||||
Variant="Variant.Text">
|
||||
@(teamWasInMeeting ? "Team Met" : "Team Not Scheduled")
|
||||
</MudChip>
|
||||
</MudTd>
|
||||
</RowTemplate>
|
||||
</MudTable>
|
||||
}
|
||||
</DialogContent>
|
||||
<DialogActions>
|
||||
<MudSpacer />
|
||||
<MudButton OnClick="Close">Close</MudButton>
|
||||
</DialogActions>
|
||||
</MudDialog>
|
||||
|
||||
@code {
|
||||
[CascadingParameter]
|
||||
IMudDialogInstance MudDialog { get; set; } = null!;
|
||||
|
||||
[Parameter]
|
||||
public int TeamId { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public string TeamName { get; set; } = string.Empty;
|
||||
|
||||
private List<TeamMeetingHistory> _meetingHistories = [];
|
||||
private bool _isLoading = true;
|
||||
private CancellationTokenSource? _cancellationTokenSource;
|
||||
private bool _isDisposed = false;
|
||||
|
||||
protected override void OnInitialized()
|
||||
{
|
||||
_cancellationTokenSource = new CancellationTokenSource();
|
||||
}
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
await LoadMeetingHistories();
|
||||
}
|
||||
|
||||
private async Task LoadMeetingHistories()
|
||||
{
|
||||
if (_isDisposed) return;
|
||||
|
||||
try
|
||||
{
|
||||
var cancellationToken = _cancellationTokenSource?.Token ?? CancellationToken.None;
|
||||
var histories = await TeamMeetingHistoryService.GetMeetingHistoriesForTeamAsync(TeamId);
|
||||
_meetingHistories = histories.ToList();
|
||||
}
|
||||
catch (TaskCanceledException)
|
||||
{
|
||||
// Component was disposed, ignore
|
||||
}
|
||||
catch (JSDisconnectedException)
|
||||
{
|
||||
// JS connection lost, ignore
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (!_isDisposed)
|
||||
{
|
||||
System.Diagnostics.Debug.WriteLine($"Error loading meeting histories: {ex.Message}");
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (!_isDisposed)
|
||||
{
|
||||
_isLoading = false;
|
||||
StateHasChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void Close()
|
||||
{
|
||||
if (_isDisposed) return;
|
||||
MudDialog.Close();
|
||||
}
|
||||
|
||||
public async ValueTask DisposeAsync()
|
||||
{
|
||||
if (!_isDisposed)
|
||||
{
|
||||
_isDisposed = true;
|
||||
_cancellationTokenSource?.Cancel();
|
||||
_cancellationTokenSource?.Dispose();
|
||||
_cancellationTokenSource = null;
|
||||
}
|
||||
await ValueTask.CompletedTask;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user