This commit is contained in:
Pistasj 2023-05-28 17:35:51 +02:00
parent c5d43489de
commit 13d2b1b1fb
8 changed files with 369 additions and 7 deletions

View File

@ -4,7 +4,7 @@ namespace LiveChat.Server.Hubs;
public class ChatHub : Hub public class ChatHub : Hub
{ {
public async Task SendMessage(string user, string message) public async Task SendMessage(string user, string message, string room)
{ {
using (var db = new ChattingContext()) using (var db = new ChattingContext())
{ {
@ -14,9 +14,32 @@ public class ChatHub : Hub
Message = message, Message = message,
}; };
var dbSave = db.Messages.Add(messageData); var dbSave = db.Messages.Add(messageData);
await Clients.All.SendAsync("ReceiveMessage", user, message); await Clients.AllExcept("LiveChat Room Users").SendAsync("ReceiveMessage", user, message);
db.SaveChanges(); db.SaveChanges();
} }
} }
public async Task SendMessageRoom(string user, string message, string room)
{
using (var db = new ChattingContext())
{
var messageData = new RoomChatMessage()
{
User = user,
Message = message,
RoomId = room
};
var dbSave = db.RoomChatMessages.Add(messageData);
await Clients.Group(room).SendAsync("ReceiveMessage", user, message);
db.SaveChanges();
}
}
public async Task JoinRoom(string room, string user)
{
await Groups.AddToGroupAsync(Context.ConnectionId, room);
await Groups.AddToGroupAsync(Context.ConnectionId, "Folk i rom");
await Clients.Caller.SendAsync("ConnectionIdReceive", Context.ConnectionId);
}
} }

View File

@ -0,0 +1,91 @@
// <auto-generated />
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
#nullable disable
namespace LiveChat.Migrations
{
[DbContext(typeof(ChattingContext))]
[Migration("20230526180433_sqlite.local_migration_189")]
partial class sqlitelocal_migration_189
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder.HasAnnotation("ProductVersion", "7.0.4");
modelBuilder.Entity("ChatMessage", b =>
{
b.Property<string>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("TEXT");
b.Property<string>("Message")
.HasColumnType("TEXT");
b.Property<string>("User")
.HasColumnType("TEXT");
b.HasKey("Id");
b.ToTable("Messages");
});
modelBuilder.Entity("Room", b =>
{
b.Property<string>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("TEXT");
b.Property<string>("RoomJoinCode")
.HasColumnType("TEXT");
b.HasKey("Id");
b.ToTable("Rooms");
});
modelBuilder.Entity("RoomChatMessage", b =>
{
b.Property<string>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("TEXT");
b.Property<string>("Message")
.HasColumnType("TEXT");
b.Property<string>("RoomId")
.HasColumnType("TEXT");
b.Property<string>("User")
.HasColumnType("TEXT");
b.HasKey("Id");
b.HasIndex("RoomId")
.IsUnique();
b.ToTable("RoomChatMessages");
});
modelBuilder.Entity("RoomChatMessage", b =>
{
b.HasOne("Room", "Room")
.WithOne("RoomChatMessage")
.HasForeignKey("RoomChatMessage", "RoomId");
b.Navigation("Room");
});
modelBuilder.Entity("Room", b =>
{
b.Navigation("RoomChatMessage");
});
#pragma warning restore 612, 618
}
}
}

View File

@ -0,0 +1,61 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace LiveChat.Migrations
{
/// <inheritdoc />
public partial class sqlitelocal_migration_189 : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "Rooms",
columns: table => new
{
Id = table.Column<string>(type: "TEXT", nullable: false),
RoomJoinCode = table.Column<string>(type: "TEXT", nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_Rooms", x => x.Id);
});
migrationBuilder.CreateTable(
name: "RoomChatMessages",
columns: table => new
{
Id = table.Column<string>(type: "TEXT", nullable: false),
User = table.Column<string>(type: "TEXT", nullable: true),
Message = table.Column<string>(type: "TEXT", nullable: true),
RoomId = table.Column<string>(type: "TEXT", nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_RoomChatMessages", x => x.Id);
table.ForeignKey(
name: "FK_RoomChatMessages_Rooms_RoomId",
column: x => x.RoomId,
principalTable: "Rooms",
principalColumn: "Id");
});
migrationBuilder.CreateIndex(
name: "IX_RoomChatMessages_RoomId",
table: "RoomChatMessages",
column: "RoomId",
unique: true);
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "RoomChatMessages");
migrationBuilder.DropTable(
name: "Rooms");
}
}
}

