-
Notifications
You must be signed in to change notification settings - Fork 18
[Admin] Component: Create event details - UI component #214 #293
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
justinyoo
merged 43 commits into
aliencube:main
from
KYJKY:feature/214-create-event-details
Oct 12, 2024
Merged
Changes from all commits
Commits
Show all changes
43 commits
Select commit
Hold shift + click to select a range
986d5fe
Feat: 어드민 UI 컴포넌트 Page 추가
KYJKY aa36c46
Test: 어드민 UI 컴포넌트 테스트 추가
KYJKY b6d13d1
Feat: 버튼 추가
KYJKY 15b36d4
Merge branch 'main' into feature/214-create-event-details
KYJKY 765a28f
Fix: 피드백 적용
KYJKY 7af315d
Update PlaygroundApp Model 최신화
KYJKY 560c359
Merge: main > Task #214
KYJKY b578fb2
Refactor: 컴포넌트 수정
KYJKY 70cbc7c
Feat: NodaTime을 사용하여 Time Zone Option 추가
KYJKY 59d5eb7
Feat: 기본값 및 이벤트 설정
KYJKY 6524e01
Refactor: 불필요한 코드 정리
KYJKY 77681cc
Refactor: Time Zone Select 높이 수정
KYJKY 197d7ee
Refactor: CSS 적용 방식 수정 - 외부 스타일 시트 적용
KYJKY ecb1b2a
Revert "Refactor: CSS 적용 방식 수정 - 외부 스타일 시트 적용"
KYJKY 0fbcc1f
Refactor: 이벤트 종료 날짜 기본값 수정 (오늘 기준 다음날로 적용)
KYJKY a52fa78
Refactor: NewEventDetailsComponent.razor
KYJKY 1c7b77e
Merge branch 'main' into feature/214-create-event-details
KYJKY ad18000
Refactor: Remove @temp~ variables
KYJKY a4b8b4e
Fix: FluentDatePicker, FluentTimePicker ValueChanged error fix
KYJKY 4597c16
Refactor: NewEventDetailsComponent.razor
KYJKY 57475f5
Test: Add NewEventDetailsComponent.razor test
KYJKY a361c2e
Merge branch 'main' into feature/214-create-event-details
KYJKY 41ce714
Test: Add input test
KYJKY 19fc5a1
Fix: delete inject
KYJKY 9181344
Feat: Get local browser timezone
KYJKY 88f32ef
Refactor: Add JS error handling
KYJKY 60e851a
Refactor: NewEventDetailsComponent.razor
KYJKY c636124
Test: Add init timezone test
KYJKY 1a3cd8c
Merge branch 'main' into feature/214-create-event-details
KYJKY 6bf9e4f
Fix: Browser Timezone > System Timezone
KYJKY 7c13476
Fix: Test error fix (Now > UtcNow)
KYJKY 77fd773
Fix: add attribute Culture to FluentDatePicker
KYJKY d5b9d02
Fix: Add culture info in OnAfterRenderAsync
KYJKY 4587101
Feat: Convert from Windows timezone to IANA timezone using TimeZoneCo…
KYJKY 225ff36
Test: Convert from Windows timezone to IANA timezone using TimeZoneCo…
KYJKY ad7ee1f
Fix: Check OS to get timezone
KYJKY 50d38bf
Test: Refactoring NewEventDetailsPageTests
KYJKY 02ff26f
Test: Refactoring NewEventDetailsPageTests
KYJKY 7e3bdfa
Merge branch 'main' into feature/214-create-event-details
KYJKY 77cf3a1
Refactor: Refactoring NewEventDetailsComponent and test
KYJKY ff6ed0e
Merge branch 'main' into feature/214-create-event-details
KYJKY 8713a32
Test: Add NewEventDetailsPageTests.cs to AppHost test
KYJKY e77caa0
Merge branch 'main' into feature/214-create-event-details
KYJKY File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
181 changes: 181 additions & 0 deletions
181
src/AzureOpenAIProxy.PlaygroundApp/Components/UI/Admin/NewEventDetailsComponent.razor
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,181 @@ | ||
@using AzureOpenAIProxy.PlaygroundApp.Clients | ||
@using AzureOpenAIProxy.PlaygroundApp.Models; | ||
|
||
@using System.Globalization | ||
|
||
@using NodaTime | ||
KYJKY marked this conversation as resolved.
Show resolved
Hide resolved
|
||
@using NodaTime.Extensions | ||
@using NodaTime.TimeZones | ||
|
||
<FluentLayout Id="@Id"> | ||
@if (adminEventDetails == null) | ||
{ | ||
<p><em>Loading...</em></p> | ||
} | ||
else | ||
{ | ||
<FluentHeader>New Event</FluentHeader> | ||
<FluentBodyContent> | ||
<section> | ||
<h2>Event Infomation</h2> | ||
|
||
<FluentStack Class="create-fluent-stack" Orientation="Orientation.Horizontal" VerticalAlignment="VerticalAlignment.Center"> | ||
<FluentLabel For="event-title" Class="create-input-label">Title</FluentLabel> | ||
<FluentTextField Id="event-title" Name="title" TextFieldType="TextFieldType.Text" Required /> | ||
</FluentStack> | ||
|
||
<FluentStack Class="create-fluent-stack" Orientation="Orientation.Horizontal" VerticalAlignment="VerticalAlignment.Center"> | ||
<FluentLabel For="event-summary" Class="create-input-label">Summary</FluentLabel> | ||
<FluentTextField id="event-summary" TextFieldType="TextFieldType.Text" Required /> | ||
</FluentStack> | ||
|
||
<FluentStack Class="create-fluent-stack" Orientation="Orientation.Horizontal" VerticalAlignment="VerticalAlignment.Center"> | ||
<FluentLabel For="event-description" Class="create-input-label">Description</FluentLabel> | ||
<FluentTextArea Id="event-description" Style="width:300px" /> | ||
</FluentStack> | ||
|
||
<FluentStack Class="create-fluent-stack" Orientation="Orientation.Horizontal" VerticalAlignment="VerticalAlignment.Center"> | ||
<FluentLabel For="event-start-date" Class="create-input-label">Event Start Date</FluentLabel> | ||
<FluentDatePicker Id="event-start-date" Value="@adminEventDetails.DateStart.DateTime" ValueChanged="@(e => adminEventDetails.DateStart = e.Value)" Culture="System.Globalization.CultureInfo.CurrentCulture" /> | ||
<FluentTimePicker Id="event-start-time" Value="@adminEventDetails.DateStart.DateTime" ValueChanged="@(e => adminEventDetails.DateStart = e.Value)" /> | ||
</FluentStack> | ||
|
||
<FluentStack Class="create-fluent-stack" Orientation="Orientation.Horizontal" VerticalAlignment="VerticalAlignment.Center"> | ||
<FluentLabel For="event-end-date" Class="create-input-label">Event End Date</FluentLabel> | ||
<FluentDatePicker Id="event-end-date" Value="@adminEventDetails.DateEnd.DateTime" ValueChanged="@(e => adminEventDetails.DateEnd = e.Value)" Culture="System.Globalization.CultureInfo.CurrentCulture" /> | ||
<FluentTimePicker Id="event-end-time" Value="@adminEventDetails.DateEnd.DateTime" ValueChanged="@(e => adminEventDetails.DateEnd = e.Value)" /> | ||
</FluentStack> | ||
|
||
<FluentStack Class="create-fluent-stack" Orientation="Orientation.Horizontal" VerticalAlignment="VerticalAlignment.Center"> | ||
<FluentLabel For="event-timezone" Class="create-input-label">Time Zone</FluentLabel> | ||
<FluentSelect Id="event-timezone" @bind-Value="@adminEventDetails.TimeZone" Height="500px" TOption="string" Required> | ||
@foreach (var timeZone in timeZoneList) | ||
{ | ||
<FluentOption Value="@timeZone.Id">@timeZone.Id</FluentOption> | ||
} | ||
</FluentSelect> | ||
</FluentStack> | ||
</section> | ||
|
||
<section> | ||
<h2>Event Organizer</h2> | ||
|
||
<FluentStack Class="create-fluent-stack" Orientation="Orientation.Horizontal" VerticalAlignment="VerticalAlignment.Center"> | ||
<FluentLabel For="event-organizer-name" Class="create-input-label">Organizer Name</FluentLabel> | ||
<FluentTextField Id="event-organizer-name" TextFieldType="TextFieldType.Text" Required /> | ||
</FluentStack> | ||
|
||
|
||
<FluentStack Class="create-fluent-stack" Orientation="Orientation.Horizontal" VerticalAlignment="VerticalAlignment.Center"> | ||
<FluentLabel For="event-organizer-email" Class="create-input-label">Organizer Email</FluentLabel> | ||
<FluentTextField Id="event-organizer-email" TextFieldType="TextFieldType.Email" Required /> | ||
</FluentStack> | ||
</section> | ||
|
||
<section> | ||
<h2>Event Coorganizers</h2> | ||
|
||
<FluentStack Class="create-fluent-stack" Orientation="Orientation.Horizontal" VerticalAlignment="VerticalAlignment.Center"> | ||
<FluentLabel For="event-coorgnizer-name" Class="create-input-label">Coorgnizer Name</FluentLabel> | ||
<FluentTextField Id="event-coorgnizer-name" TextFieldType="TextFieldType.Text" Required /> | ||
</FluentStack> | ||
|
||
<FluentStack Class="create-fluent-stack" Orientation="Orientation.Horizontal" VerticalAlignment="VerticalAlignment.Center"> | ||
<FluentLabel For="event-coorgnizer-email" Class="create-input-label">Coorgnizer Email</FluentLabel> | ||
<FluentTextField Id="event-coorgnizer-email" TextFieldType="TextFieldType.Email" Required /> | ||
</FluentStack> | ||
</section> | ||
|
||
<section> | ||
<h2>Event Configuration</h2> | ||
|
||
<FluentStack Class="create-fluent-stack" Orientation="Orientation.Horizontal" VerticalAlignment="VerticalAlignment.Center"> | ||
<FluentLabel For="event-max-token-cap" Class="create-input-label">Max Token Cap</FluentLabel> | ||
<FluentNumberField Id="event-max-token-cap" @bind-Value="adminEventDetails.MaxTokenCap" Required /> | ||
</FluentStack> | ||
|
||
<FluentStack Class="create-fluent-stack" Orientation="Orientation.Horizontal" VerticalAlignment="VerticalAlignment.Center"> | ||
<FluentLabel For="event-daily-request-cap" Class="create-input-label">Daily Request Cap</FluentLabel> | ||
<FluentNumberField Id="event-daily-request-cap" @bind-Value="adminEventDetails.DailyRequestCap" Required /> | ||
</FluentStack> | ||
</section> | ||
|
||
<section class="button-section"> | ||
<FluentButton Id="admin-event-detail-add" Appearance="Appearance.Accent" Class="button" OnClick="AddEvent">Add Event</FluentButton> | ||
<FluentButton Id="admin-event-detail-cancel" Appearance="Appearance.Outline" Class="button" OnClick="CancelEvent">Cancel</FluentButton> | ||
</section> | ||
</FluentBodyContent> | ||
} | ||
</FluentLayout> | ||
|
||
|
||
@code { | ||
private List<DateTimeZone>? timeZoneList; | ||
private AdminEventDetails? adminEventDetails; | ||
private DateTimeOffset currentTime = DateTimeOffset.UtcNow; | ||
|
||
[Parameter] | ||
public string? Id { get; set; } | ||
justinyoo marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
protected override async Task OnInitializedAsync() | ||
{ | ||
adminEventDetails = adminEventDetails == null ? new() : adminEventDetails; | ||
|
||
timeZoneList = DateTimeZoneProviders.Tzdb.GetAllZones().ToList(); | ||
|
||
CultureInfo customCulture = (CultureInfo)CultureInfo.CurrentCulture.Clone(); | ||
customCulture.DateTimeFormat.ShortDatePattern = "yyyy-MM-dd"; | ||
customCulture.DateTimeFormat.ShortTimePattern = "HH:mm"; | ||
|
||
CultureInfo.DefaultThreadCurrentCulture = customCulture; | ||
CultureInfo.DefaultThreadCurrentUICulture = customCulture; | ||
} | ||
|
||
protected override async Task OnAfterRenderAsync(bool firstRender) | ||
{ | ||
if (firstRender) | ||
{ | ||
var timezoneId = GetIanaTimezoneId(); | ||
currentTime = GetCurrentDateTimeOffset(timezoneId); | ||
|
||
justinyoo marked this conversation as resolved.
Show resolved
Hide resolved
|
||
adminEventDetails.DateStart = currentTime.AddHours(1).AddMinutes(-currentTime.Minute); | ||
adminEventDetails.DateEnd = currentTime.AddDays(1).AddHours(1).AddMinutes(-currentTime.Minute); | ||
adminEventDetails.TimeZone = timezoneId; | ||
|
||
await InvokeAsync(StateHasChanged); | ||
} | ||
} | ||
|
||
private async Task AddEvent() | ||
{ | ||
await Task.CompletedTask; | ||
} | ||
|
||
private async Task CancelEvent() | ||
{ | ||
await Task.CompletedTask; | ||
} | ||
|
||
private string GetIanaTimezoneId() | ||
{ | ||
string timezoneId = TimeZoneInfo.Local.Id; | ||
|
||
if (OperatingSystem.IsWindows()) | ||
{ | ||
if (TimeZoneInfo.TryConvertWindowsIdToIanaId(timezoneId, out var ianaTimezoneId)) | ||
{ | ||
timezoneId = ianaTimezoneId; | ||
} | ||
} | ||
|
||
return timezoneId; | ||
} | ||
|
||
private DateTimeOffset GetCurrentDateTimeOffset(string timezoneId) | ||
{ | ||
var timeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById(timezoneId); | ||
|
||
justinyoo marked this conversation as resolved.
Show resolved
Hide resolved
|
||
return TimeZoneInfo.ConvertTime(DateTimeOffset.UtcNow, timeZoneInfo); | ||
} | ||
} | ||
|
25 changes: 25 additions & 0 deletions
25
src/AzureOpenAIProxy.PlaygroundApp/Components/UI/Admin/NewEventDetailsComponent.razor.css
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
section { | ||
margin-bottom: 100px | ||
} | ||
|
||
::deep .create-input-label { | ||
width: 200px; | ||
--type-ramp-base-font-size: 22px; | ||
} | ||
|
||
::deep .create-fluent-stack { | ||
height: 100px; | ||
} | ||
|
||
.button-section { | ||
display: flex; | ||
justify-content: center; | ||
gap: 50px; | ||
} | ||
|
||
.button { | ||
width: 150px; | ||
height: 50px; | ||
font-size: 16px; | ||
margin: 0 10px; | ||
} |
118 changes: 59 additions & 59 deletions
118
src/AzureOpenAIProxy.PlaygroundApp/Models/AdminEventDetails.cs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,60 +1,60 @@ | ||
using System.Text.Json.Serialization; | ||
namespace AzureOpenAIProxy.PlaygroundApp.Models; | ||
/// <summary> | ||
/// This represent the event detail data for response by admin event endpoint. | ||
/// </summary> | ||
public class AdminEventDetails : EventDetails | ||
{ | ||
/// <summary> | ||
/// Gets or sets the event description. | ||
/// </summary> | ||
public string? Description { get; set; } | ||
/// <summary> | ||
/// Gets or sets the event start date. | ||
/// </summary> | ||
[JsonRequired] | ||
public DateTimeOffset DateStart { get; set; } | ||
/// <summary> | ||
/// Gets or sets the event end date. | ||
/// </summary> | ||
[JsonRequired] | ||
public DateTimeOffset DateEnd { get; set; } | ||
/// <summary> | ||
/// Gets or sets the event start to end date timezone. | ||
/// </summary> | ||
[JsonRequired] | ||
public string TimeZone { get; set; } = string.Empty; | ||
/// <summary> | ||
/// Gets or sets the event active status. | ||
/// </summary> | ||
[JsonRequired] | ||
public bool IsActive { get; set; } | ||
/// <summary> | ||
/// Gets or sets the event organizer name. | ||
/// </summary> | ||
[JsonRequired] | ||
public string OrganizerName { get; set; } = string.Empty; | ||
/// <summary> | ||
/// Gets or sets the event organizer email. | ||
/// </summary> | ||
[JsonRequired] | ||
public string OrganizerEmail { get; set; } = string.Empty; | ||
/// <summary> | ||
/// Gets or sets the event coorganizer name. | ||
/// </summary> | ||
public string? CoorganizerName { get; set; } | ||
/// <summary> | ||
/// Gets or sets the event coorganizer email. | ||
/// </summary> | ||
public string? CoorganizerEmail { get; set; } | ||
using System.Text.Json.Serialization; | ||
|
||
namespace AzureOpenAIProxy.PlaygroundApp.Models; | ||
|
||
/// <summary> | ||
/// This represent the event detail data for response by admin event endpoint. | ||
/// </summary> | ||
public class AdminEventDetails : EventDetails | ||
{ | ||
/// <summary> | ||
/// Gets or sets the event description. | ||
/// </summary> | ||
public string? Description { get; set; } | ||
|
||
/// <summary> | ||
/// Gets or sets the event start date. | ||
/// </summary> | ||
[JsonRequired] | ||
public DateTimeOffset DateStart { get; set; } | ||
|
||
/// <summary> | ||
/// Gets or sets the event end date. | ||
/// </summary> | ||
[JsonRequired] | ||
public DateTimeOffset DateEnd { get; set; } | ||
|
||
/// <summary> | ||
/// Gets or sets the event start to end date timezone. | ||
/// </summary> | ||
[JsonRequired] | ||
public string TimeZone { get; set; } = string.Empty; | ||
|
||
/// <summary> | ||
/// Gets or sets the event active status. | ||
/// </summary> | ||
[JsonRequired] | ||
public bool IsActive { get; set; } | ||
|
||
/// <summary> | ||
/// Gets or sets the event organizer name. | ||
/// </summary> | ||
[JsonRequired] | ||
public string OrganizerName { get; set; } = string.Empty; | ||
|
||
/// <summary> | ||
/// Gets or sets the event organizer email. | ||
/// </summary> | ||
[JsonRequired] | ||
public string OrganizerEmail { get; set; } = string.Empty; | ||
|
||
/// <summary> | ||
/// Gets or sets the event coorganizer name. | ||
/// </summary> | ||
public string? CoorganizerName { get; set; } | ||
|
||
/// <summary> | ||
/// Gets or sets the event coorganizer email. | ||
/// </summary> | ||
public string? CoorganizerEmail { get; set; } | ||
} |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.