Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
47 commits
Select commit Hold shift + click to select a range
2ce7094
Update dotnet-dev-build.yml
bberka Apr 6, 2025
4ea0fc8
fix: statistics calculation corrected
bberka Apr 6, 2025
56d9ea6
fix: discord bot intents
bberka Apr 6, 2025
d642ddb
chore: removed duplicated bot dependency configuration
bberka Apr 6, 2025
9187c0d
feat: Converted ProcessedReactionDiscordEmoji string to unicode
bberka Apr 6, 2025
98d3b8a
feat: Enhance user engagement with mirrored reactions
bberka Apr 6, 2025
3405c23
feat: Implement mirrored message deletion
bberka Apr 6, 2025
9ca8168
feat: added new log messages
bberka Apr 7, 2025
31f1bfc
feat: new lang keys
bberka Apr 7, 2025
7ea76de
feat(UtilMention.cs): implemented new utility class
bberka Apr 7, 2025
f5318ee
feat: Centralize mention handling with UtilMention class
bberka Apr 7, 2025
de7903b
feat(TicketMessageQueue.cs): better log messages
bberka Apr 7, 2025
e7d7974
chore: removed unnecessary DI injection
bberka Apr 7, 2025
84f2fb2
feat: Improve Modmail event handling through modularization
bberka Apr 7, 2025
1467181
chore: updated DSharp plus latest nuget nightly version
bberka Apr 7, 2025
5702bc5
feat: Improve project structure with vertical slicing and granular co…
bberka Apr 7, 2025
8b4649b
fix: Properly handle anonymous flag during mod message updates
bberka Apr 7, 2025
e18c1a1
feat(TicketMessageHistory.cs): new table added and migrated
bberka Apr 7, 2025
f85bb06
feat: Implement tracking of TicketMessage status changes
bberka Apr 7, 2025
0c4e0d9
feat(Transcript.razor): Display message status and fix message orderi…
bberka Apr 7, 2025
1b7fd15
feat: implement message update and delete event handlers to add messa…
bberka Apr 7, 2025
32f600c
chore: version v2.3
bberka Apr 7, 2025
896fc31
fix: db migration issue when upgrading from 2.2 to 2.3
bberka Apr 7, 2025
dde939c
fix: issue where modal submit causing same message always
bberka Apr 7, 2025
ea44da5
fix: ticket data deletion logic
bberka Apr 7, 2025
4ee1d12
fix: guild option incorrect range constraints
bberka Apr 8, 2025
47f80cc
feat: Enhance Guild Option UI with visual separators and descriptions
bberka Apr 8, 2025
b521c32
feat: implement ticket feedback data view dialog
bberka Apr 8, 2025
7d1d309
fix: Prevent multiple feedback submissions and remove initial feedbac…
bberka Apr 8, 2025
723ff44
fix: Make feedback content optional and enforce length limits from co…
bberka Apr 8, 2025
2add4a9
feat: Implement a feedback list page
bberka Apr 8, 2025
f272dbe
feat: Introduce tag system groundwork (database and entities)
bberka Apr 8, 2025
e420294
feat: Add preliminary permission policies (currently inactive)
bberka Apr 8, 2025
4cd72e7
feat: Convert ModmailBotException to concrete class
bberka Apr 8, 2025
488d9e4
feat: Implement tag management UI and database infrastructure
bberka Apr 8, 2025
f924495
feat: implement CheckActiveTicket command
bberka Apr 8, 2025
9676675
feat: added new language keys for tag system
bberka Apr 8, 2025
ae2773e
feat: added new TagReceivedColor
bberka Apr 8, 2025
826b01c
feat(TagProvider): Implement Discord slash command provider for tags
bberka Apr 8, 2025
d120caa
feat(TagBotMessages): Create helper class for tag message generation
bberka Apr 8, 2025
fd738d5
feat: Implement handlers and commands for tag retrieval and execution
bberka Apr 8, 2025
ae33f06
feat: Enable 'tag' slash command for tag retrieval and execution
bberka Apr 8, 2025
8b6eedf
fix: Prevent spaces in tag names through UI conversion
bberka Apr 8, 2025
0188573
fix: Create or Update dialog confirmation message
bberka Apr 8, 2025
712587d
docs: COMMANDS.md
bberka Apr 8, 2025
3bd91ec
chore: DSharpPlus nuget nightly upgrade
bberka Apr 8, 2025
36d3edf
docs: CHANGELOG.md
bberka Apr 8, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
2 changes: 1 addition & 1 deletion .github/workflows/dotnet-dev-build.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: Build on Push
name: Build Dev on Push

