add save button and remove asp.net SPA proxy

using the docker compose nginx proxy instead
This commit is contained in:
2023-12-20 12:53:30 +01:00
parent f619cc850a
commit bc158279d8
10 changed files with 100 additions and 103 deletions
@@ -24,12 +24,12 @@ public class CharacterDbModelToDtoService : ICharacterDbModelToDtoService
Osztaly = entity.Osztaly.Convert(), Osztaly = entity.Osztaly.Convert(),
Tulajdonsagok = new KarakterTulajdonsagokDto Tulajdonsagok = new KarakterTulajdonsagokDto
{ {
T_Ero = entity.Ero, Ero = entity.Ero,
T_Ugy = entity.Ugyesseg, Ugy = entity.Ugyesseg,
T_Egs = entity.Egeszseg, Egs = entity.Egeszseg,
T_Int = entity.Intelligencia, Int = entity.Intelligencia,
T_Bol = entity.Bolcsesseg, Bol = entity.Bolcsesseg,
T_Kar = entity.Karizma, Kar = entity.Karizma,
}, },
Kepzettsegek = entity.KarakterKepzettsegek.Where(x => !x.IsTolvajKepzettseg).Select(x => x.Kepzettseg.Convert()).ToList(), Kepzettsegek = entity.KarakterKepzettsegek.Where(x => !x.IsTolvajKepzettseg).Select(x => x.Kepzettseg.Convert()).ToList(),
Tolvajkepzettsegek = entity.KarakterKepzettsegek.Where(x => x.IsTolvajKepzettseg).Select(x => x.Kepzettseg.Convert()).ToList(), Tolvajkepzettsegek = entity.KarakterKepzettsegek.Where(x => x.IsTolvajKepzettseg).Select(x => x.Kepzettseg.Convert()).ToList(),
@@ -23,12 +23,12 @@ public class CharacterDtoToDbModelService : ICharacterDtoToDbModelService
Isten = dto.Isten, Isten = dto.Isten,
Faj = FajExtensions.Convert(dto.Faj), Faj = FajExtensions.Convert(dto.Faj),
Osztaly = OsztalyExtensions.Convert(dto.Osztaly), Osztaly = OsztalyExtensions.Convert(dto.Osztaly),
Ero = dto.Tulajdonsagok.T_Ero, Ero = dto.Tulajdonsagok.Ero,
Ugyesseg = dto.Tulajdonsagok.T_Ugy, Ugyesseg = dto.Tulajdonsagok.Ugy,
Egeszseg = dto.Tulajdonsagok.T_Egs, Egeszseg = dto.Tulajdonsagok.Egs,
Intelligencia = dto.Tulajdonsagok.T_Int, Intelligencia = dto.Tulajdonsagok.Int,
Bolcsesseg = dto.Tulajdonsagok.T_Bol, Bolcsesseg = dto.Tulajdonsagok.Bol,
Karizma = dto.Tulajdonsagok.T_Kar, Karizma = dto.Tulajdonsagok.Kar,
Szint = dto.Szint, Szint = dto.Szint,
}; };
karakter.KarakterKepzettsegek = ConvertKepzettsegek(dto, karakter); karakter.KarakterKepzettsegek = ConvertKepzettsegek(dto, karakter);
@@ -1,11 +1,19 @@
using System.Text.Json.Serialization;
namespace Kemkas.Web.ViewModels; namespace Kemkas.Web.ViewModels;
public struct KarakterTulajdonsagokDto public struct KarakterTulajdonsagokDto
{ {
public byte T_Ero { get; set; } [JsonPropertyName("t_ero")]
public byte T_Ugy { get; set; } public byte Ero { get; set; }
public byte T_Egs { get; set; } [JsonPropertyName("t_ugy")]
public byte T_Int { get; set; } public byte Ugy { get; set; }
public byte T_Bol { get; set; } [JsonPropertyName("t_egs")]
public byte T_Kar { get; set; } public byte Egs { get; set; }
[JsonPropertyName("t_int")]
public byte Int { get; set; }
[JsonPropertyName("t_bol")]
public byte Bol { get; set; }
[JsonPropertyName("t_kar")]
public byte Kar { get; set; }
} }
+5
View File
@@ -10,6 +10,11 @@ function App(props: {faro?: Faro}) {
path: "/", path: "/",
element: <CreateCharacter faro={props.faro} />, element: <CreateCharacter faro={props.faro} />,
}, },
{
path: "/:id",
element: <CreateCharacter faro={props.faro} />,
loader: args => fetch(`/Character/${args.params.id}`)
}
]); ]);
return ( return (
@@ -0,0 +1,8 @@
import {Tooltip} from "react-bootstrap";
import React from "react";
const SaveOverlayTooltip = <Tooltip id="save-tooltip">
A mentéssel egyedi URL-en elérhető lesz a karakter bárkinek, azonban módosítani már nem lehet, csak újat menteni.
</Tooltip>
export default SaveOverlayTooltip
@@ -17,23 +17,29 @@ import {
SetDefaultTolvajKepzettsegek, SetDefaultTolvajKepzettsegek,
} from "../domain-models/kepzettsegek"; } from "../domain-models/kepzettsegek";
import {CreatePDF} from "../pdf/character.pdf"; import {CreatePDF} from "../pdf/character.pdf";
import {KarakterDefaults} from "../domain-models/karakter"; import {KarakterDefaults, KarakterInputs} from "../domain-models/karakter";
import {CalculateMasodlagosErtekek} from "../domain-models/masodlagos_ertekek"; import {CalculateMasodlagosErtekek} from "../domain-models/masodlagos_ertekek";
import {KarakterInputToPdfView} from "../pdf/karakter_pdf_view"; import {KarakterInputToPdfView} from "../pdf/karakter_pdf_view";
import JellemSelector from "../components/JellemSelector"; import JellemSelector from "../components/JellemSelector";
import {CanLevelUp, LevelDown, LevelUp} from "../domain-models/level"; import {CanLevelUp, LevelDown, LevelUp} from "../domain-models/level";
import {Card} from "react-bootstrap"; import {Card, OverlayTrigger} from "react-bootstrap";
import LevelUps from "../components/LevelUps"; import LevelUps from "../components/LevelUps";
import HarcosFegyverSpecializacio from "../components/HarcosFegyverSpecializacio"; import HarcosFegyverSpecializacio from "../components/HarcosFegyverSpecializacio";
import Felszereles from '../components/Felszereles'; import Felszereles from '../components/Felszereles';
import { KarakterFelszereles } from '../domain-models/felszereles'; import { KarakterFelszereles } from '../domain-models/felszereles';
import {Faro} from "@grafana/faro-web-sdk"; import {Faro} from "@grafana/faro-web-sdk";
import {StoreNewCharacter} from "../api/character.api"; import {StoreNewCharacter} from "../api/character.api";
import {useLoaderData} from "react-router-dom";
import saveOverlayTooltip from "../components/SaveOverlayTooltip";
function CreateCharacterPage(props: {faro?: Faro}) { function CreateCharacterPage(props: {
faro?: Faro,
}) {
const {faro} = props const {faro} = props
let [karakter, changeKarakter] = useState(KarakterDefaults) const initialKarakterInputs = useLoaderData() as KarakterInputs;
let [karakter, changeKarakter] = useState(initialKarakterInputs ?? KarakterDefaults)
const tulajdonsagokFajjal = TulajdonsagokFajjal(karakter.tulajdonsagok, karakter.faj) const tulajdonsagokFajjal = TulajdonsagokFajjal(karakter.tulajdonsagok, karakter.faj)
@@ -50,7 +56,6 @@ function CreateCharacterPage(props: {faro?: Faro}) {
const canLevelUp = CanLevelUp(karakter) const canLevelUp = CanLevelUp(karakter)
return ( return (
<div> <div>
<div className='container-fluid p-5 bg-black text-white text-center'> <div className='container-fluid p-5 bg-black text-white text-center'>
@@ -167,19 +172,37 @@ function CreateCharacterPage(props: {faro?: Faro}) {
<Felszereles osztaly={karakter.osztaly} felszereles={karakter.felszereles} <Felszereles osztaly={karakter.osztaly} felszereles={karakter.felszereles}
changeFelszereles={setFelszereles} harcosSpec={karakter.harcosSpecializaciok}/> changeFelszereles={setFelszereles} harcosSpec={karakter.harcosSpecializaciok}/>
<div className='d-grid gap-2 m-5'> <div className="row">
<button className='btn btn-danger btn-lg' type='button' onClick={async () => { <div className="col-6">
await StoreNewCharacter(karakter) <div className='d-grid gap-2 m-5'>
}}>Mentés <OverlayTrigger placement='top' overlay={saveOverlayTooltip} delay={0} defaultShow={false} flip={false}>
</button> <button className='btn btn-danger btn-lg' type='button' onClick={async () => {
<button className='btn btn-danger btn-lg' type='button' onClick={async () => { faro?.api.pushEvent('public_character_stored', {
faro?.api.pushEvent('character_created', { osztaly: karakter.osztaly,
osztaly: karakter.osztaly, szint: karakter.szint.toString()
szint: karakter.szint.toString() })
}) let newId = await StoreNewCharacter(karakter)
await CreatePDF(KarakterInputToPdfView(karakter)) const win = window.open(`/${newId}`, '_blank');
}}>PDF if (win != null) {
</button> win.focus();
}
}}>Mentés
</button>
</OverlayTrigger>
</div>
</div>
<div className="col-6">
<div className='d-grid gap-2 m-5'>
<button className='btn btn-danger btn-lg' type='button' onClick={async () => {
faro?.api.pushEvent('character_created', {
osztaly: karakter.osztaly,
szint: karakter.szint.toString()
})
await CreatePDF(KarakterInputToPdfView(karakter))
}}>PDF
</button>
</div>
</div>
</div> </div>
</form> </form>
</div> </div>
-36
View File
@@ -1,36 +0,0 @@
const { createProxyMiddleware } = require('http-proxy-middleware');
const { env } = require('process');
const target = env.ASPNETCORE_HTTPS_PORT ? `https://localhost:${env.ASPNETCORE_HTTPS_PORT}` :
env.ASPNETCORE_URLS ? env.ASPNETCORE_URLS.split(';')[0] : 'http://localhost:40870';
const context = [
"/weatherforecast",
"/_configuration",
"/.well-known",
"/Identity",
"/connect",
"/ApplyDatabaseMigrations",
"/_framework"
];
const onError = (err, req, resp, target) => {
console.error(`${err.message}`);
}
module.exports = function (app) {
const appProxy = createProxyMiddleware(context, {
target: target,
// Handle errors to prevent the proxy middleware from crashing when
// the ASP NET Core webserver is unavailable
onError: onError,
secure: false,
// Uncomment this line to add support for proxying websockets
//ws: true,
headers: {
Connection: 'Keep-Alive'
}
});
app.use(appProxy);
};
-31
View File
@@ -1,31 +0,0 @@
// jest-dom adds custom jest matchers for asserting on DOM nodes.
// allows you to do things like:
// expect(element).toHaveTextContent(/react/i)
// learn more: https://github.com/testing-library/jest-dom
import '@testing-library/jest-dom';
const localStorageMock = {
getItem: jest.fn(),
setItem: jest.fn(),
removeItem: jest.fn(),
clear: jest.fn(),
length: 0,
key: jest.fn()
};
global.localStorage = localStorageMock;
// Mock the request issued by the react app to get the client configuration parameters.
window.fetch = () => {
return Promise.resolve(
{
ok: true,
json: () => Promise.resolve({
"authority": "https://localhost:7251",
"client_id": "Kemkas.Web",
"redirect_uri": "https://localhost:7251/authentication/login-callback",
"post_logout_redirect_uri": "https://localhost:7251/authentication/logout-callback",
"response_type": "id_token token",
"scope": "Kemkas.WebAPI openid profile"
})
});
};
+11
View File
@@ -2,6 +2,17 @@
Microsoft Visual Studio Solution File, Format Version 12.00 Microsoft Visual Studio Solution File, Format Version 12.00
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Kemkas.Web", "Kemkas.Web\Kemkas.Web.csproj", "{ABAEE4DC-1A07-40AE-A2B6-4D3755A6C1E8}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Kemkas.Web", "Kemkas.Web\Kemkas.Web.csproj", "{ABAEE4DC-1A07-40AE-A2B6-4D3755A6C1E8}"
EndProject EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "General", "General", "{5D06CE1E-DD86-41C0-A1BF-53162BD027AA}"
ProjectSection(SolutionItems) = preProject
README.md = README.md
TODO.md = TODO.md
.gitignore = .gitignore
.dockerignore = .dockerignore
.tool-versions = .tool-versions
.github\dependabot.yml = .github\dependabot.yml
.github\workflows\ci.yml = .github\workflows\ci.yml
EndProjectSection
EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU Debug|Any CPU = Debug|Any CPU
+9
View File
@@ -8,5 +8,14 @@ Kard és Mágia karakter alkotó segédlet (https://app.kemkas.hu)
## Coding readmes ## Coding readmes
To start development, spin up the docker-compose.yaml file and use the launchSettings.json to start the backend and frontend dev servers.
For the first time setup:
1. start the DB from the docker compose (required for the backend)
2. launch the project with the launchSettings file (will generate SSL certs)
3. spin up the proxy from docker compose (needs the SSL certs)
Later start the docker compose first and the project launch settings after the DB is up and running.
[Frontend README](./frontend/README.md) [Frontend README](./frontend/README.md)