dfgsdfdfgsdfdfgsdfdfgsdf

This commit is contained in:
Alex 2023-05-20 20:28:51 +02:00
parent dc0b504114
commit c5d43489de
18 changed files with 237 additions and 159 deletions

35
.vscode/launch.json vendored Normal file
View File

@ -0,0 +1,35 @@
{
"version": "0.2.0",
"configurations": [
{
// Use IntelliSense to find out which attributes exist for C# debugging
// Use hover for the description of the existing attributes
// For further information visit https://github.com/OmniSharp/omnisharp-vscode/blob/master/debugger-launchjson.md
"name": ".NET Core Launch (web)",
"type": "coreclr",
"request": "launch",
"preLaunchTask": "build",
// If you have changed target frameworks, make sure to update the program path.
"program": "${workspaceFolder}/bin/Debug/net7.0/LiveChat.dll",
"args": [],
"cwd": "${workspaceFolder}",
"stopAtEntry": false,
// Enable launching a web browser when ASP.NET Core starts. For more information: https://aka.ms/VSCode-CS-LaunchJson-WebBrowser
"serverReadyAction": {
"action": "openExternally",
"pattern": "\\bNow listening on:\\s+(https?://\\S+)"
},
"env": {
"ASPNETCORE_ENVIRONMENT": "Development"
},
"sourceFileMap": {
"/Views": "${workspaceFolder}/Views"
}
},
{
"name": ".NET Core Attach",
"type": "coreclr",
"request": "attach"
}
]
}

41
.vscode/tasks.json vendored Normal file
View File

@ -0,0 +1,41 @@
{
"version": "2.0.0",
"tasks": [
{
"label": "build",
"command": "dotnet",
"type": "process",
"args": [
"build",
"${workspaceFolder}/LiveChat.csproj",
"/property:GenerateFullPaths=true",
"/consoleloggerparameters:NoSummary"
],
"problemMatcher": "$msCompile"
},
{
"label": "publish",
"command": "dotnet",
"type": "process",
"args": [
"publish",
"${workspaceFolder}/LiveChat.csproj",
"/property:GenerateFullPaths=true",
"/consoleloggerparameters:NoSummary"
],
"problemMatcher": "$msCompile"
},
{
"label": "watch",
"command": "dotnet",
"type": "process",
"args": [
"watch",
"run",
"--project",
"${workspaceFolder}/LiveChat.csproj"
],
"problemMatcher": "$msCompile"
}
]
}

View File

@ -6,7 +6,7 @@
<NotFound> <NotFound>
<PageTitle>Not found</PageTitle> <PageTitle>Not found</PageTitle>
<LayoutView Layout="@typeof(MainLayout)"> <LayoutView Layout="@typeof(MainLayout)">
<p role="alert">Sorry, there's nothing at this address.</p> <p class="alert alert-info" role="alert">Her er det ingenting. :(</p>
</LayoutView> </LayoutView>
</NotFound> </NotFound>
</Router> </Router>

View File

@ -1,13 +0,0 @@
namespace LiveChat.Data
{
public class WeatherForecast
{
public DateOnly Date { get; set; }
public int TemperatureC { get; set; }
public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);
public string? Summary { get; set; }
}
}

View File

@ -1,20 +0,0 @@
namespace LiveChat.Data
{
public class WeatherForecastService
{
private static readonly string[] Summaries = new[]
{
"Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
};
public Task<WeatherForecast[]> GetForecastAsync(DateOnly startDate)
{
return Task.FromResult(Enumerable.Range(1, 5).Select(index => new WeatherForecast
{
Date = startDate.AddDays(index),
TemperatureC = Random.Shared.Next(-20, 55),
Summary = Summaries[Random.Shared.Next(Summaries.Length)]
}).ToArray());
}
}
}

View File

@ -1,24 +1,9 @@
using Microsoft.AspNetCore.SignalR; using Microsoft.AspNetCore.SignalR;
using Microsoft.EntityFrameworkCore;
namespace LiveChat.Server.Hubs; namespace LiveChat.Server.Hubs;
public class ChatHub : Hub public class ChatHub : Hub
{ {
private readonly ChattingContext _context;
public override async Task OnConnectedAsync()
{
using (var db = new ChattingContext())
{
var messages = db.Messages.ToList();
messages.ForEach(Console.WriteLine);
// Send the messages to the caller
await Clients.Caller.SendAsync("ReceiveMessages", messages);
}
}
public async Task SendMessage(string user, string message) public async Task SendMessage(string user, string message)
{ {
using (var db = new ChattingContext()) using (var db = new ChattingContext())
@ -28,9 +13,7 @@ public class ChatHub : Hub
User = user, User = user,
Message = message, Message = message,
}; };
Console.WriteLine(messageData);
var dbSave = db.Messages.Add(messageData); var dbSave = db.Messages.Add(messageData);
Console.WriteLine(dbSave);
await Clients.All.SendAsync("ReceiveMessage", user, message); await Clients.All.SendAsync("ReceiveMessage", user, message);
db.SaveChanges(); db.SaveChanges();
} }