View File

@ -31,6 +31,57 @@ namespace LiveChat.Migrations
b.ToTable("Messages"); b.ToTable("Messages");
}); });
modelBuilder.Entity("Room", b =>
{
b.Property<string>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("TEXT");
b.Property<string>("RoomJoinCode")
.HasColumnType("TEXT");
b.HasKey("Id");
b.ToTable("Rooms");
});
modelBuilder.Entity("RoomChatMessage", b =>
{
b.Property<string>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("TEXT");
b.Property<string>("Message")
.HasColumnType("TEXT");
b.Property<string>("RoomId")
.HasColumnType("TEXT");
b.Property<string>("User")
.HasColumnType("TEXT");
b.HasKey("Id");
b.HasIndex("RoomId")
.IsUnique();
b.ToTable("RoomChatMessages");
});
modelBuilder.Entity("RoomChatMessage", b =>
{
b.HasOne("Room", "Room")
.WithOne("RoomChatMessage")
.HasForeignKey("RoomChatMessage", "RoomId");
b.Navigation("Room");
});
modelBuilder.Entity("Room", b =>
{
b.Navigation("RoomChatMessage");
});
#pragma warning restore 612, 618 #pragma warning restore 612, 618
} }
} }

View File

@ -9,6 +9,10 @@ public class ChattingContext : DbContext
{ {
public DbSet<ChatMessage> Messages { get; set; } public DbSet<ChatMessage> Messages { get; set; }
public DbSet<Room> Rooms { get; set; }
public DbSet<RoomChatMessage> RoomChatMessages { get; set; }
public string DbPath { get; } public string DbPath { get; }
public ChattingContext() public ChattingContext()
@ -30,9 +34,9 @@ public class Room
public string? RoomJoinCode { get; set; } public string? RoomJoinCode { get; set; }
// koble tilsammen ChatMessage til Room // koble tilsammen RoomChatMessage til Room
// https://www.entityframeworktutorial.net/efcore/one-to-many-conventions-entity-framework-core.aspx // https://www.entityframeworktutorial.net/efcore/one-to-many-conventions-entity-framework-core.aspx
public ChatMessage? ChatMessage { get; set; } public RoomChatMessage? RoomChatMessage { get; set; }
} }
@ -45,3 +49,19 @@ public class ChatMessage
public string? User { get; set; } public string? User { get; set; }
public string? Message { get; set; } public string? Message { get; set; }
} }
public class RoomChatMessage
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public string? Id { get; set; }
public string? User { get; set; }
public string? Message { get; set; }
public string? RoomId { get; set; }
// koble tilsammen RoomChatMessage til Room
// https://www.entityframeworktutorial.net/efcore/one-to-many-conventions-entity-framework-core.aspx
public Room? Room { get; set; }
}

View File

