Skip to content

Commit a694ff9

Browse files
committed
sync fork to upstream
2 parents a49ff98 + 54ef75a commit a694ff9

15 files changed

+689
-205
lines changed
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
@page "/admin/events"
2+
3+
<PageTitle>AdminEvents</PageTitle>
4+
5+
<h1>AdminEvents</h1>
6+
7+
<p>This component demonstrates showing admin events.</p>
8+
9+
<AdminEventsComponent Id="admin-events" @rendermode="InteractiveServer"/>
Lines changed: 29 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,29 @@
1-
@page "/tests"
2-
@rendermode InteractiveServer
3-
4-
<h1>Debug Button</h1>
5-
<DebugTargetComponent Id="debug-target" OnValueChanged="SetInput" />
6-
<DebugButtonComponent Id="debug-button" Input="@currentValue" />
7-
8-
@code {
9-
private object? currentValue;
10-
11-
private async Task SetInput(int newValue)
12-
{
13-
currentValue = newValue;
14-
await Task.CompletedTask;
15-
}
16-
}
1+
@page "/tests"
2+
@rendermode InteractiveServer
3+
4+
<h1>Component Tests</h1>
5+
6+
<h2>Debug Button</h2>
7+
<DebugTargetComponent Id="debug-target" OnValueChanged="SetInput" />
8+
<DebugButtonComponent Id="debug-button" Input="@targetValue" />
9+
10+
<h2>Deployment Models</h2>
11+
<DeploymentModelListComponent Id="debug-deployment-model-list" OnUserOptionSelected="SetDeploymentModel" @rendermode="InteractiveServer" />
12+
<DebugButtonComponent Id="debug-button-deployment-model-list" Input="@selectedModel" />
13+
14+
@code {
15+
private object? targetValue;
16+
private string? selectedModel;
17+
18+
private async Task SetInput(int value)
19+
{
20+
targetValue = value;
21+
await Task.CompletedTask;
22+
}
23+
24+
private async Task SetDeploymentModel(string value)
25+
{
26+
selectedModel = value;
27+
await Task.CompletedTask;
28+
}
29+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<div class="admin-event-active-state">
2+
<div class="@GetActiveClass(IsActive)"></div>
3+
</div>
4+
5+
@code {
6+
[Parameter]
7+
public required bool IsActive { get; set; }
8+
9+
private string GetActiveClass(bool? isActive)
10+
{
11+
if (!isActive.HasValue)
12+
{
13+
return "deactivated";
14+
}
15+
16+
return isActive.Value ? "activated" : "deactivated";
17+
}
18+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
.admin-event-active-state {
2+
display: flex;
3+
flex-direction: column;
4+
justify-content: center;
5+
align-items: center;
6+
height: 100%;
7+
}
8+
9+
.activated {
10+
width: 10px;
11+
height: 10px;
12+
background-color: green;
13+
border-radius: 50%;
14+
display: inline-block;
15+
}
16+
17+
.deactivated {
18+
width: 10px;
19+
height: 10px;
20+
background-color: red;
21+
border-radius: 50%;
22+
display: inline-block;
23+
}
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
@using AzureOpenAIProxy.PlaygroundApp.Models
2+
3+
<FluentLayout Id="@Id">
4+
@if (eventDetails == null)
5+
{
6+
<p><em>Loading...</em></p>
7+
}
8+
else
9+
{
10+
<div id="admin-events-table">
11+
<FluentDataGrid Items="@eventDetails" Pagination="@pagination" >
12+
<PropertyColumn Class="fluent-datagrid-cell" Property="@(p => p.Title)" Align="@Align.Center" Sortable="true" />
13+
<PropertyColumn Class="fluent-datagrid-cell" Property="@(p => p.DateStart)" Format="yyyy-MM-dd" Align="@Align.Center" Sortable="true" />
14+
<PropertyColumn Class="fluent-datagrid-cell" Property="@(p => p.DateEnd)" Format="yyyy-MM-dd" Align="@Align.Center" Sortable="true" />
15+
<PropertyColumn Class="fluent-datagrid-cell" Property="@(p => p.TimeZone)" Align="@Align.Center" Sortable="true" />
16+
<PropertyColumn Class="fluent-datagrid-cell" Property="@(p => p.OrganizerName)" Align="@Align.Center" Sortable="true" />
17+
<PropertyColumn Class="fluent-datagrid-cell" Property="@(p => p.CoorganizerName)" Align="@Align.Center" Sortable="true" />
18+
<PropertyColumn Class="fluent-datagrid-cell" Property="@(p => p.MaxTokenCap)" Align="@Align.Center" Sortable="true" />
19+
<PropertyColumn Class="fluent-datagrid-cell" Property="@(p => p.DailyRequestCap)" Align="@Align.Center" Sortable="true" />
20+
<TemplateColumn Class="fluent-datagrid-cell" Title="Active" Align="@Align.Center">
21+
<AdminEventIsActiveComponent IsActive="@(((AdminEventDetails)@context).IsActive)" />
22+
</TemplateColumn>
23+
<TemplateColumn Class="fluent-datagrid-cell" Title="Actions" Align="@Align.Center">
24+
<FluentButton aria-label="Edit item" IconEnd="@(new Icons.Regular.Size16.Edit())" />
25+
<FluentButton aria-label="Delete item" IconEnd="@(new Icons.Regular.Size16.Delete())" />
26+
</TemplateColumn>
27+
</FluentDataGrid>
28+
</div>
29+
30+
<div class="page-button-box">
31+
@if (pagination.TotalItemCount.HasValue)
32+
{
33+
for (var pageIndex = 0; pageIndex <= pagination.LastPageIndex; pageIndex++)
34+
{
35+
var capturedIndex = pageIndex;
36+
<FluentButton class="page-button" @onclick="@(() => GoToPageAsync(capturedIndex))" Appearance="@PageButtonAppearance(capturedIndex)"
37+
aria-current="@AriaCurrentValue(capturedIndex)">
38+
@(capturedIndex + 1)
39+
</FluentButton>
40+
}
41+
}
42+
</div>
43+
}
44+
</FluentLayout>
45+
46+
@code {
47+
private IQueryable<AdminEventDetails>? eventDetails;
48+
private PaginationState pagination = new PaginationState { ItemsPerPage = 10 };
49+
50+
[Parameter]
51+
public string? Id { get; set; }
52+
53+
protected override async Task OnInitializedAsync()
54+
{
55+
// Simulate asynchronous loading to demonstrate streaming rendering
56+
await Task.Delay(100);
57+
58+
var startDate = DateOnly.FromDateTime(DateTime.Now);
59+
60+
// make dummy data
61+
eventDetails = Enumerable.Range(1, 150).Select(index => new AdminEventDetails
62+
{
63+
EventId = Guid.NewGuid(),
64+
Title = $"event title #{index}",
65+
Summary = "dummy summary",
66+
Description = "dummy description",
67+
DateStart = DateTimeOffset.Now,
68+
DateEnd = DateTimeOffset.Now.AddDays(7 + index),
69+
TimeZone = "KST",
70+
IsActive = index % 3 == 0,
71+
OrganizerName = $"Charlie_{index}",
72+
OrganizerEmail = $"user_{index}@gmail.com",
73+
CoorganizerName = $"Bravo_{index}",
74+
CoorganizerEmail = $"support_{index}@gmail.com",
75+
MaxTokenCap = (100 + index) * 100,
76+
DailyRequestCap = index * 10
77+
}).AsQueryable();
78+
79+
pagination.TotalItemCountChanged += (sender, eventArgs) => StateHasChanged();
80+
}
81+
82+
private async Task GoToPageAsync(int pageIndex)
83+
{
84+
await pagination.SetCurrentPageIndexAsync(pageIndex);
85+
}
86+
87+
private Appearance PageButtonAppearance(int pageIndex)
88+
=> pagination.CurrentPageIndex == pageIndex ? Appearance.Accent : Appearance.Neutral;
89+
90+
private string? AriaCurrentValue(int pageIndex)
91+
=> pagination.CurrentPageIndex == pageIndex ? "page" : null;
92+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
.fluent-datagrid-cell {
2+
display: flex;
3+
align-items: center;
4+
justify-content: center;
5+
height: 100%;
6+
}
7+
8+
.page-button-box {
9+
display: flex;
10+
justify-content: center;
11+
align-items: center;
12+
margin-top: 20px;
13+
}
14+
15+
.page-button {
16+
margin-left: 10px;
17+
}
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
<FluentLayout Id="@Id" Style="margin: 10px;">
2+
<div style="display: flex; align-items: center; margin-bottom: 5px;">
3+
<label id="deployment-model-label" for="deployment-model-list-options" style="margin-right: 5px;">Deployment</label>
4+
<span style="color: red;">*</span>
5+
</div>
6+
7+
<FluentSelect Items=@deploymentModelOptions Id="deployment-model-list-options" name="deployment-models"
8+
TOption="Option<string>" Height="300px"
9+
OptionText="@(e => e.Text?.ToString())"
10+
OptionValue="@(e => e.Value?.ToString())"
11+
OptionSelected="@(e => e.Selected)"
12+
@bind-SelectedOption="@selectedOption"
13+
@onclick="OnValueChanged"
14+
aria-labelledby="deployment-model-label">
15+
</FluentSelect>
16+
</FluentLayout>
17+
18+
@code {
19+
private Option<string>? selectedOption { get; set; } = new();
20+
21+
[Parameter]
22+
public string? Id { get; set; }
23+
24+
[Parameter]
25+
public EventCallback<string> OnUserOptionSelected { get; set; }
26+
27+
private async Task OnValueChanged()
28+
{
29+
string? selectedValue = selectedOption?.Value?.ToString();
30+
await OnUserOptionSelected.InvokeAsync(selectedValue);
31+
}
32+
33+
static List<Option<string>> deploymentModelOptions = new()
34+
{
35+
new Option<string> { Value = "AL", Text = "Alabama" },
36+
new Option<string> { Value = "AK", Text = "Alaska" },
37+
new Option<string> { Value = "AZ", Text = "Arizona" },
38+
new Option<string> { Value = "AR", Text = "Arkansas" },
39+
new Option<string> { Value = "CA", Text = "California" },
40+
new Option<string> { Value = "CO", Text = "Colorado" },
41+
new Option<string> { Value = "CT", Text = "Connecticut" },
42+
new Option<string> { Value = "DE", Text = "Delaware" },
43+
new Option<string> { Value = "FL", Text = "Florida" },
44+
new Option<string> { Value = "GA", Text = "Georgia" },
45+
new Option<string> { Value = "HI", Text = "Hawaii" },
46+
new Option<string> { Value = "ID", Text = "Idaho" },
47+
new Option<string> { Value = "IL", Text = "Illinois" },
48+
new Option<string> { Value = "IN", Text = "Indiana" },
49+
new Option<string> { Value = "IA", Text = "Iowa" },
50+
new Option<string> { Value = "KS", Text = "Kansas" },
51+
new Option<string> { Value = "KY", Text = "Kentucky" },
52+
new Option<string> { Value = "LA", Text = "Louisiana" },
53+
new Option<string> { Value = "ME", Text = "Maine" },
54+
new Option<string> { Value = "MD", Text = "Maryland" },
55+
new Option<string> { Value = "MA", Text = "Massachussets" },
56+
new Option<string> { Value = "MI", Text = "Michigain" },
57+
new Option<string> { Value = "MN", Text = "Minnesota" },
58+
new Option<string> { Value = "MS", Text = "Mississippi" },
59+
new Option<string> { Value = "MO", Text = "Missouri" },
60+
new Option<string> { Value = "MT", Text = "Montana" },
61+
new Option<string> { Value = "NE", Text = "Nebraska" },
62+
new Option<string> { Value = "NV", Text = "Nevada" },
63+
new Option<string> { Value = "NH", Text = "New Hampshire" },
64+
new Option<string> { Value = "NJ", Text = "New Jersey" },
65+
new Option<string> { Value = "NM", Text = "New Mexico" },
66+
new Option<string> { Value = "NY", Text = "New York" },
67+
new Option<string> { Value = "NC", Text = "North Carolina" },
68+
new Option<string> { Value = "ND", Text = "North Dakota" },
69+
new Option<string> { Value = "OH", Text = "Ohio" },
70+
new Option<string> { Value = "OK", Text = "Oklahoma" },
71+
new Option<string> { Value = "OR", Text = "Oregon" },
72+
new Option<string> { Value = "PA", Text = "Pennsylvania" }
73+
};
74+
}

src/AzureOpenAIProxy.PlaygroundApp/Components/_Imports.razor

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,4 +14,5 @@
1414

1515
@using AzureOpenAIProxy.PlaygroundApp
1616
@using AzureOpenAIProxy.PlaygroundApp.Components
17-
@using AzureOpenAIProxy.PlaygroundApp.Components.UI
17+
@using AzureOpenAIProxy.PlaygroundApp.Components.UI
18+
@using AzureOpenAIProxy.PlaygroundApp.Components.UI.Admin
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
using System.Text.Json.Serialization;
2+
3+
namespace AzureOpenAIProxy.PlaygroundApp.Models;
4+
5+
/// <summary>
6+
/// This represent the event detail data for response by admin event endpoint.
7+
/// </summary>
8+
public class AdminEventDetails : EventDetails
9+
{
10+
/// <summary>
11+
/// Gets or sets the event description.
12+
/// </summary>
13+
public string? Description { get; set; }
14+
15+
/// <summary>
16+
/// Gets or sets the event start date.
17+
/// </summary>
18+
[JsonRequired]
19+
public DateTimeOffset DateStart { get; set; }
20+
21+
/// <summary>
22+
/// Gets or sets the event end date.
23+
/// </summary>
24+
[JsonRequired]
25+
public DateTimeOffset DateEnd { get; set; }
26+
27+
/// <summary>
28+
/// Gets or sets the event start to end date timezone.
29+
/// </summary>
30+
[JsonRequired]
31+
public string TimeZone { get; set; } = string.Empty;
32+
33+
/// <summary>
34+
/// Gets or sets the event active status.
35+
/// </summary>
36+
[JsonRequired]
37+
public bool IsActive { get; set; }
38+
39+
/// <summary>
40+
/// Gets or sets the event organizer name.
41+
/// </summary>
42+
[JsonRequired]
43+
public string OrganizerName { get; set; } = string.Empty;
44+
45+
/// <summary>
46+
/// Gets or sets the event organizer email.
47+
/// </summary>
48+
[JsonRequired]
49+
public string OrganizerEmail { get; set; } = string.Empty;
50+
51+
/// <summary>
52+
/// Gets or sets the event coorganizer name.
53+
/// </summary>
54+
public string? CoorganizerName { get; set; }
55+
56+
/// <summary>
57+
/// Gets or sets the event coorganizer email.
58+
/// </summary>
59+
public string? CoorganizerEmail { get; set; }
60+
}

0 commit comments

Comments
 (0)