on:
push:
Expand Down
33 changes: 33 additions & 0 deletions docs/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,38 @@
# **Changelogs**

## **v2.3**
### Features

- **Tag System Implementation:** Introduced a tag system, allowing users to trigger pre-defined responses from the bot using a 'tag' slash command.
- Implemented web UI and database infrastructure for managing tags (create, view, update, delete).
- Added command handlers for tag retrieval and execution.
- Implemented a `TagProvider` class to dynamically generate slash commands for available tags.
- Implemented a `TagBotMessages` helper class to centralize the creation of messages sent by the bot when using tags.

- **Enhanced User Engagement with Mirrored Reactions:** Reactions added by moderators in ticket channels are now automatically mirrored to the corresponding user's direct messages, and vice versa, creating a more interactive communication experience.

- **Implement mirrored message deletion** The bot now removes original user messages from DMs after they are removed to maintain organization and clarity of communications.

- **Feedback implementation:** The feedback submission system is improved and a data list has been added to improve visibility of user interaction.

- **Automatic Ticket Data Deletion and Optional Timeout**: Added support for automatically deleting timeout tickets.

- **Add preliminary permission policies (currently inactive)** Added the configuration for authorization to be tested and applied by admins once the implementation is finished.

- **Enhance Guild Option UI with visual separators and descriptions:** the visual clarity is improved by seperating groups of guild options through horizontal lines.

### Bug Fixes

- Fixed minor UI text issues
- Fixed incorrect metric calculation
- Fixed bot intents
- Fixed multiple feedback submissions
### Dependency Updates

- Updated DSharpPlus to the latest NuGet nightly version.



## **v2.2**


Expand Down
11 changes: 10 additions & 1 deletion docs/COMMANDS.md
Original file line number Diff line number Diff line change
Expand Up @@ -96,4 +96,13 @@ This set of commands allows moderators or higher-level users to manage the black
- **Description**: Check if a user is blacklisted.
- **Parameters**:
- `user`: The user to check.
- **Usage**: `/blacklist status [user]`
- **Usage**: `/blacklist status [user]`

## Tag Slash Commands

### `/tag`

- **Description**: Get tag content.
- **Parameters**:
- `name`: Tag name.
- **Usage**: `/tag [name]`
2 changes: 1 addition & 1 deletion src/Modmail.NET.Web.Blazor/Components/App.razor
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
@using Modmail.NET.Static
@using Modmail.NET.Common.Static
@using Modmail.NET.Web.Blazor.Components.Layout.Shared
@inject ThemeService ThemeService

Expand Down
18 changes: 14 additions & 4 deletions src/Modmail.NET.Web.Blazor/Components/Layout/AuthLayout.razor
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
@using Modmail.NET.Extensions
@using Modmail.NET.Features.Permission
@using Modmail.NET.Static
@using Modmail.NET.Common.Static
@using Modmail.NET.Features.Permission.Queries
@using Modmail.NET.Web.Blazor.Components.Layout.Shared
@using Modmail.NET.Web.Blazor.Extensions
@using Modmail.NET.Web.Blazor.Providers
@inherits LayoutComponentBase
@inject NavigationManager NavigationManager
Expand Down Expand Up @@ -36,9 +36,17 @@
<RadzenSidebar @bind-Expanded="@_sidebarExpanded">
<RadzenPanelMenu>
<RadzenPanelMenuItem Text="Dashboard" Icon="home" Path="/dashboard"/>

@* <RadzenPanelMenuItem Text="Analytics" Icon="analytics" Path="/analytics"/> *@

@if (_hasAccessTickets) {
<RadzenPanelMenuItem Text="Tickets" Icon="local_activity" Path="/tickets"/>
}
<RadzenPanelMenuItem Text="Feedbacks" Icon="reviews" Path="/feedback"/>

<RadzenPanelMenuItem Text="Tags" Icon="label" Path="/tags"/>


@if (_hasAccessBlacklist) {
<RadzenPanelMenuItem Text="Blacklist" Icon="block" Path="/blacklist"/>
}
Expand All @@ -47,13 +55,15 @@
}

