1
0
mirror of synced 2024-11-23 22:10:59 +01:00

Start API and WebUI rework

This commit is contained in:
asesidaa 2023-02-17 00:38:01 +08:00
parent 6de389cf2b
commit 2ff32b9693
95 changed files with 813 additions and 82 deletions

View File

@ -0,0 +1,18 @@
namespace Application.Api;
public record GetCardsQuery() : IRequestWrapper<List<ClientCardDto>>;
public class GetCardsQueryHandler : RequestHandlerBase<GetCardsQuery, List<ClientCardDto>>
{
public GetCardsQueryHandler(ICardDependencyAggregate aggregate) : base(aggregate)
{
}
public override async Task<ServiceResult<List<ClientCardDto>>> Handle(GetCardsQuery request, CancellationToken cancellationToken)
{
var cards = await CardDbContext.CardMains.ToListAsync(cancellationToken: cancellationToken);
var dtoList = cards.Select(card => card.CardMainToClientDto()).ToList();
return new ServiceResult<List<ClientCardDto>>(dtoList);
}
}

View File

@ -0,0 +1,41 @@
namespace Application.Api;
public record GetPlayOptionQuery(long CardId) : IRequestWrapper<PlayOptionData>;
public class GetPlayOptionQueryHandler : RequestHandlerBase<GetPlayOptionQuery, PlayOptionData>
{
public GetPlayOptionQueryHandler(ICardDependencyAggregate aggregate) : base(aggregate)
{
}
public override async Task<ServiceResult<PlayOptionData>> Handle(GetPlayOptionQuery request,
CancellationToken cancellationToken)
{
var optionDetail1 = await CardDbContext.CardDetails.FirstOrDefaultAsync(detail =>
detail.CardId == request.CardId &&
detail.Pcol1 == 0 &&
detail.Pcol2 == 0 &&
detail.Pcol3 == 0,
cancellationToken: cancellationToken);
var optionDetail2 = await CardDbContext.CardDetails.FirstOrDefaultAsync(detail =>
detail.CardId == request.CardId &&
detail.Pcol1 == 1 &&
detail.Pcol2 == 0 &&
detail.Pcol3 == 0,
cancellationToken: cancellationToken);
if (optionDetail1 is null ||
optionDetail2 is null)
{
return ServiceResult.Failed<PlayOptionData>(ServiceError.CustomMessage("At least one of the play option records not found"));
}
var result = new PlayOptionData
{
CardId = request.CardId,
OptionPart1 = optionDetail1.CardDetailToFirstOption(),
OptionPart2 = optionDetail2.CardDetailToSecondOption()
};
return new ServiceResult<PlayOptionData>(result);
}
}

View File

@ -0,0 +1,79 @@
using Microsoft.Extensions.Logging;
namespace Application.Api;
public record GetTotalResultQuery(long CardId) : IRequestWrapper<TotalResultData>;
public class GetTotalResultQueryHandler : RequestHandlerBase<GetTotalResultQuery, TotalResultData>
{
private const int S_SCORE = 900000;
private const int SS_SCORE = 950000;
private const int SSS_SCORE = 990000;
private readonly ILogger<GetTotalResultQueryHandler> logger;
public GetTotalResultQueryHandler(ICardDependencyAggregate aggregate, ILogger<GetTotalResultQueryHandler> logger) : base(aggregate)
{
this.logger = logger;
}
public override async Task<ServiceResult<TotalResultData>> Handle(GetTotalResultQuery request, CancellationToken cancellationToken)
{
var card = await CardDbContext.CardMains.FirstOrDefaultAsync(card => card.CardId == request.CardId, cancellationToken);
if (card is null)
{
logger.LogWarning("Trying to get total result for non existing card: {CardId}", request.CardId);
return ServiceResult.Failed<TotalResultData>(ServiceError.UserNotFound);
}
var result = new TotalResultData
{
CardId = card.CardId,
PlayerName = card.PlayerName
};
var totalSongCount = await MusicDbContext.MusicUnlocks.CountAsync(cancellationToken: cancellationToken);
var totalExtraCount = await MusicDbContext.MusicExtras.CountAsync(cancellationToken: cancellationToken);
var totalStageCount = totalSongCount * 3 + totalExtraCount;
result.PlayerData.TotalSongCount = totalSongCount;
result.StageCountData.Total = totalStageCount;
var playedStageDetails = await CardDbContext.CardDetails.Where(detail =>
detail.CardId == request.CardId &&
detail.Pcol1 == 20).ToListAsync(cancellationToken: cancellationToken);
var playedStageScores = await CardDbContext.CardDetails.Where(detail =>
detail.CardId == request.CardId &&
detail.Pcol1 == 21).ToListAsync(cancellationToken: cancellationToken);
var playedSongCount = playedStageDetails.DistinctBy(detail => detail.Pcol2).Count();
var playedStageCount = playedStageDetails.Count;
var clearedStageCount = playedStageDetails.Count(detail => detail.ScoreUi2 > 0);
var noMissStageCount = playedStageDetails.Count(detail => detail.ScoreUi3 > 0);
var fullChainStageCount = playedStageDetails.Count(detail => detail.ScoreUi4 > 0);
var perfectStageCount = playedStageDetails.Count(detail => detail.ScoreUi6 > 0);
var sStageCount = playedStageScores.Count(detail => detail.ScoreUi1 > S_SCORE);
var ssStageCount = playedStageScores.Count(detail => detail.ScoreUi1 > SS_SCORE);
var sssStageCount = playedStageScores.Count(detail => detail.ScoreUi1 > SSS_SCORE);
result.PlayerData.PlayedSongCount = playedSongCount;
result.StageCountData.Cleared = clearedStageCount;
result.StageCountData.NoMiss = noMissStageCount;
result.StageCountData.FullChain = fullChainStageCount;
result.StageCountData.Perfect = perfectStageCount;
result.StageCountData.S = sStageCount;
result.StageCountData.Ss = ssStageCount;
result.StageCountData.Sss = sssStageCount;
var totalScore = playedStageScores.Sum(detail => detail.ScoreUi1);
var averageScore = playedStageCount == 0 ? 0 : totalScore / playedStageCount;
result.PlayerData.TotalScore = totalScore;
result.PlayerData.AverageScore = (int)averageScore;
var rank = await CardDbContext.GlobalScoreRanks.FirstOrDefaultAsync(rank => rank.CardId == request.CardId,
cancellationToken: cancellationToken);
result.PlayerData.Rank = (int)(rank?.Rank ?? -1);
return new ServiceResult<TotalResultData>(result);
}
}

View File