View File

@ -8,6 +8,7 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Blazored.LocalStorage" Version="4.3.0" />
<PackageReference Include="Microsoft.AspNetCore.SignalR.Client" Version="7.0.4" /> <PackageReference Include="Microsoft.AspNetCore.SignalR.Client" Version="7.0.4" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="7.0.4"> <PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="7.0.4">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
@ -16,6 +17,11 @@
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="7.0.4" /> <PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="7.0.4" />
<PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration" Version="7.0.5" /> <PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration" Version="7.0.5" />
<PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.EntityFrameworkCore" Version="7.0.5" /> <PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.EntityFrameworkCore" Version="7.0.5" />
<PackageReference Include="Profanity.Detector" Version="0.1.8" />
</ItemGroup>
<ItemGroup>
<Folder Include="Utils\" />
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@ -3,7 +3,7 @@ Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17 # Visual Studio Version 17
VisualStudioVersion = 17.5.33424.131 VisualStudioVersion = 17.5.33424.131
MinimumVisualStudioVersion = 10.0.40219.1 MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LiveChat", "LiveChat.csproj", "{FDCEF6A6-0F83-47A1-AD48-2603502392F8}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LiveChat", "LiveChat.csproj", "{FDCEF6A6-0F83-47A1-AD48-2603502392F8}"
EndProject EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution

View File