@if (_hasAccessTeams) {
@* <RadzenPanelMenuItem Text="Permissions" Icon="security" Path="/permissions"/> *@

<RadzenPanelMenuItem Text="Teams" Icon="group" Path="/teams"/>
}
@if (_isOwner) {
<RadzenPanelMenuItem Text="Options" Icon="settings" Path="/options"/>
}
@if (_hasAccessHangfire) {
<RadzenPanelMenuItem Text="Hangfire Dashboard" Icon="grid_view" Path="/hangfire"/>
<RadzenPanelMenuItem Text="Hangfire" Icon="grid_view" Path="/hangfire"/>
}
</RadzenPanelMenu>
@* <div class="rz-p-4"> *@
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
@using Modmail.NET.Utils
@using Modmail.NET.Common.Utils
<RadzenFooter>
<RadzenStack Orientation="Orientation.Horizontal" JustifyContent="JustifyContent.Center"
AlignItems="AlignItems.Center" Gap="0">
Expand Down
11 changes: 6 additions & 5 deletions src/Modmail.NET.Web.Blazor/Components/Pages/Blacklist.razor
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
@page "/blacklist"
@using Microsoft.EntityFrameworkCore
@using Modmail.NET.Abstract
@using Modmail.NET.Extensions
@using Modmail.NET.Features.Blacklist
@using Modmail.NET.Static
@using Modmail.NET.Common.Exceptions
@using Modmail.NET.Common.Static
@using Modmail.NET.Database.Entities
@using Modmail.NET.Features.Blacklist.Commands
@using Modmail.NET.Web.Blazor.Components.Shared.Blacklist
@using Modmail.NET.Web.Blazor.Extensions
@using Modmail.NET.Web.Blazor.Providers
@using Serilog
@inject IDbContextFactory<ModmailDbContext> DbContextFactory
Expand Down Expand Up @@ -91,7 +92,7 @@
"User removed from blacklist");
await ReloadDataAsync();
}
catch (BotExceptionBase ex) {
catch (ModmailBotException ex) {
Log.Warning(ex,
logMessage,
blacklist.DiscordUserId);
Expand Down
19 changes: 10 additions & 9 deletions src/Modmail.NET.Web.Blazor/Components/Pages/Dashboard.razor
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
@page "/dashboard"
@using Modmail.NET.Extensions
@using Modmail.NET.Features.Guild
@using Modmail.NET.Features.Metric
@using Modmail.NET.Features.Permission
@using Modmail.NET.Queues
@using Modmail.NET.Static
@using Modmail.NET.Utils
@using Modmail.NET.Common.Static
@using Modmail.NET.Common.Utils
@using Modmail.NET.Features.Guild.Queries
@using Modmail.NET.Features.Metric.Models
@using Modmail.NET.Features.Metric.Queries
@using Modmail.NET.Features.Permission.Queries
@using Modmail.NET.Features.Ticket.Services
@using Modmail.NET.Web.Blazor.Extensions
@using Modmail.NET.Web.Blazor.Providers
@inject NavigationManager NavigationManager
@inject DialogService DialogService
@inject NotificationService NotificationService
@inject ModmailBot Bot
@inject TicketMessageQueue TicketMessageQueue
@inject TicketMessage TicketMessage
@inject IServiceScopeFactory ScopeFactory
@attribute [AuthorizeTeam]

Expand Down Expand Up @@ -235,7 +236,7 @@
<RadzenColumn Size="12" SizeMD="6" SizeLG="4">
<RadzenCard class="rz-shadow-7">
<RadzenText TextStyle="TextStyle.H3">
@(UtilReadable.ConvertNumberToReadableString(TicketMessageQueue.GetChannelCount()))
@(UtilReadable.ConvertNumberToReadableString(TicketMessage.GetChannelCount()))
</RadzenText>
<RadzenText TextStyle="TextStyle.Subtitle1" class="rz-color-primary">
Processing Message Queues
Expand Down
141 changes: 141 additions & 0 deletions src/Modmail.NET.Web.Blazor/Components/Pages/Feedback.razor
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
@page "/feedback"
@using Microsoft.EntityFrameworkCore
@using Modmail.NET.Features.Ticket.Mappers
@using Modmail.NET.Features.Ticket.Models
@inject IDbContextFactory<ModmailDbContext> DbContextFactory

@* @attribute [AuthorizeTeam(nameof(AuthPolicy.ViewFeedbacks))] *@

@code {

//TODO: Feedback page authentication
[CascadingParameter]
public Task<AuthenticationState> AuthContext { get; set; }

private IQueryable<TicketFeedbackDto> _data;

bool _isLoading;

async Task ShowLoading() {
_isLoading = true;

await Task.Yield();

_isLoading = false;
}


private async Task ReloadDataAsync(LoadDataArgs args = null) {
await ShowLoading();

var dbContext = await DbContextFactory.CreateDbContextAsync();
var query = dbContext.Tickets
.AsNoTracking()
.OrderByDescending(x => x.ClosedDateUtc)
.AsQueryable()
.ProjectToFeedbackDto();


if (args is not null) {
query = query.ApplyDataGridFilter(args);
}

_count = await query.CountAsync();

_data = args is not null
? query.ApplyPagination(args)
: query.Skip(0).Take(10).AsQueryable();

StateHasChanged();
}


protected override async Task OnInitializedAsync() {
await base.OnInitializedAsync();
await ReloadDataAsync();
}


private async Task LoadDataAsync(LoadDataArgs args) {
await ReloadDataAsync(args);
}

private int _count;


}


<div class="container-xxl rz-mx-auto">
<RadzenRow>
<RadzenColumn Size="12">
<RadzenRow>
<RadzenColumn Size="12">
<RadzenText TextStyle="TextStyle.H3" class="fw-bold">
Feedbacks
</RadzenText>
<p>
This page shows the list of feedbacks given by users after ticket is closed.
</p>
@* <hr class="my-4"/> *@
</RadzenColumn>
</RadzenRow>
<RadzenRow RowGap="4" class="rz-mt-5">
@if (_data is null) {
<Loading></Loading>
}
else {
<RadzenCard Style="width: 100% !important;" class="rz-shadow-7">
<RadzenDataGrid Responsive="true" Count="_count" LoadData="LoadDataAsync" AllowColumnPicking="true"
AllowFiltering="true" AllowColumnResize="true" AllowAlternatingRows="false"
FilterMode="FilterMode.SimpleWithMenu"
Density="Density.Default"
AllowGrouping="false" AllowSorting="true" PageSize="10" AllowPaging="true"
PagerHorizontalAlign="HorizontalAlign.Left" PagerPosition="PagerPosition.TopAndBottom"
PagerAlwaysVisible="false" GotoFirstPageOnSort="true"
Data="@_data" TItem="TicketFeedbackDto" ColumnWidth="180px"
LogicalFilterOperator="LogicalFilterOperator.Or" ShowPagingSummary="true"
IsLoading=@_isLoading Sort="@ShowLoading" Page="@ShowLoading" Group="@ShowLoading"
Filter="@ShowLoading">
<Columns>
<RadzenDataGridColumn Visible="false" Property="@nameof(TicketFeedbackDto.Id)" Filterable="false"
Title="ID" Width="120px" TextAlign="TextAlign.Center"/>
<RadzenDataGridColumn Title="User Avatar" Sortable="false" Filterable="false" Width="120px"
TextAlign="TextAlign.Center">
<Template Context="data">
<RadzenStack AlignItems="AlignItems.Center" class="rz-mx-auto rz-my-12">
<RadzenImage class="rz-m-0 rz-p-0" Style="width: 100px; height: 100px"
Path="@data.OpenerUser!.AvatarUrl" AlternateText=""/>
</RadzenStack>
</Template>
</RadzenDataGridColumn>
<RadzenDataGridColumn Property="OpenerUser.Username" Title="User" Sortable="true" Filterable="true"
Width="100px" TextAlign="TextAlign.Center">
<Template Context="data">
<RadzenStack AlignItems="AlignItems.Center" class="rz-mx-auto rz-my-12">
<RadzenText Text="@data.OpenerUser!.Username" TextAlign="TextAlign.Center"
class="fw-bold"></RadzenText>
</RadzenStack>
</Template>
</RadzenDataGridColumn>
<RadzenDataGridColumn Visible="true" Property="@nameof(TicketFeedbackDto.ClosedDateUtc)"
Filterable="true" Title="Ticket Close UTC" Width="120px"
TextAlign="TextAlign.Center"/>
<RadzenDataGridColumn Visible="true" Property="@nameof(TicketFeedbackDto.FeedbackStar)"
Filterable="true"
Title="Star" Width="80px" TextAlign="TextAlign.Center"/>
<RadzenDataGridColumn Visible="true" Property="@nameof(TicketFeedbackDto.FeedbackMessage)"
Filterable="true"
Title="Message" Width="300px" TextAlign="TextAlign.Center"/>
<RadzenDataGridColumn Visible="true" Property="@nameof(TicketFeedbackDto.Id)" Filterable="true"
Title="Ticket Id" Width="200px" TextAlign="TextAlign.Center"/>

</Columns>
</RadzenDataGrid>
</RadzenCard>
}

</RadzenRow>
</RadzenColumn>
</RadzenRow>
</div>
Loading