@ -0,0 +1,39 @@
using Microsoft.Extensions.Logging;
namespace Application.Api;
public record SetFavoriteMusicCommand(MusicDetailDto Data) : IRequestWrapper<bool>;
public class SetFavoriteMusicCommandHandler : RequestHandlerBase<SetFavoriteMusicCommand, bool>
{
private readonly ILogger<SetFavoriteMusicCommandHandler> logger;
public SetFavoriteMusicCommandHandler(ICardDependencyAggregate aggregate, ILogger<SetFavoriteMusicCommandHandler> logger) : base(aggregate)
{
this.logger = logger;
}
public override async Task<ServiceResult<bool>> Handle(SetFavoriteMusicCommand request,
CancellationToken cancellationToken)
{
var musicDetail = await CardDbContext.CardDetails.FirstOrDefaultAsync(detail =>
detail.CardId == request.Data.CardId &&
detail.Pcol1 == 10 &&
detail.Pcol2 == request.Data.MusicId &&
detail.Pcol3 == 0,
cancellationToken);
if (musicDetail is null)
{
logger.LogWarning("Attempt to set favorite for non existing music, card id: {CardId}, music id: {MusicId}",
request.Data.CardId, request.Data.MusicId);
return ServiceResult.Failed<bool>(ServiceError.CustomMessage("Music record not found"));
}
musicDetail.Fcol1 = request.Data.IsFavorite ? 1 : 0;
CardDbContext.CardDetails.Update(musicDetail);
var count = await CardDbContext.SaveChangesAsync(cancellationToken);
return count == 1 ? new ServiceResult<bool>(true) : ServiceResult.Failed<bool>(ServiceError.DatabaseSaveFailed);
}
}

View File

@ -0,0 +1,48 @@
using Microsoft.Extensions.Logging;
namespace Application.Api;
public record SetPlayOptionCommand(PlayOptionData Data) : IRequestWrapper<bool>;
public class SetPlayOptionCommandHandler : RequestHandlerBase<SetPlayOptionCommand, bool>
{
private readonly ILogger<SetPlayOptionCommandHandler> logger;
public SetPlayOptionCommandHandler(ICardDependencyAggregate aggregate, ILogger<SetPlayOptionCommandHandler> logger) : base(aggregate)
{
this.logger = logger;
}
public override async Task<ServiceResult<bool>> Handle(SetPlayOptionCommand request, CancellationToken cancellationToken)
{
var optionDetail1 = await CardDbContext.CardDetails.FirstOrDefaultAsync(detail =>
detail.CardId == request.Data.CardId &&
detail.Pcol1 == 0 &&
detail.Pcol2 == 0 &&
detail.Pcol3 == 0,
cancellationToken: cancellationToken);
var optionDetail2 = await CardDbContext.CardDetails.FirstOrDefaultAsync(detail =>
detail.CardId == request.Data.CardId &&
detail.Pcol1 == 1 &&
detail.Pcol2 == 0 &&
detail.Pcol3 == 0,
cancellationToken: cancellationToken);
if (optionDetail1 is null ||
optionDetail2 is null)
{
logger.LogWarning("Attempt to set play options for card id {CardId} failed due to missing data",
request.Data.CardId);
return ServiceResult.Failed<bool>(ServiceError.CustomMessage("At least one of the play option records not found"));
}
request.Data.OptionPart1.MapFirstOptionDetail(optionDetail1);
request.Data.OptionPart2.MapSecondOptionDetail(optionDetail2);
CardDbContext.CardDetails.Update(optionDetail1);
CardDbContext.CardDetails.Update(optionDetail2);
var count = await CardDbContext.SaveChangesAsync(cancellationToken);
return count == 1 ? new ServiceResult<bool>(true) : ServiceResult.Failed<bool>(ServiceError.DatabaseSaveFailed);
}
}

View File

@ -0,0 +1,33 @@
using Application.Common.Helpers;
using Microsoft.Extensions.Logging;
namespace Application.Api;
public record SetPlayerNameCommand(ClientCardDto Card) : IRequestWrapper<bool>;
public class SetPlayerNameCommandHandler : RequestHandlerBase<SetPlayerNameCommand, bool>
{
private readonly ILogger<SetPlayerNameCommandHandler> logger;
public SetPlayerNameCommandHandler(ICardDependencyAggregate aggregate, ILogger<SetPlayerNameCommandHandler> logger) : base(aggregate)
{
this.logger = logger;
}
public override async Task<ServiceResult<bool>> Handle(SetPlayerNameCommand request, CancellationToken cancellationToken)
{
var card = await CardDbContext.CardMains.FirstOrDefaultAsync(card => card.CardId == request.Card.CardId, cancellationToken: cancellationToken);
if (card is null)
{
logger.LogWarning("Attempt to set name for a non existing card {CardId}", request.Card.CardId);
return ServiceResult.Failed<bool>(ServiceError.UserNotFound);
}
card.PlayerName = request.Card.PlayerName;
card.Modified = TimeHelper.CurrentTimeToString();
CardDbContext.CardMains.Update(card);
var count = await CardDbContext.SaveChangesAsync(cancellationToken);
return count == 1 ? new ServiceResult<bool>(true) : ServiceResult.Failed<bool>(ServiceError.DatabaseSaveFailed);
}
}

View File