@ -1,13 +1,119 @@
@page "/chat/{room?}" @page "/chat/{room?}"
@using Microsoft.AspNetCore.SignalR.Client;
@using LiveChat.Models;
@inject NavigationManager Navigation
<PageTitle>Chat room</PageTitle> <PageTitle>Chat room</PageTitle>
@if(Room is null or "") @if(Room is null or "")
{ {
<p class="alert alert-info"><i class="bi bi-exclamation-circle-fill"></i> Ingen rom ble avgitt. Lag et rom og putt det i URLen.</p> <p class="alert alert-info"><i class="bi bi-exclamation-circle-fill"></i> Fant ikke rom i URL. Lag et rom og putt det i URLen.</p>
} }
<h1>Rom @Room</h1>
<p>Din tilkoblings ID: @connectionId. Brukernavn: @username</p>
@foreach (var msg in msgs)
{
<div class="message">@msg</div>
}
<div class="messageFormContainer">
@if (messageModel == null)
{
<p>laster inn meldingsboks</p>
}
else
{
<EditForm Model="@messageModel" OnValidSubmit="@HandleSubmit" class="MessageForm">
<DataAnnotationsValidator />
<div class="MessageFormValidation">
<ValidationSummary />
</div>
<div class="MessageFormInputs">
<input @bind-value="messageModel.Message" placeholder="Skriv inn din melding..." class="MessageFormMessage" />
<button type="submit" class="MessageFormButton"><i class="bi bi-send-fill"></i></button>
</div>
</EditForm>
}
</div>
@code { @code {
[Parameter] [Parameter]
public string? Room { get; set; } public string? Room { get; set; }
private HubConnection? hubConnection;
private List<string> msgs = new List<string>();
private bool ErViInne = false;
private string connectionId = "";
private string username = "";
private MessageModel messageModel = new MessageModel() { User = "Something", Message = "" };
protected override async Task OnInitializedAsync()
{
hubConnection = new HubConnectionBuilder()
.WithUrl(Navigation.ToAbsoluteUri("/chathub"))
.Build();
await hubConnection.StartAsync();
// lag tilfeldig navn
username = "Bruker" + new Random().Next(1, 1000);
if (Room != null || Room != "")
{
// sjekk om rom finnes
// hvis ikke, lag et rom
using (var db = new ChattingContext())
{
var room = db.Rooms.FirstOrDefault(r => r.RoomJoinCode == Room);
if (room is null)
{
Console.WriteLine("Lager rom?!?");
room = new Room() { RoomJoinCode = Room };
db.Rooms.Add(room);
db.SaveChanges();
}
}
}
// bli med i rom
await hubConnection.SendAsync("JoinRoom", Room, username);
ErViInne = true;
messageModel.User = username;
hubConnection.On<string, string>("ReceiveMessage", (user, message) =>
{
var encodedMsg = $"{user}: {message}";
msgs.Add(encodedMsg);
InvokeAsync(StateHasChanged);
});
}
private async Task HandleSubmit()
{
messageModel.User = username;
await hubConnection.SendAsync("SendMessageRoom", messageModel.User, messageModel.Message, Room);
}
public bool IsConnected =>
hubConnection?.State == HubConnectionState.Connected;
public async ValueTask DisposeAsync()
{
if (hubConnection is not null)
{
await hubConnection.DisposeAsync();
}
}
} }

View File

@ -12,11 +12,11 @@
<div hidden="@(!ModalIsVisible)"> <div hidden="@(!ModalIsVisible)">
<EditForm Model="@userModel" OnValidSubmit="@SetUser"> <EditForm Model="@userModel" OnValidSubmit="@SetUser">
<DataAnnotationsValidator /> <DataAnnotationsValidator />
<ValidationSummary />
<div class="giveNameMessage"> <div class="giveNameMessage">
<h1>Skriv inn navnet ditt</h1> <h1>Skriv inn navnet ditt</h1>
<p>Dette kan ikke endres (helt til du oppdaterer sida)</p> <p>Dette kan ikke endres (helt til du oppdaterer sida)</p>
<ValidationSummary />
<input @bind-value="userModel.User" disabled="@(!ModalIsVisible)" placeholder="Navn" class="MessageFormName" /> <input @bind-value="userModel.User" disabled="@(!ModalIsVisible)" placeholder="Navn" class="MessageFormName" />
<button type="submit" disabled="@(!IsConnected)" class="MessageFormButton"><i class="bi bi-send-fill"></i> Sett navn</button> <button type="submit" disabled="@(!IsConnected)" class="MessageFormButton"><i class="bi bi-send-fill"></i> Sett navn</button>
</div> </div>
@ -101,6 +101,7 @@ else
await InvokeAsync(StateHasChanged); await InvokeAsync(StateHasChanged);
} }
hubConnection.On<string, string>("ReceiveMessage", (user, message) => hubConnection.On<string, string>("ReceiveMessage", (user, message) =>
{ {
var encodedMsg = $"{user}: {message}"; var encodedMsg = $"{user}: {message}";

View File

@ -168,3 +168,12 @@ a, .btn-link {
border-radius: 0.25rem; border-radius: 0.25rem;
transition: 0.25s all ease-in-out; transition: 0.25s all ease-in-out;
} }
/* bli kvitt med punkt på valideringsfeil */
.validation-errors > .validation-message {
list-style-type: none;
margin: 0;
margin-left: -31px;
padding: 0;
}