@ -22,6 +22,20 @@ public class ChattingContext : DbContext
=> options.UseSqlite($"Data Source={DbPath}"); => options.UseSqlite($"Data Source={DbPath}");
} }
public class Room
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public string? Id { get; set; }
public string? RoomJoinCode { get; set; }
// koble tilsammen ChatMessage til Room
// https://www.entityframeworktutorial.net/efcore/one-to-many-conventions-entity-framework-core.aspx
public ChatMessage? ChatMessage { get; set; }
}
public class ChatMessage public class ChatMessage
{ {
[Key] [Key]

14
Models/User.cs Normal file
View File

@ -0,0 +1,14 @@
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
namespace LiveChat.Models
{
public class UserModel
{
[Required] // påkrevd
[DataType(DataType.Text)] // datatype er tekst
[StringLength(16, ErrorMessage = "Navnet ditt er for langt! (maks 16 bokstaver)")] // sett maksimal lenge til 16 bokstaver
[DisplayName("Navnet ditt")] // navnet til User på appen
public string User { get; set; }
}
}

13
Pages/Chat.razor Normal file
View File

@ -0,0 +1,13 @@
@page "/chat/{room?}"
<PageTitle>Chat room </PageTitle>
@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>
}
@code {
[Parameter]
public string? Room { get; set; }
}

View File

@ -1,18 +0,0 @@
@page "/counter"
<PageTitle>Counter</PageTitle>
<h1>Counter</h1>
<p role="status">Current count: @currentCount</p>
<button class="btn btn-primary" @onclick="IncrementCount">Click me</button>
@code {
private int currentCount = 0;
private void IncrementCount()
{
currentCount++;
}
}

View File

@ -1,47 +0,0 @@
@page "/fetchdata"
@using LiveChat.Data
@inject WeatherForecastService ForecastService
<PageTitle>Weather forecast</PageTitle>
<h1>Weather forecast</h1>
<p>This component demonstrates fetching data from a service.</p>
@if (forecasts == null)
{
<p><em>Loading...</em></p>
}
else
{
<table class="table">
<thead>
<tr>
<th>Date</th>
<th>Temp. (C)</th>
<th>Temp. (F)</th>
<th>Summary</th>
</tr>
</thead>
<tbody>
@foreach (var forecast in forecasts)
{
<tr>
<td>@forecast.Date.ToShortDateString()</td>
<td>@forecast.TemperatureC</td>
<td>@forecast.TemperatureF</td>
<td>@forecast.Summary</td>
</tr>
}
</tbody>
</table>
}
@code {
private WeatherForecast[]? forecasts;
protected override async Task OnInitializedAsync()
{
forecasts = await ForecastService.GetForecastAsync(DateOnly.FromDateTime(DateTime.Now));
}
}

View File

@ -1,56 +1,90 @@
@page "/" @page "/"
@using LiveChat.Models; @using LiveChat.Models;
@using Microsoft.AspNetCore.SignalR.Client @using Microsoft.AspNetCore.SignalR.Client
@inject Blazored.LocalStorage.ILocalStorageService localStorage
@inject NavigationManager Navigation @inject NavigationManager Navigation
@implements IAsyncDisposable @implements IAsyncDisposable
<PageTitle>LiveChat app</PageTitle> <PageTitle>LiveChat app</PageTitle>
<p>Sortert fra topp-bunn</p> <div class="container d-flex flex-column flex-wrap gap-4">
<div hidden="@(!ModalIsVisible)">
<EditForm Model="@userModel" OnValidSubmit="@SetUser">
<DataAnnotationsValidator />
<ValidationSummary />
<div class="giveNameMessage">
<h1>Skriv inn navnet ditt</h1>
<p>Dette kan ikke endres (helt til du oppdaterer sida)</p>
<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>
</div>
</EditForm>
</div>
<div hidden="@(!ModalIsVisible)">
<div >
<h1>Skriv inn romkode</h1>
<p>Få tak i koden av eieren av rommet eller noen som er i det.</p>
</div>
</div>
<div hidden="@(!ModalIsVisible)">
<div>
<h1>Lag et rom</h1>
<p>Snakk med venner osv.</p>
<button type="submit" disabled="@(!IsConnected)" class="MessageFormButton">Lag et tilfeldig rom</button>
</div>
</div>
</div>
@if (msgs != null) @if (msgs != null)
{ {
<div class="MessagesList" id="messagesList"> <div class="MessagesList" id="messagesList" hidden="@(ModalIsVisible)">
@foreach (var message in msgs) @foreach (var message in msgs)
{ {
<div class="message">@message</div> <div class="message">@message</div>
} }
</div> </div>
} else }
else
{ {
<h1>Ingen meldinger tilgjengelig.</h1> <h1>Ingen meldinger tilgjengelig.</h1>
} }
<div class="messageFormContainer"> <div class="messageFormContainer" hidden="@(ModalIsVisible)">
@if (messageModel == null) @if (messageModel == null)
{ {
<p>laster inn meldingsboks</p> <p>laster inn meldingsboks</p>
} }
else else
{ {
<EditForm Model="@messageModel" OnValidSubmit="@HandleSubmit" class="MessageForm"> <EditForm Model="@messageModel" OnValidSubmit="@HandleSubmit" class="MessageForm">
<DataAnnotationsValidator /> <DataAnnotationsValidator />
<div class="MessageFormValidation"> <div class="MessageFormValidation">
<ValidationSummary /> <ValidationSummary />
</div> </div>
<div class="MessageFormInputs"> <div class="MessageFormInputs">
<input @bind-value="messageModel.User" placeholder="Navn" class="MessageFormName" /> <input @bind-value="messageModel.Message" placeholder="Skriv inn din melding..." class="MessageFormMessage" />
<input @bind-value="messageModel.Message" placeholder="Skriv inn din melding..." class="MessageFormMessage" /> <button type="submit" disabled="@(!IsConnected || ModalIsVisible)" class="MessageFormButton"><i class="bi bi-send-fill"></i></button>
<button type="submit" disabled="@(!IsConnected)" class="MessageFormButton">Send melding!</button> </div>
</div> </EditForm>
</EditForm> }
}
</div> </div>
@code { @code {
private HubConnection? hubConnection; private HubConnection? hubConnection;
private bool ModalIsVisible = true;
private MessageModel messageModel = new MessageModel() { User = "", Message = "" }; private MessageModel messageModel = new MessageModel() { User = "", Message = "" };
private UserModel userModel = new UserModel() { User = "" };
private List<string> msgs = new List<string>(); private List<string> msgs = new List<string>();
protected override async Task OnInitializedAsync() protected override async Task OnInitializedAsync()
{ {
Console.WriteLine(messageModel);
hubConnection = new HubConnectionBuilder() hubConnection = new HubConnectionBuilder()
.WithUrl(Navigation.ToAbsoluteUri("/chathub")) .WithUrl(Navigation.ToAbsoluteUri("/chathub"))
.Build(); .Build();
@ -63,11 +97,12 @@ else
{ {
var encodedMsg = $"{msg.User}: {msg.Message}"; var encodedMsg = $"{msg.User}: {msg.Message}";
msgs.Add(encodedMsg); msgs.Add(encodedMsg);
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}";
msgs.Add(encodedMsg); msgs.Add(encodedMsg);
InvokeAsync(StateHasChanged); InvokeAsync(StateHasChanged);
@ -76,8 +111,30 @@ else
await hubConnection.StartAsync(); await hubConnection.StartAsync();
} }
private async Task SetUser()
{
ModalIsVisible = false;
messageModel.User = userModel.User;
await localStorage.SetItemAsync("user", userModel.User);
}
private async Task HandleSubmit() private async Task HandleSubmit()
{ {
var filter = new ProfanityFilter.ProfanityFilter();
// Kjempegøy
filter.AddProfanity("faen");
filter.AddProfanity("jævla");
filter.AddProfanity("jævel");
filter.AddProfanity("homse");
filter.AddProfanity("homo");
filter.AddProfanity("neger");
filter.AddProfanity("transe");
filter.AddProfanity("dritt");
messageModel.User = filter.CensorString(messageModel.User);
messageModel.Message = filter.CensorString(messageModel.Message);
if (hubConnection is not null) if (hubConnection is not null)
{ {
await hubConnection.SendAsync("SendMessage", messageModel.User, messageModel.Message); await hubConnection.SendAsync("SendMessage", messageModel.User, messageModel.Message);

View File

@ -10,6 +10,7 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<base href="~/" /> <base href="~/" />
<link rel="stylesheet" href="css/bootstrap/bootstrap.min.css" /> <link rel="stylesheet" href="css/bootstrap/bootstrap.min.css" />
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.10.3/font/bootstrap-icons.css">
<link href="css/site.css" rel="stylesheet" /> <link href="css/site.css" rel="stylesheet" />
<link href="LiveChat.styles.css" rel="stylesheet" /> <link href="LiveChat.styles.css" rel="stylesheet" />
<link rel="icon" type="image/png" href="favicon.png"/> <link rel="icon" type="image/png" href="favicon.png"/>

View File

@ -1,15 +1,15 @@
using LiveChat.Data;
using Microsoft.AspNetCore.Components; using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Web; using Microsoft.AspNetCore.Components.Web;
using Microsoft.AspNetCore.ResponseCompression; using Microsoft.AspNetCore.ResponseCompression;
using LiveChat.Server.Hubs; using LiveChat.Server.Hubs;
using Blazored.LocalStorage;
var builder = WebApplication.CreateBuilder(args); var builder = WebApplication.CreateBuilder(args);
// Add services to the container. // Add services to the container.
builder.Services.AddRazorPages(); builder.Services.AddRazorPages();
builder.Services.AddServerSideBlazor(); builder.Services.AddServerSideBlazor();
builder.Services.AddSingleton<WeatherForecastService>(); builder.Services.AddBlazoredLocalStorage();
builder.Services.AddResponseCompression(opts => builder.Services.AddResponseCompression(opts =>
{ {
opts.MimeTypes = ResponseCompressionDefaults.MimeTypes.Concat( opts.MimeTypes = ResponseCompressionDefaults.MimeTypes.Concat(

View File

@ -2,4 +2,10 @@
LiveChat er mitt siste programmeringsprosjekt for ungdomsskolen, og er skrevet med ASP.NET Core, EF Core, SignalR Core og Blazor (Server). Jeg jobber fortsatt med den :P LiveChat er mitt siste programmeringsprosjekt for ungdomsskolen, og er skrevet med ASP.NET Core, EF Core, SignalR Core og Blazor (Server). Jeg jobber fortsatt med den :P
Den bruker SQLite for database, det er ikke det raskeste men er rask nok for en liten app som dette. Det går også an å bruke andre databasesystemer hvis du installerer støtte for det. Den bruker SQLite for database, det er ikke det raskeste men er rask nok for en liten app som dette. Det g<>r ogs<67> an <20> bruke andre databasesystemer hvis du installerer st<73>tte for det.
For å kjøre programmet, må du ha .NET SDK installert.
Installer ``dotnet-ef`` verktøyet også kjør ``dotnet ef database update`` for å lage databasen.
Så kan du kjøre ``dotnet build`` for å bygge LiveChat, du finner han i bin/Debug/LiveChat.exe

View File

@ -43,7 +43,7 @@ a, .btn-link {
} }
#blazor-error-ui { #blazor-error-ui {
background: lightyellow; background: #151515;
bottom: 0; bottom: 0;
box-shadow: 0 -1px 2px rgba(0, 0, 0, 0.2); box-shadow: 0 -1px 2px rgba(0, 0, 0, 0.2);
display: none; display: none;
@ -86,21 +86,27 @@ a, .btn-link {
} }
.MessageForm { .MessageForm {
background-color: #202020;
width: fit-content;
border-radius: 2rem;
display: flex;
flex-direction: column;
gap: 0.25rem;
text-align: center;
align-items: center;
justify-content: center;
padding: 1rem; padding: 1rem;
margin-top: 1rem; margin-top: 1rem;
} }
.giveName {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
@media screen and (max-width: 768px) {
.messageFormContainer {
bottom: 0;
}
.MessageForm {
border-radius: initial;
width: initial;
}
}
.MessageFormValidation > ul { .MessageFormValidation > ul {
display: flex; display: flex;
flex-direction: row; flex-direction: row;