@ -1,8 +1,8 @@
using Domain.Config;
namespace Application.Game.Card;
namespace Application.Common.Base;
public abstract class CardRequestHandlerBase<TIn, TOut>: IRequestHandlerWrapper<TIn, TOut>
public abstract class RequestHandlerBase<TIn, TOut>: IRequestHandlerWrapper<TIn, TOut>
where TIn : IRequestWrapper<TOut>
{
protected ICardDbContext CardDbContext { get; }
@ -10,7 +10,7 @@ public abstract class CardRequestHandlerBase<TIn, TOut>: IRequestHandlerWrapper<
protected GameConfig Config { get; }
public CardRequestHandlerBase(ICardDependencyAggregate aggregate)
public RequestHandlerBase(ICardDependencyAggregate aggregate)
{
CardDbContext = aggregate.CardDbContext;
MusicDbContext = aggregate.MusicDbContext;

View File

@ -0,0 +1,10 @@
namespace Application.Common.Models;
public class PlayOptionData
{
public long CardId { get; set; }
public FirstPlayOptionDto OptionPart1 { get; set; } = new();
public SecondPlayOptionDto OptionPart2 { get; set; } = new();
}

View File

@ -61,9 +61,11 @@ public class ServiceError
return new ServiceError(errorMessage, (int)CardReturnCode.Unknown);
}
public static ServiceError DatabaseSaveFailed => new ServiceError("Database save failed", 800);
public static ServiceError NotReissue => new ServiceError("Not reissue, registering a new card", (int)CardReturnCode.NotReissue);
public static ServiceError UserNotFound => new("User with this id does not exist", 996);
public static ServiceError UserNotFound => new("Card with this id does not exist", 996);
public static ServiceError UserFailedToCreate => new("Failed to create User.", 995);

View File

@ -0,0 +1,44 @@
namespace Application.Common.Models;
public class TotalResultData
{
public long CardId { get; set; }
public string PlayerName { get; set; } = string.Empty;
public PlayerData PlayerData { get; set; } = new();
public StageCountData StageCountData { get; set; } = new();
}
public class PlayerData
{
public long TotalScore { get; set; }
public int AverageScore { get; set; }
public int TotalSongCount { get; set; }
public int PlayedSongCount { get; set; }
public int Rank { get; set; }
}
public class StageCountData
{
public int Total { get; set; }
public int Cleared { get; set; }
public int NoMiss { get; set; }
public int FullChain { get; set; }
public int S { get; set; }
public int Ss { get; set; }
public int Sss { get; set; }
public int Perfect { get; set; }
}

View File

@ -0,0 +1,8 @@
namespace Application.Dto.Api;
public class ClientCardDto
{
public long CardId { get; set; }
public string PlayerName { get; set; } = string.Empty;
}

View File

@ -0,0 +1,16 @@
using Domain.Enums;
namespace Application.Dto.Api;
public class FirstPlayOptionDto
{
public long CardId { get; set; }
public long AvatarId { get; set; }
public int TitleId { get; set; }
public ShowFastSlowOption ShowFastSlowOption { get; set; }
public ShowFeverTranceOption ShowFeverTranceOption { get; set; }
}

View File

@ -0,0 +1,10 @@
namespace Application.Dto.Api;
public class MusicDetailDto
{
public long CardId { get; set; }
public int MusicId { get; set; }
public bool IsFavorite { get; set; }
}

View File

@ -0,0 +1,8 @@
namespace Application.Dto.Api;
public class SecondPlayOptionDto
{
public long CardId { get; set; }
public long NavigatorId { get; set; }
}

View File

@ -1,6 +1,6 @@
using System.ComponentModel;
namespace Application.Dto;
namespace Application.Dto.Game;
public class AvatarDto
{

View File

@ -1,4 +1,4 @@
namespace Application.Dto;
namespace Application.Dto.Game;
public class CardBDatumDto
{

View File

@ -1,6 +1,6 @@
using System.ComponentModel;
namespace Application.Dto;
namespace Application.Dto.Game;
public class CardDetailDto
{

View File

@ -1,6 +1,6 @@
using System.ComponentModel;
namespace Application.Dto;
namespace Application.Dto.Game;
public class CardDto
{

View File

@ -1,4 +1,4 @@
namespace Application.Dto;
namespace Application.Dto.Game;
public class CoinDto
{

View File

@ -1,4 +1,4 @@
namespace Application.Dto;
namespace Application.Dto.Game;
public class ItemDto
{

View File

@ -1,4 +1,4 @@
namespace Application.Dto;
namespace Application.Dto.Game;
public class MusicAouDto
{

View File

@ -1,4 +1,4 @@
namespace Application.Dto;
namespace Application.Dto.Game;
public class MusicDto
{

View File

@ -1,4 +1,4 @@
namespace Application.Dto;
namespace Application.Dto.Game;
public class MusicExtraDto
{

View File

@ -1,4 +1,4 @@
namespace Application.Dto;
namespace Application.Dto.Game;
public class NavigatorDto
{

View File

@ -1,4 +1,4 @@
namespace Application.Dto;
namespace Application.Dto.Game;
public class PlayNumRankDto
{

View File

@ -1,4 +1,4 @@
namespace Application.Dto;
namespace Application.Dto.Game;
public class ScoreRankDto
{

View File

@ -1,4 +1,4 @@
namespace Application.Dto;
namespace Application.Dto.Game;
public class SessionDto
{

View File

@ -1,4 +1,4 @@
namespace Application.Dto;
namespace Application.Dto.Game;
public class SkinDto
{

View File

@ -1,4 +1,4 @@
namespace Application.Dto;
namespace Application.Dto.Game;
public class SoundEffectDto
{

View File

@ -1,4 +1,4 @@
namespace Application.Dto;
namespace Application.Dto.Game;
public class TitleDto
{

View File

@ -1,4 +1,4 @@
namespace Application.Dto;
namespace Application.Dto.Game;
public class TotalTrophyDto
{

View File

@ -1,4 +1,4 @@
namespace Application.Dto;
namespace Application.Dto.Game;
public class UnlockKeyNumDto
{

View File

@ -2,9 +2,9 @@
public record CardRegisterCommand(long CardId, string Data) : IRequestWrapper<string>;
public class CardRegisterCommandHandler : CardRequestHandlerBase<CardRegisterCommand, string>
public class RegisterCommandHandler : RequestHandlerBase<CardRegisterCommand, string>
{
public CardRegisterCommandHandler(ICardDependencyAggregate aggregate) : base(aggregate)
public RegisterCommandHandler(ICardDependencyAggregate aggregate) : base(aggregate)
{
}

View File

@ -2,9 +2,9 @@
public record CardReissueCommand(long CardId) : IRequestWrapper<string>;
public class CardReissueCommandHandler : CardRequestHandlerBase<CardReissueCommand, string>
public class ReissueCommandHandler : RequestHandlerBase<CardReissueCommand, string>
{
public CardReissueCommandHandler(ICardDependencyAggregate aggregate) : base(aggregate)
public ReissueCommandHandler(ICardDependencyAggregate aggregate) : base(aggregate)
{
}

View File

@ -2,7 +2,7 @@
public record StartOnlineMatchingCommand(long CardId, string Data) : IRequestWrapper<string>;
public class StartOnlineMatchingCommandHandler : CardRequestHandlerBase<StartOnlineMatchingCommand, string>
public class StartOnlineMatchingCommandHandler : RequestHandlerBase<StartOnlineMatchingCommand, string>
{
public StartOnlineMatchingCommandHandler(ICardDependencyAggregate aggregate) : base(aggregate)
{

View File

@ -2,7 +2,7 @@
public record UpdateOnlineMatchingCommand(long CardId, string Data) : IRequestWrapper<string>;
public class UpdateOnlineMatchingCommandHandler : CardRequestHandlerBase<UpdateOnlineMatchingCommand, string>
public class UpdateOnlineMatchingCommandHandler : RequestHandlerBase<UpdateOnlineMatchingCommand, string>
{
public UpdateOnlineMatchingCommandHandler(ICardDependencyAggregate aggregate) : base(aggregate)
{

View File

@ -2,7 +2,7 @@
public record UploadOnlineMatchingResultCommand(long CardId, string Data) : IRequestWrapper<string>;
public class UploadOnlineMatchingResultCommandHandler : CardRequestHandlerBase<UploadOnlineMatchingResultCommand, string>
public class UploadOnlineMatchingResultCommandHandler : RequestHandlerBase<UploadOnlineMatchingResultCommand, string>
{
public UploadOnlineMatchingResultCommandHandler(ICardDependencyAggregate aggregate) : base(aggregate)
{

View File

@ -7,14 +7,14 @@ namespace Application.Game.Card.Read;
public record ReadAllCardDetailsQuery(long CardId) : IRequestWrapper<string>;
public class ReadAllCardDetailsQueryHandler : CardRequestHandlerBase<ReadAllCardDetailsQuery, string>
public class ReadAllDetailsQueryHandler : RequestHandlerBase<ReadAllCardDetailsQuery, string>
{
private const string CARD_DETAILS_XPATH = "/root/card_detail";
private const string RECORD_XPATH = $"{CARD_DETAILS_XPATH}/record";
private readonly ILogger<ReadAllCardDetailsQueryHandler> logger;
private readonly ILogger<ReadAllDetailsQueryHandler> logger;
public ReadAllCardDetailsQueryHandler(ICardDependencyAggregate aggregate, ILogger<ReadAllCardDetailsQueryHandler> logger) : base(aggregate)
public ReadAllDetailsQueryHandler(ICardDependencyAggregate aggregate, ILogger<ReadAllDetailsQueryHandler> logger) : base(aggregate)
{
this.logger = logger;
}

View File

@ -3,7 +3,7 @@ namespace Application.Game.Card.Read;
public record ReadAvatarQuery(long CardId) : IRequestWrapper<string>;
public class ReadAvatarQueryHandler : CardRequestHandlerBase<ReadAvatarQuery, string>
public class ReadAvatarQueryHandler : RequestHandlerBase<ReadAvatarQuery, string>
{
private const string AVATAR_XPATH = "/root/avatar/record";

View File

@ -6,13 +6,13 @@ namespace Application.Game.Card.Read;
public record ReadCardBDataQuery(long CardId) : IRequestWrapper<string>;
public class ReadCardBDataQueryHandler : CardRequestHandlerBase<ReadCardBDataQuery, string>
public class ReadBDataQueryHandler : RequestHandlerBase<ReadCardBDataQuery, string>
{
private const string CARD_BDATA_XPATH = "/root/card_bdata";
private readonly ILogger<ReadCardBDataQueryHandler> logger;
private readonly ILogger<ReadBDataQueryHandler> logger;
public ReadCardBDataQueryHandler(ICardDependencyAggregate aggregate, ILogger<ReadCardBDataQueryHandler> logger) : base(aggregate)
public ReadBDataQueryHandler(ICardDependencyAggregate aggregate, ILogger<ReadBDataQueryHandler> logger) : base(aggregate)
{
this.logger = logger;
}

View File

@ -6,13 +6,13 @@ namespace Application.Game.Card.Read;
public record ReadCardDetailQuery(long CardId, string Data) : IRequestWrapper<string>;
public class ReadCardDetailQueryHandler : CardRequestHandlerBase<ReadCardDetailQuery, string>
public class ReadDetailQueryHandler : RequestHandlerBase<ReadCardDetailQuery, string>
{
private const string CARD_DETAILS_XPATH = "/root/card_detail";
private readonly ILogger<ReadCardDetailQueryHandler> logger;
private readonly ILogger<ReadDetailQueryHandler> logger;
public ReadCardDetailQueryHandler(ICardDependencyAggregate aggregate, ILogger<ReadCardDetailQueryHandler> logger) : base(aggregate)
public ReadDetailQueryHandler(ICardDependencyAggregate aggregate, ILogger<ReadDetailQueryHandler> logger) : base(aggregate)
{
this.logger = logger;
}

View File

@ -5,11 +5,11 @@ namespace Application.Game.Card.Read;
public record ReadCardQuery(long CardId) : IRequestWrapper<string>;
public class ReadCardQueryHandler : CardRequestHandlerBase<ReadCardQuery, string>
public class ReadQueryHandler : RequestHandlerBase<ReadCardQuery, string>
{
private readonly ILogger<ReadCardQueryHandler> logger;
private readonly ILogger<ReadQueryHandler> logger;
public ReadCardQueryHandler(ICardDependencyAggregate aggregate, ILogger<ReadCardQueryHandler> logger) : base(aggregate) {
public ReadQueryHandler(ICardDependencyAggregate aggregate, ILogger<ReadQueryHandler> logger) : base(aggregate) {
this.logger = logger;
}

View File

@ -3,7 +3,7 @@ namespace Application.Game.Card.Read;
public record ReadCoinQuery(long CardId) : IRequestWrapper<string>;
public class ReadCoinQueryHandler : CardRequestHandlerBase<ReadCoinQuery, string>
public class ReadCoinQueryHandler : RequestHandlerBase<ReadCoinQuery, string>
{
private const string COIN_XPATH = "/root/coin";

View File

@ -3,7 +3,7 @@ namespace Application.Game.Card.Read;
public record ReadCondQuery(long CardId) : IRequestWrapper<string>;
public class ReadCondQueryHandler : CardRequestHandlerBase<ReadCondQuery, string>
public class ReadCondQueryHandler : RequestHandlerBase<ReadCondQuery, string>
{
private const string COND_XPATH = "/root/cond";

View File

@ -3,7 +3,7 @@ namespace Application.Game.Card.Read;
public record ReadEventRewardQuery(long CardId) : IRequestWrapper<string>;
public class ReadEventRewardQueryHandler : CardRequestHandlerBase<ReadEventRewardQuery, string>
public class ReadEventRewardQueryHandler : RequestHandlerBase<ReadEventRewardQuery, string>
{
private const string EVENT_REWARD_XPATH = "/root/event_reward";

View File

@ -3,7 +3,7 @@ namespace Application.Game.Card.Read;
public record ReadGetMessageQuery(long CardId) : IRequestWrapper<string>;
public class ReadGetMessageQueryHandler : CardRequestHandlerBase<ReadGetMessageQuery, string>
public class ReadGetMessageQueryHandler : RequestHandlerBase<ReadGetMessageQuery, string>
{
private const string GET_MESSAGE_XPATH = "/root/get_message";

View File

@ -2,7 +2,7 @@ namespace Application.Game.Card.Read;
public record ReadItemQuery(long CardId) : IRequestWrapper<string>;
public class ReadItemQueryHandler : CardRequestHandlerBase<ReadItemQuery, string>
public class ReadItemQueryHandler : RequestHandlerBase<ReadItemQuery, string>
{
private const string ITEM_XPATH = "/root/item/record";

View File

@ -5,7 +5,7 @@ namespace Application.Game.Card.Read;
public record ReadMusicAouQuery(long CardId) : IRequestWrapper<string>;
public class ReadMusicAouQueryHandler : CardRequestHandlerBase<ReadMusicAouQuery, string>
public class ReadMusicAouQueryHandler : RequestHandlerBase<ReadMusicAouQuery, string>
{
private const string MUSIC_AOU_XPATH = "/root/music_aou";

View File

@ -3,7 +3,7 @@ namespace Application.Game.Card.Read;
public record ReadMusicExtraQuery(long CardId) : IRequestWrapper<string>;
public class ReadMusicExtraQueryHandler : CardRequestHandlerBase<ReadMusicExtraQuery, string>
public class ReadMusicExtraQueryHandler : RequestHandlerBase<ReadMusicExtraQuery, string>
{
private const string MUSIC_EXTRA_XPATH = "/root/music_extra";

View File

@ -5,7 +5,7 @@ namespace Application.Game.Card.Read;
public record ReadMusicQuery(long CardId) : IRequestWrapper<string>;
public class ReadMusicQueryHandler : CardRequestHandlerBase<ReadMusicQuery, string>
public class ReadMusicQueryHandler : RequestHandlerBase<ReadMusicQuery, string>
{
private const string MUSIC_XPATH = "/root/music/record";
public ReadMusicQueryHandler(ICardDependencyAggregate aggregate) : base(aggregate)

View File

@ -3,7 +3,7 @@ namespace Application.Game.Card.Read;
public record ReadNavigatorQuery(long CardId) : IRequestWrapper<string>;
public class ReadNavigatorQueryHandler : CardRequestHandlerBase<ReadNavigatorQuery, string>
public class ReadNavigatorQueryHandler : RequestHandlerBase<ReadNavigatorQuery, string>
{
private const string NAVIGATOR_XPATH = "/root/navigator/record";

View File

@ -3,7 +3,7 @@ namespace Application.Game.Card.Read;
public record ReadSkinQuery(long CardId) : IRequestWrapper<string>;
public class ReadSkinQueryHandler : CardRequestHandlerBase<ReadSkinQuery, string>
public class ReadSkinQueryHandler : RequestHandlerBase<ReadSkinQuery, string>
{
private const string SKIN_XPATH = "/root/skin/record";

View File

@ -3,7 +3,7 @@ namespace Application.Game.Card.Read;
public record ReadSoundEffectQuery(long CardId) : IRequestWrapper<string>;
public class ReadSoundEffectQueryHandler : CardRequestHandlerBase<ReadSoundEffectQuery, string>
public class ReadSoundEffectQueryHandler : RequestHandlerBase<ReadSoundEffectQuery, string>
{
private const string SOUND_EFFECT_XPATH = "/root/sound_effect/record";
public ReadSoundEffectQueryHandler(ICardDependencyAggregate aggregate) : base(aggregate)

View File

@ -3,7 +3,7 @@ namespace Application.Game.Card.Read;
public record ReadTitleQuery(long CardId) : IRequestWrapper<string>;
public class ReadTitleQueryHandler : CardRequestHandlerBase<ReadTitleQuery, string>
public class ReadTitleQueryHandler : RequestHandlerBase<ReadTitleQuery, string>
{
private const string TITLE_XPATH = "/root/title/record";

View File

@ -3,7 +3,7 @@ namespace Application.Game.Card.Read;
public record ReadTotalTrophyQuery(long CardId) : IRequestWrapper<string>;
public class ReadTotalTrophyQueryHandler : CardRequestHandlerBase<ReadTotalTrophyQuery, string>
public class ReadTotalTrophyQueryHandler : RequestHandlerBase<ReadTotalTrophyQuery, string>
{
private const string TOTAL_TROPHY_XPATH = "/root/total_trophy";

View File

@ -3,7 +3,7 @@ namespace Application.Game.Card.Read;
public record ReadUnlockKeynumQuery(long CardId) : IRequestWrapper<string>;
public class ReadUnlockKeynumQueryHandler : CardRequestHandlerBase<ReadUnlockKeynumQuery, string>
public class ReadUnlockKeynumQueryHandler : RequestHandlerBase<ReadUnlockKeynumQuery, string>
{
private const string UNLOCK_KEYNUM_XPATH = "/root/unlock_keynum/record";
public ReadUnlockKeynumQueryHandler(ICardDependencyAggregate aggregate) : base(aggregate)

View File

@ -3,7 +3,7 @@ namespace Application.Game.Card.Read;
public record ReadUnlockRewardQuery(long CardId) : IRequestWrapper<string>;
public class ReadUnlockRewardQueryHandler : CardRequestHandlerBase<ReadUnlockRewardQuery, string>
public class ReadUnlockRewardQueryHandler : RequestHandlerBase<ReadUnlockRewardQuery, string>
{
private const string UNLOCK_REWARD_XPATH = "/root/unlock_reward/record";

View File

@ -2,7 +2,7 @@
public record GetSessionCommand(long CardId, string Mac) : IRequestWrapper<string>;
public class GetSessionCommandHandler : CardRequestHandlerBase<GetSessionCommand, string>
public class GetSessionCommandHandler : RequestHandlerBase<GetSessionCommand, string>
{
private const string SESSION_XPATH = "/root/session";

View File

@ -2,7 +2,7 @@ namespace Application.Game.Card.Write;
public record WriteAvatarCommand(long CardId, string Data) : IRequestWrapper<string>;
public class WriteAvatarCommandHandler : CardRequestHandlerBase<WriteAvatarCommand, string>
public class WriteAvatarCommandHandler : RequestHandlerBase<WriteAvatarCommand, string>
{
public WriteAvatarCommandHandler(ICardDependencyAggregate aggregate) : base(aggregate) {}

View File

@ -5,11 +5,11 @@ namespace Application.Game.Card.Write;
public record WriteCardBDataCommand(long CardId, string Data) : IRequestWrapper<string>;
public class WriteCardBDataCommandHandler : CardRequestHandlerBase<WriteCardBDataCommand, string>
public class WriteBDataCommandHandler : RequestHandlerBase<WriteCardBDataCommand, string>
{
private readonly ILogger<WriteCardBDataCommandHandler> logger;
private readonly ILogger<WriteBDataCommandHandler> logger;
public WriteCardBDataCommandHandler(ICardDependencyAggregate aggregate, ILogger<WriteCardBDataCommandHandler> logger) : base(aggregate)
public WriteBDataCommandHandler(ICardDependencyAggregate aggregate, ILogger<WriteBDataCommandHandler> logger) : base(aggregate)
{
this.logger = logger;
}

View File

@ -5,11 +5,11 @@ namespace Application.Game.Card.Write;
public record WriteCardCommand(long CardId, string Data) : IRequestWrapper<string>;
public class WriteCardCommandHandler : CardRequestHandlerBase<WriteCardCommand, string>
public class WriteCommandHandler : RequestHandlerBase<WriteCardCommand, string>
{
private readonly ILogger<WriteCardCommandHandler> logger;
private readonly ILogger<WriteCommandHandler> logger;
public WriteCardCommandHandler(ICardDependencyAggregate aggregate, ILogger<WriteCardCommandHandler> logger) : base(aggregate)
public WriteCommandHandler(ICardDependencyAggregate aggregate, ILogger<WriteCommandHandler> logger) : base(aggregate)
{
this.logger = logger;
}

View File

@ -5,11 +5,11 @@ namespace Application.Game.Card.Write;
public record WriteCardDetailCommand(long CardId, string Data) : IRequestWrapper<string>;
public class WriteCardDetailCommandHandler : CardRequestHandlerBase<WriteCardDetailCommand, string>
public class WriteDetailCommandHandler : RequestHandlerBase<WriteCardDetailCommand, string>
{
private readonly ILogger<WriteCardDetailCommandHandler> logger;
private readonly ILogger<WriteDetailCommandHandler> logger;
public WriteCardDetailCommandHandler(ICardDependencyAggregate aggregate, ILogger<WriteCardDetailCommandHandler> logger) : base(aggregate)
public WriteDetailCommandHandler(ICardDependencyAggregate aggregate, ILogger<WriteDetailCommandHandler> logger) : base(aggregate)
{
this.logger = logger;
}

View File

@ -2,7 +2,7 @@ namespace Application.Game.Card.Write;
public record WriteCoinCommand(long CardId, string Data) : IRequestWrapper<string>;
public class WriteCoinCommandHandler : CardRequestHandlerBase<WriteCoinCommand, string>
public class WriteCoinCommandHandler : RequestHandlerBase<WriteCoinCommand, string>
{
public WriteCoinCommandHandler(ICardDependencyAggregate aggregate) : base(aggregate) {}

View File

@ -2,7 +2,7 @@ namespace Application.Game.Card.Write;
public record WriteItemCommand(long CardId, string Data) : IRequestWrapper<string>;
public class WriteItemCommandHandler : CardRequestHandlerBase<WriteItemCommand, string>
public class WriteItemCommandHandler : RequestHandlerBase<WriteItemCommand, string>
{
public WriteItemCommandHandler(ICardDependencyAggregate aggregate) : base(aggregate) {}

View File

@ -2,7 +2,7 @@ namespace Application.Game.Card.Write;
public record WriteMusicDetailCommand(long CardId, string Data) : IRequestWrapper<string>;
public class WriteMusicDetailCommandHandler : CardRequestHandlerBase<WriteMusicDetailCommand, string>
public class WriteMusicDetailCommandHandler : RequestHandlerBase<WriteMusicDetailCommand, string>
{
public WriteMusicDetailCommandHandler(ICardDependencyAggregate aggregate) : base(aggregate) {}

View File

@ -2,7 +2,7 @@ namespace Application.Game.Card.Write;
public record WriteNavigatorCommand(long CardId, string Data) : IRequestWrapper<string>;
public class WriteNavigatorCommandHandler : CardRequestHandlerBase<WriteNavigatorCommand, string>
public class WriteNavigatorCommandHandler : RequestHandlerBase<WriteNavigatorCommand, string>
{
public WriteNavigatorCommandHandler(ICardDependencyAggregate aggregate) : base(aggregate) {}

View File

@ -2,7 +2,7 @@ namespace Application.Game.Card.Write;
public record WriteSkinCommand(long CardId, string Data) : IRequestWrapper<string>;
public class WriteSkinCommandHandler : CardRequestHandlerBase<WriteSkinCommand, string>
public class WriteSkinCommandHandler : RequestHandlerBase<WriteSkinCommand, string>
{
public WriteSkinCommandHandler(ICardDependencyAggregate aggregate) : base(aggregate) {}

View File

@ -2,7 +2,7 @@ namespace Application.Game.Card.Write;
public record WriteSoundEffectCommand(long CardId, string Data) : IRequestWrapper<string>;
public class WriteSoundEffectCommandHandler : CardRequestHandlerBase<WriteSoundEffectCommand, string>
public class WriteSoundEffectCommandHandler : RequestHandlerBase<WriteSoundEffectCommand, string>
{
public WriteSoundEffectCommandHandler(ICardDependencyAggregate aggregate) : base(aggregate) {}

View File

@ -2,7 +2,7 @@ namespace Application.Game.Card.Write;
public record WriteTitleCommand(long CardId, string Data) : IRequestWrapper<string>;
public class WriteTitleCommandHandler : CardRequestHandlerBase<WriteTitleCommand, string>
public class WriteTitleCommandHandler : RequestHandlerBase<WriteTitleCommand, string>
{
public WriteTitleCommandHandler(ICardDependencyAggregate aggregate) : base(aggregate) {}

View File

@ -2,7 +2,7 @@ namespace Application.Game.Card.Write;
public record WriteUnlockKeynumCommand(long CardId, string Data) : IRequestWrapper<string>;
public class WriteUnlockKeynumCommandHandler : CardRequestHandlerBase<WriteUnlockKeynumCommand, string>
public class WriteUnlockKeynumCommandHandler : RequestHandlerBase<WriteUnlockKeynumCommand, string>
{
public WriteUnlockKeynumCommandHandler(ICardDependencyAggregate aggregate) : base(aggregate) {}

View File

@ -1,9 +1,11 @@
// Global using directives
global using System.Xml.Serialization;
global using Microsoft.EntityFrameworkCore;
global using System.Xml.Serialization;
global using Application.Common.Base;
global using Application.Common.Extensions;
global using Application.Common.Models;
global using Application.Dto.Api;
global using Application.Dto.Game;
global using Application.Interfaces;
global using Application.Mappers;
global using Application.Dto;
global using Application.Mappers;

View File

@ -9,4 +9,25 @@ public static partial class CardDetailMapper
public static partial CardDetailDto CardDetailToDto(this CardDetail cardDetail);
public static partial CardDetail DtoToCardDetail(this CardDetailDto dto);
[MapperIgnoreSource(nameof(FirstPlayOptionDto.CardId))]
[MapProperty(nameof(FirstPlayOptionDto.AvatarId), nameof(CardDetail.ScoreI1))]
[MapProperty(nameof(FirstPlayOptionDto.TitleId), nameof(CardDetail.Fcol2))]
[MapProperty(nameof(FirstPlayOptionDto.ShowFastSlowOption), nameof(CardDetail.ScoreUi1))]
[MapProperty(nameof(FirstPlayOptionDto.ShowFeverTranceOption), nameof(CardDetail.ScoreUi2))]
public static partial void MapFirstOptionDetail(this FirstPlayOptionDto dto, CardDetail detail);
[MapperIgnoreSource(nameof(SecondPlayOptionDto.CardId))]
[MapProperty(nameof(SecondPlayOptionDto.NavigatorId), nameof(CardDetail.ScoreI1))]
public static partial void MapSecondOptionDetail(this SecondPlayOptionDto dto, CardDetail detail);
[MapProperty(nameof(CardDetail.ScoreI1), nameof(FirstPlayOptionDto.AvatarId))]
[MapProperty(nameof(CardDetail.Fcol2), nameof(FirstPlayOptionDto.TitleId))]
[MapProperty(nameof(CardDetail.ScoreUi1), nameof(FirstPlayOptionDto.ShowFastSlowOption))]
[MapProperty(nameof(CardDetail.ScoreUi2), nameof(FirstPlayOptionDto.ShowFeverTranceOption))]
public static partial FirstPlayOptionDto CardDetailToFirstOption(this CardDetail detail);
[MapProperty(nameof(CardDetail.ScoreI1), nameof(SecondPlayOptionDto.NavigatorId))]
public static partial SecondPlayOptionDto CardDetailToSecondOption(this CardDetail detail);
}

View File

@ -8,4 +8,6 @@ public static partial class CardMapper
{
public static partial CardDto CardMainToCardDto(this CardMain cardMain);
public static partial CardMain CardDtoToCardMain(this CardDto cardDto);
public static partial ClientCardDto CardMainToClientDto(this CardMain cardMain);
}

View File

@ -0,0 +1,8 @@
namespace Domain.Enums;
public enum ShowFastSlowOption : long
{
NearAvatar = 1,
NearJudgement = 2,
NotShow = 3
}

View File

@ -0,0 +1,7 @@
namespace Domain.Enums;
public enum ShowFeverTranceOption : long
{
Show = 1,
NotShow = 2
}

View File

@ -21,6 +21,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Domain", "Domain\Domain.csp
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Infrastructure", "Infrastructure\Infrastructure.csproj", "{2666D734-0E81-431E-A22D-216218FC9023}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WebUI", "WebUI\WebUI.csproj", "{DDF8DE35-62C5-4033-93CE-0CB811A9CAEC}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@ -63,6 +65,10 @@ Global
{2666D734-0E81-431E-A22D-216218FC9023}.Debug|Any CPU.Build.0 = Debug|Any CPU
{2666D734-0E81-431E-A22D-216218FC9023}.Release|Any CPU.ActiveCfg = Release|Any CPU
{2666D734-0E81-431E-A22D-216218FC9023}.Release|Any CPU.Build.0 = Release|Any CPU
{DDF8DE35-62C5-4033-93CE-0CB811A9CAEC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{DDF8DE35-62C5-4033-93CE-0CB811A9CAEC}.Debug|Any CPU.Build.0 = Debug|Any CPU
{DDF8DE35-62C5-4033-93CE-0CB811A9CAEC}.Release|Any CPU.ActiveCfg = Release|Any CPU
{DDF8DE35-62C5-4033-93CE-0CB811A9CAEC}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

View File

@ -1,4 +1,4 @@
{
"CardDbName": "card.db3",
"CardDbName": "card1.db3",
"MusicDbName": "music471omni.db3"
}

View File

@ -0,0 +1,24 @@
using Application.Api;
using Application.Common.Models;
using Microsoft.AspNetCore.Mvc;
namespace MainServer.Controllers.API;
[ApiController]
[Route("api/[controller]")]
public class PlayOptionController : BaseController<PlayOptionController>
{
[HttpGet("{cardId:long}")]
public async Task<ActionResult<ServiceResult<PlayOptionData>>> GetPlayOptionById(long cardId)
{
var result = await Mediator.Send(new GetPlayOptionQuery(cardId));
return result;
}
[HttpPost]
public async Task<ActionResult<ServiceResult<bool>>> SetPlayOption(PlayOptionData data)
{
var result = await Mediator.Send(new SetPlayOptionCommand(data));
return result;
}
}

View File

@ -0,0 +1,39 @@
using Application.Api;
using Application.Common.Models;
using Application.Dto.Api;
using Microsoft.AspNetCore.Mvc;
namespace MainServer.Controllers.API;
[ApiController]
[Route("api/[controller]")]
public class ProfilesController : BaseController<ProfilesController>
{
[HttpGet]
public async Task<ActionResult<ServiceResult<List<ClientCardDto>>>> GetAllCards()
{
var result = await Mediator.Send(new GetCardsQuery());
return result;
}
[HttpGet("{cardId:long}")]
public async Task<ActionResult<ServiceResult<TotalResultData>>> GetCardTotalResultById(long cardId)
{
var result = await Mediator.Send(new GetTotalResultQuery(cardId));
return result;
}
[HttpPost("Favorite")]
public async Task<ActionResult<ServiceResult<bool>>> SetFavoriteMusic(MusicDetailDto detail)
{
var result = await Mediator.Send(new SetFavoriteMusicCommand(detail));
return result;
}
[HttpPost("PlayerName")]
public async Task<ActionResult<ServiceResult<bool>>> SetPlayerName(ClientCardDto card)
{
var result = await Mediator.Send(new SetPlayerNameCommand(card));
return result;
}
}

View File

@ -72,7 +72,6 @@
</ItemGroup>
<ItemGroup>
<Folder Include="Controllers\API" />
<Folder Include="Logs" />
<Folder Include="wwwroot" />
</ItemGroup>

View File

@ -1,4 +1,4 @@
<MudNavMenu>
<MudNavLink Href="" Match="NavLinkMatch.All" Icon="@Icons.Material.Filled.Home">Home</MudNavLink>
<MudNavLink Href="users" Match="NavLinkMatch.Prefix" Icon="@Icons.Material.Filled.List">Users</MudNavLink>
<MudNavLink Href="Cards" Match="NavLinkMatch.Prefix" Icon="@Icons.Material.Filled.List">Cards</MudNavLink>
</MudNavMenu>

11
WebUI/App.razor Normal file
View File

@ -0,0 +1,11 @@
<Router AppAssembly="@typeof(App).Assembly">
<Found Context="routeData">
<RouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)"/>
</Found>
<NotFound>
<PageTitle>Not found</PageTitle>
<LayoutView Layout="@typeof(MainLayout)">
<p role="alert">Sorry, there's nothing at this address.</p>
</LayoutView>
</NotFound>
</Router>

2
WebUI/Pages/Cards.razor Normal file
View File

@ -0,0 +1,2 @@
@page "/Cards"
<h3>Cards</h3>

View File

@ -0,0 +1,34 @@
using System.Net.Http.Json;
using Application.Common.Models;
using Application.Dto.Api;
using Microsoft.AspNetCore.Components;
namespace WebUI.Pages;
public partial class Cards
{
[Inject]
public HttpClient Client { get; set; } = null!;
private List<ClientCardDto>? CardDtos { get; set; }
private string ErrorMessage { get; set; } = string.Empty;
protected override async Task OnInitializedAsync()
{
await base.OnInitializedAsync();
var result = await Client.GetFromJsonAsync<ServiceResult<List<ClientCardDto>>>("api/Profiles");
if (result is null)
{
ErrorMessage = "Parse result failed";
return;
}
if (!result.Succeeded)
{
ErrorMessage = result.Error!.Message;
return;
}
CardDtos = result.Data;
}
}

5
WebUI/Pages/Index.razor Normal file
View File

@ -0,0 +1,5 @@
@page "/"
<PageTitle>Index</PageTitle>
<MudText Typo="Typo.h3" GutterBottom="true">Welcome to GC Local Server WebUI</MudText>

13
WebUI/Program.cs Normal file
View File

@ -0,0 +1,13 @@
using Microsoft.AspNetCore.Components.Web;
using Microsoft.AspNetCore.Components.WebAssembly.Hosting;
using WebUI;
using MudBlazor.Services;
var builder = WebAssemblyHostBuilder.CreateDefault(args);
builder.RootComponents.Add<App>("#app");
builder.RootComponents.Add<HeadOutlet>("head::after");
builder.Services.AddScoped(sp => new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) });
builder.Services.AddMudServices();
await builder.Build().RunAsync();

View File

@ -0,0 +1,30 @@
{
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:65283",
"sslPort": 44398
}
},
"profiles": {
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"inspectUri": "{wsProtocol}://{url.hostname}:{url.port}/_framework/debug/ws-proxy?browser={browserInspectUri}",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"Mudblazor.Template": {
"commandName": "Project",
"dotnetRunMessages": "true",
"launchBrowser": true,
"inspectUri": "{wsProtocol}://{url.hostname}:{url.port}/_framework/debug/ws-proxy?browser={browserInspectUri}",
"applicationUrl": "https://localhost:5001;http://localhost:5000",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
}
}
}

View File

@ -0,0 +1,60 @@
@inherits LayoutComponentBase
<MudThemeProvider @ref="@MudThemeProvider" @bind-IsDarkMode="@IsDarkMode"/>
<MudDialogProvider/>
<MudSnackbarProvider/>
<MudLayout>
<MudAppBar Elevation="0" Dense="true">
<MudIconButton Icon="@Icons.Material.Filled.Menu" Color="Color.Inherit" Edge="Edge.Start"
OnClick="@(_ => DrawerToggle())"/>
<MudSpacer/>
<MudTooltip Duration="1000" Text="Powered by MudBlazor">
<MudIconButton Icon="@Icons.Custom.Brands.MudBlazor" Color="Color.Inherit"
Link="https://mudblazor.com/" Target="_blank"/>
</MudTooltip>
<MudTooltip Duration="1000" Text="Github Repository">
<MudIconButton Icon="@Icons.Custom.Brands.GitHub" Color="Color.Inherit"
Link="https://github.com/asesidaa/GC-local-server-rewrite/" Target="_blank"/>
</MudTooltip>
<MudTooltip Duration="1000" Text="@(IsDarkMode ? "Switch to Light Mode" : "Switch to DarkMode")">
<MudToggleIconButton @bind-Toggled="@IsDarkMode"
Icon="@Icons.Material.Outlined.DarkMode" Color="Color.Inherit"
ToggledIcon="@Icons.Material.Filled.LightMode"/>
</MudTooltip>
</MudAppBar>
<MudDrawer @bind-Open="drawerOpen" Elevation="1">
<MudDrawerHeader>
<MudText Typo="Typo.h6">GC Local Server WebUI</MudText>
</MudDrawerHeader>
<NavMenu/>
</MudDrawer>
<MudMainContent>
<MudContainer MaxWidth="MaxWidth.Large" Class="my-16 pt-16">
@Body
</MudContainer>
</MudMainContent>
</MudLayout>
@code {
bool drawerOpen = true;
public bool IsDarkMode { get; set; }
public MudThemeProvider MudThemeProvider { get; set; } = null!;
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
{
IsDarkMode = await MudThemeProvider.GetSystemPreference();
StateHasChanged();
}
}
void DrawerToggle()
{
drawerOpen = !drawerOpen;
}
}

View File

@ -0,0 +1,4 @@
<MudNavMenu>
<MudNavLink Href="" Match="NavLinkMatch.All" Icon="@Icons.Material.Filled.Home">Home</MudNavLink>
<MudNavLink Href="Cards" Match="NavLinkMatch.Prefix" Icon="@Icons.Material.Filled.CreditCard">Cards</MudNavLink>
</MudNavMenu>

20
WebUI/WebUI.csproj Normal file
View File

@ -0,0 +1,20 @@
<Project Sdk="Microsoft.NET.Sdk.BlazorWebAssembly">
<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="7.0.3" />
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.DevServer" Version="7.0.3" PrivateAssets="all" />
<PackageReference Include="MudBlazor" Version="6.1.9" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Application\Application.csproj" />
</ItemGroup>
</Project>

25
WebUI/WebUI.sln Normal file
View File

@ -0,0 +1,25 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.0.31717.71
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WebUI", "WebUI.csproj", "{14A8F0A8-0A25-44AD-83B4-8BFE328E3148}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{14A8F0A8-0A25-44AD-83B4-8BFE328E3148}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{14A8F0A8-0A25-44AD-83B4-8BFE328E3148}.Debug|Any CPU.Build.0 = Debug|Any CPU
{14A8F0A8-0A25-44AD-83B4-8BFE328E3148}.Release|Any CPU.ActiveCfg = Release|Any CPU
{14A8F0A8-0A25-44AD-83B4-8BFE328E3148}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {5A60C47D-9115-4F94-A725-C8F37B455972}
EndGlobalSection
EndGlobal

11
WebUI/_Imports.razor Normal file
View File

@ -0,0 +1,11 @@
@using System.Net.Http
@using System.Net.Http.Json
@using Microsoft.AspNetCore.Components.Forms
@using Microsoft.AspNetCore.Components.Routing
@using Microsoft.AspNetCore.Components.Web
@using Microsoft.AspNetCore.Components.Web.Virtualization
@using Microsoft.AspNetCore.Components.WebAssembly.Http
@using Microsoft.JSInterop
@using MudBlazor
@using WebUI
@using WebUI.Shared

BIN
WebUI/wwwroot/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

25
WebUI/wwwroot/index.html Normal file
View File

@ -0,0 +1,25 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
<title>WebUI</title>
<base href="/" />
<link href="https://fonts.googleapis.com/css?family=Roboto:300,400,500,700&display=swap" rel="stylesheet" />
<link href="_content/MudBlazor/MudBlazor.min.css" rel="stylesheet" />
</head>
<body>
<div id="app">Loading...</div>
<div id="blazor-error-ui">
An unhandled error has occurred.
<a href="" class="reload">Reload</a>
<a class="dismiss">🗙</a>
</div>
<script src="_framework/blazor.webassembly.js"></script>
<script src="_content/MudBlazor/MudBlazor.min.js"></script>
</body>
</html>

View File

@ -0,0 +1,27 @@
[
{
"date": "2018-05-06",
"temperatureC": 1,
"summary": "Freezing"
},
{
"date": "2018-05-07",
"temperatureC": 14,
"summary": "Bracing"
},
{
"date": "2018-05-08",
"temperatureC": -13,
"summary": "Freezing"
},
{
"date": "2018-05-09",
"temperatureC": -16,
"summary": "Balmy"
},
{
"date": "2018-05-10",
"temperatureC": -2,
"summary": "Chilly"
}
]