add redux and user slice
This commit is contained in:
@@ -5,6 +5,7 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@grafana/faro-web-sdk": "^1.4.2",
|
"@grafana/faro-web-sdk": "^1.4.2",
|
||||||
"@pdf-lib/fontkit": "^1.1.1",
|
"@pdf-lib/fontkit": "^1.1.1",
|
||||||
|
"@reduxjs/toolkit": "^2.2.2",
|
||||||
"@testing-library/jest-dom": "^6.4.2",
|
"@testing-library/jest-dom": "^6.4.2",
|
||||||
"@testing-library/react": "^14.0.0",
|
"@testing-library/react": "^14.0.0",
|
||||||
"@testing-library/user-event": "^14.5.1",
|
"@testing-library/user-event": "^14.5.1",
|
||||||
@@ -23,6 +24,7 @@
|
|||||||
"react": "^18.2.0",
|
"react": "^18.2.0",
|
||||||
"react-bootstrap": "^2.10.2",
|
"react-bootstrap": "^2.10.2",
|
||||||
"react-dom": "^18.2.0",
|
"react-dom": "^18.2.0",
|
||||||
|
"react-redux": "^9.1.0",
|
||||||
"react-router-dom": "^6.17.0",
|
"react-router-dom": "^6.17.0",
|
||||||
"react-scripts": "5.0.1",
|
"react-scripts": "5.0.1",
|
||||||
"rimraf": "^5.0.5",
|
"rimraf": "^5.0.5",
|
||||||
|
|||||||
+25
-20
@@ -1,5 +1,5 @@
|
|||||||
import * as React from 'react';
|
import * as React from "react";
|
||||||
import './App.css';
|
import "./App.css";
|
||||||
import {Faro} from "@grafana/faro-web-sdk";
|
import {Faro} from "@grafana/faro-web-sdk";
|
||||||
import {createBrowserRouter, redirect, RouterProvider} from "react-router-dom";
|
import {createBrowserRouter, redirect, RouterProvider} from "react-router-dom";
|
||||||
import CreateCharacter from "./first-edition/pages/CreateCharacter";
|
import CreateCharacter from "./first-edition/pages/CreateCharacter";
|
||||||
@@ -7,16 +7,18 @@ import CharacterList from "./shared/pages/CharacterList";
|
|||||||
import ErrorBoundary from "./shared/ErrorBoundary";
|
import ErrorBoundary from "./shared/ErrorBoundary";
|
||||||
import Header from "./shared/Header";
|
import Header from "./shared/Header";
|
||||||
import Footer from "./shared/Footer";
|
import Footer from "./shared/Footer";
|
||||||
import {useState} from "react";
|
|
||||||
import {UserContext, userDefaults} from './shared/contexts/UserContext';
|
|
||||||
import CreateCharacter2E from "./second-edition/pages/CreateCharacter2E";
|
import CreateCharacter2E from "./second-edition/pages/CreateCharacter2E";
|
||||||
|
import store, {AppDispatch, RootState} from './store'
|
||||||
|
import { Provider } from "react-redux"
|
||||||
|
import { useSelector, useDispatch } from 'react-redux'
|
||||||
|
import {load, setUser, unsetUser, userSelector} from './shared/domain-models/userSlice'
|
||||||
|
|
||||||
function App(props: {faro?: Faro}) {
|
function Router(props: {faro?: Faro}) {
|
||||||
|
const dispatch = useDispatch.withTypes<AppDispatch>()()
|
||||||
const [fetchedUser, setFetchedUser] = useState(userDefaults)
|
const fetchedUser = useSelector.withTypes<RootState>()(userSelector)
|
||||||
|
|
||||||
if (fetchedUser.state === "not-started") {
|
if (fetchedUser.state === "not-started") {
|
||||||
setFetchedUser({...fetchedUser, state: "loading"})
|
dispatch(load())
|
||||||
fetch(`${window.location.origin}/api/User/me`)
|
fetch(`${window.location.origin}/api/User/me`)
|
||||||
.then(response => {
|
.then(response => {
|
||||||
if (response.ok) {
|
if (response.ok) {
|
||||||
@@ -26,23 +28,19 @@ function App(props: {faro?: Faro}) {
|
|||||||
})
|
})
|
||||||
.then(userNameResponse => {
|
.then(userNameResponse => {
|
||||||
const userName = userNameResponse && userNameResponse.length > 0 ? userNameResponse : null;
|
const userName = userNameResponse && userNameResponse.length > 0 ? userNameResponse : null;
|
||||||
setFetchedUser({
|
dispatch(setUser(userName))
|
||||||
data: userName,
|
|
||||||
state: "finished"
|
|
||||||
});
|
|
||||||
})
|
})
|
||||||
.catch(() => {
|
.catch(() => {
|
||||||
setFetchedUser({
|
dispatch(unsetUser())
|
||||||
data: null,
|
|
||||||
state: "finished"
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const router = createBrowserRouter([
|
const router = createBrowserRouter([
|
||||||
{
|
{
|
||||||
path: "/",
|
path: "/",
|
||||||
loader: () => fetchedUser.data == null ? redirect("/2e/karakter") : redirect("/karaktereim")
|
loader: () => fetchedUser.email == null ? redirect("/2e/karakter") : redirect("/karaktereim")
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: "/karaktereim",
|
path: "/karaktereim",
|
||||||
@@ -83,13 +81,20 @@ function App(props: {faro?: Faro}) {
|
|||||||
]);
|
]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<UserContext.Provider value={fetchedUser}>
|
|
||||||
<Header/>
|
|
||||||
<div className='container'>
|
<div className='container'>
|
||||||
<RouterProvider router={router}/>
|
<RouterProvider router={router}/>
|
||||||
</div>
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function App(props: { faro?: Faro }) {
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Provider store={store}>
|
||||||
|
<Header/>
|
||||||
|
<Router faro={props.faro} />
|
||||||
<Footer />
|
<Footer />
|
||||||
</UserContext.Provider>
|
</Provider>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import React, {useContext, useState} from 'react';
|
import React, {useState} from 'react';
|
||||||
import './CreateCharacter.css'
|
import './CreateCharacter.css'
|
||||||
import {Faj, TulajdonsagokFajjal} from "../domain-models/faj";
|
import {Faj, TulajdonsagokFajjal} from "../domain-models/faj";
|
||||||
import {Osztaly, SetFelszerelesForChangedOsztaly} from "../domain-models/osztaly"
|
import {Osztaly, SetFelszerelesForChangedOsztaly} from "../domain-models/osztaly"
|
||||||
@@ -31,8 +31,10 @@ import {Faro} from "@grafana/faro-web-sdk";
|
|||||||
import {StoreNewCharacter, UpdateCharacter} from "../api/character.api";
|
import {StoreNewCharacter, UpdateCharacter} from "../api/character.api";
|
||||||
import {useLoaderData, useNavigate, useParams} from "react-router-dom";
|
import {useLoaderData, useNavigate, useParams} from "react-router-dom";
|
||||||
import saveOverlayTooltip from "../components/SaveOverlayTooltip";
|
import saveOverlayTooltip from "../components/SaveOverlayTooltip";
|
||||||
import {UserContext} from "../../shared/contexts/UserContext";
|
|
||||||
import {KarakterTulajdonsagok} from "../domain-models/tulajdonsag";
|
import {KarakterTulajdonsagok} from "../domain-models/tulajdonsag";
|
||||||
|
import {useSelector} from "react-redux";
|
||||||
|
import {RootState} from "../../store";
|
||||||
|
import {userSelector} from "../../shared/domain-models/userSlice";
|
||||||
|
|
||||||
function CreateCharacterPage(props: {
|
function CreateCharacterPage(props: {
|
||||||
faro?: Faro,
|
faro?: Faro,
|
||||||
@@ -46,9 +48,9 @@ function CreateCharacterPage(props: {
|
|||||||
initialKarakterInputs = t2
|
initialKarakterInputs = t2
|
||||||
}
|
}
|
||||||
const { id } = useParams();
|
const { id } = useParams();
|
||||||
const fetchedUser = useContext(UserContext);
|
const fetchedUser = useSelector.withTypes<RootState>()(userSelector);
|
||||||
|
|
||||||
const initialIsPublic = loaderData?.isPublic ?? fetchedUser?.data == null;
|
const initialIsPublic = loaderData?.isPublic ?? fetchedUser?.email == null;
|
||||||
|
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
|
||||||
@@ -257,7 +259,7 @@ function CreateCharacterPage(props: {
|
|||||||
<h5 className='col align-self-center'>Véglegesítés</h5>
|
<h5 className='col align-self-center'>Véglegesítés</h5>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{fetchedUser.data != null &&
|
{fetchedUser.email != null &&
|
||||||
<div className='row m-2'>
|
<div className='row m-2'>
|
||||||
<label className='col-md-2 col-sm-3 col-form-label'>Publikus karakterlap?</label>
|
<label className='col-md-2 col-sm-3 col-form-label'>Publikus karakterlap?</label>
|
||||||
<select className="col form-select" value={isPublic.toString()}
|
<select className="col form-select" value={isPublic.toString()}
|
||||||
@@ -270,7 +272,7 @@ function CreateCharacterPage(props: {
|
|||||||
<div className="row">
|
<div className="row">
|
||||||
<div className="col-6">
|
<div className="col-6">
|
||||||
<div className='d-grid gap-2 m-5'>
|
<div className='d-grid gap-2 m-5'>
|
||||||
{fetchedUser.data == null
|
{fetchedUser.email == null
|
||||||
? <OverlayTrigger placement='top' overlay={saveOverlayTooltip} delay={0}
|
? <OverlayTrigger placement='top' overlay={saveOverlayTooltip} delay={0}
|
||||||
defaultShow={false} flip={false}>
|
defaultShow={false} flip={false}>
|
||||||
<button className='btn btn-danger btn-lg' type='button'
|
<button className='btn btn-danger btn-lg' type='button'
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import React, {useContext, useState} from 'react'
|
import React, {useState} from 'react'
|
||||||
import {useLoaderData, useNavigate, useParams} from "react-router-dom";
|
import {useLoaderData, useNavigate, useParams} from "react-router-dom";
|
||||||
import {Button, InputGroup, Modal, OverlayTrigger, Toast, ToastContainer} from "react-bootstrap";
|
import {Button, InputGroup, Modal, OverlayTrigger, Toast, ToastContainer} from "react-bootstrap";
|
||||||
import {ChangeLvl1Osztaly, DefaultKarakter, Karakter2E} from "../domain-models/karakter2E";
|
import {ChangeLvl1Osztaly, DefaultKarakter, Karakter2E} from "../domain-models/karakter2E";
|
||||||
@@ -25,7 +25,6 @@ import {LevelDown, LevelUp} from "../domain-models/szintlepes";
|
|||||||
import HarcosFegyverSpecializacio from "../components/HarcosFegyverSpec";
|
import HarcosFegyverSpecializacio from "../components/HarcosFegyverSpec";
|
||||||
import {arraySetN} from "../../util";
|
import {arraySetN} from "../../util";
|
||||||
import saveOverlayTooltip from "../../first-edition/components/SaveOverlayTooltip";
|
import saveOverlayTooltip from "../../first-edition/components/SaveOverlayTooltip";
|
||||||
import {UserContext} from "../../shared/contexts/UserContext";
|
|
||||||
import {
|
import {
|
||||||
StoreNewCharacter2E,
|
StoreNewCharacter2E,
|
||||||
UpdateCharacter2E
|
UpdateCharacter2E
|
||||||
@@ -34,20 +33,23 @@ import {Faro} from "@grafana/faro-web-sdk";
|
|||||||
import Form from "react-bootstrap/Form";
|
import Form from "react-bootstrap/Form";
|
||||||
import {CreatePDF} from "../pdf/character.pdf";
|
import {CreatePDF} from "../pdf/character.pdf";
|
||||||
import {KarakterInputToPdfView} from "../pdf/karakter_pdf_view";
|
import {KarakterInputToPdfView} from "../pdf/karakter_pdf_view";
|
||||||
|
import {useSelector} from "react-redux";
|
||||||
|
import {RootState} from "../../store";
|
||||||
|
import {userSelector} from "../../shared/domain-models/userSlice";
|
||||||
|
|
||||||
function CreateCharacter2E(props: {
|
function CreateCharacter2E(props: {
|
||||||
faro?: Faro
|
faro?: Faro
|
||||||
}) {
|
}) {
|
||||||
const {faro} = props
|
const {faro} = props
|
||||||
const { id } = useParams();
|
const { id } = useParams();
|
||||||
const fetchedUser = useContext(UserContext);
|
const fetchedUser = useSelector.withTypes<RootState>()(userSelector);
|
||||||
const loaderData = useLoaderData() as Karakter2E & { isPublic: boolean } | undefined;
|
const loaderData = useLoaderData() as Karakter2E & { isPublic: boolean } | undefined;
|
||||||
let initialKarakterInputs = DefaultKarakter;
|
let initialKarakterInputs = DefaultKarakter;
|
||||||
if (loaderData != null) {
|
if (loaderData != null) {
|
||||||
const { isPublic: t1, ...t2 } = loaderData;
|
const { isPublic: t1, ...t2 } = loaderData;
|
||||||
initialKarakterInputs = t2
|
initialKarakterInputs = t2
|
||||||
}
|
}
|
||||||
const initialIsPublic = loaderData?.isPublic ?? fetchedUser?.data == null;
|
const initialIsPublic = loaderData?.isPublic ?? fetchedUser?.email == null;
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
|
||||||
const [karakter, setKarakter] = useState(initialKarakterInputs)
|
const [karakter, setKarakter] = useState(initialKarakterInputs)
|
||||||
@@ -234,7 +236,7 @@ function CreateCharacter2E(props: {
|
|||||||
<h5 className='col align-self-center'>Véglegesítés</h5>
|
<h5 className='col align-self-center'>Véglegesítés</h5>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{fetchedUser.data != null &&
|
{fetchedUser.email != null &&
|
||||||
<div className='row m-2'>
|
<div className='row m-2'>
|
||||||
<label className='col-md-2 col-sm-3 col-form-label'>Publikus karakterlap?</label>
|
<label className='col-md-2 col-sm-3 col-form-label'>Publikus karakterlap?</label>
|
||||||
<select className="col form-select" value={isPublic.toString()}
|
<select className="col form-select" value={isPublic.toString()}
|
||||||
@@ -247,7 +249,7 @@ function CreateCharacter2E(props: {
|
|||||||
<div className="row">
|
<div className="row">
|
||||||
<div className="col-6">
|
<div className="col-6">
|
||||||
<div className='d-grid gap-2 m-5'>
|
<div className='d-grid gap-2 m-5'>
|
||||||
{fetchedUser.data == null
|
{fetchedUser.email == null
|
||||||
? <OverlayTrigger
|
? <OverlayTrigger
|
||||||
placement='top'
|
placement='top'
|
||||||
overlay={saveOverlayTooltip}
|
overlay={saveOverlayTooltip}
|
||||||
|
|||||||
@@ -1,28 +1,29 @@
|
|||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
import {useContext} from "react";
|
|
||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
import {Container, Nav, Navbar} from "react-bootstrap";
|
import {Container, Nav, Navbar} from "react-bootstrap";
|
||||||
import { UserContext } from "./contexts/UserContext";
|
import {userSelector} from "./domain-models/userSlice";
|
||||||
|
import {RootState} from "../store";
|
||||||
|
import {useSelector} from "react-redux";
|
||||||
|
|
||||||
async function logout() {
|
async function logout() {
|
||||||
await axios.post("/Identity/Account/Logout")
|
await axios.post("/Identity/Account/Logout")
|
||||||
document.location.reload()
|
document.location.reload()
|
||||||
}
|
}
|
||||||
|
|
||||||
function Header(props: {}) {
|
function Header() {
|
||||||
|
|
||||||
const fetchedUser = useContext(UserContext);
|
const fetchedUser = useSelector.withTypes<RootState>()(userSelector);
|
||||||
|
|
||||||
return <header>
|
return <header>
|
||||||
<Navbar expand="sm" className="navbar-light bg-white border-bottom box-shadow mb-3">
|
<Navbar expand="sm" className="navbar-light bg-white border-bottom box-shadow mb-3">
|
||||||
<Container className="ps-4 pe-4">
|
<Container className="ps-4 pe-4">
|
||||||
<Navbar.Brand href="/">Kemkas</Navbar.Brand>
|
<Navbar.Brand href="/">Kemkas</Navbar.Brand>
|
||||||
{fetchedUser.data != null && <Nav.Link className="text-dark" href="/karaktereim">Karaktereim</Nav.Link>}
|
{fetchedUser.email != null && <Nav.Link className="text-dark" href="/karaktereim">Karaktereim</Nav.Link>}
|
||||||
<Navbar.Toggle aria-controls="basic-navbar-nav" />
|
<Navbar.Toggle aria-controls="basic-navbar-nav" />
|
||||||
<Navbar.Collapse id="basic-navbar-nav" className="d-sm-inline-flex flex-sm-row-reverse">
|
<Navbar.Collapse id="basic-navbar-nav" className="d-sm-inline-flex flex-sm-row-reverse">
|
||||||
<Nav>
|
<Nav>
|
||||||
{fetchedUser.state !== "finished" ? "Loading..." :
|
{fetchedUser.state !== "finished" ? "Loading..." :
|
||||||
fetchedUser.data == null
|
fetchedUser.email == null
|
||||||
? <>
|
? <>
|
||||||
<li className="nav-item">
|
<li className="nav-item">
|
||||||
<a className="nav-link text-dark" href="/Identity/Account/Register">Register</a>
|
<a className="nav-link text-dark" href="/Identity/Account/Register">Register</a>
|
||||||
@@ -34,7 +35,7 @@ function Header(props: {}) {
|
|||||||
: <>
|
: <>
|
||||||
<li className="nav-item">
|
<li className="nav-item">
|
||||||
<a className="nav-link text-dark"
|
<a className="nav-link text-dark"
|
||||||
href="/Identity/Account/Manage">Hello {fetchedUser.data}!</a>
|
href="/Identity/Account/Manage">Hello {fetchedUser.email}!</a>
|
||||||
</li>
|
</li>
|
||||||
<li className="nav-item">
|
<li className="nav-item">
|
||||||
<button className="nav-link nav text-dark" onClick={logout}>Logout</button>
|
<button className="nav-link nav text-dark" onClick={logout}>Logout</button>
|
||||||
|
|||||||
@@ -0,0 +1,31 @@
|
|||||||
|
import { createSlice } from '@reduxjs/toolkit'
|
||||||
|
|
||||||
|
type LoadingState = "not-started" | "loading" | "finished"
|
||||||
|
|
||||||
|
export const userSlice = createSlice({
|
||||||
|
name: 'user',
|
||||||
|
initialState: {
|
||||||
|
state: "not-started" as LoadingState,
|
||||||
|
email: null,
|
||||||
|
},
|
||||||
|
reducers: {
|
||||||
|
load: (state) => {
|
||||||
|
state.state = "loading"
|
||||||
|
},
|
||||||
|
setUser: (state, action) => {
|
||||||
|
state.state = "finished"
|
||||||
|
state.email = action.payload
|
||||||
|
},
|
||||||
|
unsetUser: (state) => {
|
||||||
|
state.state = "finished"
|
||||||
|
state.email = null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
// Action creators are generated for each case reducer function
|
||||||
|
export const { load, setUser, unsetUser } = userSlice.actions
|
||||||
|
|
||||||
|
export const userSelector = userSlice.selectSlice
|
||||||
|
|
||||||
|
export default userSlice.reducer
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
import { configureStore } from "@reduxjs/toolkit"
|
||||||
|
import userReducer from './shared/domain-models/userSlice'
|
||||||
|
|
||||||
|
const store = configureStore({
|
||||||
|
reducer: {
|
||||||
|
user: userReducer
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
// Infer the `RootState` and `AppDispatch` types from the store itself
|
||||||
|
export type RootState = ReturnType<typeof store.getState>
|
||||||
|
// Inferred type: {posts: PostsState, comments: CommentsState, users: UsersState}
|
||||||
|
export type AppDispatch = typeof store.dispatch
|
||||||
|
|
||||||
|
export default store
|
||||||
@@ -1818,6 +1818,16 @@
|
|||||||
dependencies:
|
dependencies:
|
||||||
"@swc/helpers" "^0.5.0"
|
"@swc/helpers" "^0.5.0"
|
||||||
|
|
||||||
|
"@reduxjs/toolkit@^2.2.2":
|
||||||
|
version "2.2.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/@reduxjs/toolkit/-/toolkit-2.2.2.tgz#952fc8f8315d7274e28f6e4608b7ec66fce7e94e"
|
||||||
|
integrity sha512-454GZrEx3G6QSYwIx9ROaso1HR6sTH8qyZBe3KEsdWVGU3ayV8jYCwdaEJV3vl9V6+pi3GRl+7Xl7AeDna6qwQ==
|
||||||
|
dependencies:
|
||||||
|
immer "^10.0.3"
|
||||||
|
redux "^5.0.1"
|
||||||
|
redux-thunk "^3.1.0"
|
||||||
|
reselect "^5.0.1"
|
||||||
|
|
||||||
"@remix-run/router@1.14.2":
|
"@remix-run/router@1.14.2":
|
||||||
version "1.14.2"
|
version "1.14.2"
|
||||||
resolved "https://registry.yarnpkg.com/@remix-run/router/-/router-1.14.2.tgz#4d58f59908d9197ba3179310077f25c88e49ed17"
|
resolved "https://registry.yarnpkg.com/@remix-run/router/-/router-1.14.2.tgz#4d58f59908d9197ba3179310077f25c88e49ed17"
|
||||||
@@ -2403,6 +2413,11 @@
|
|||||||
resolved "https://registry.yarnpkg.com/@types/trusted-types/-/trusted-types-2.0.7.tgz#baccb07a970b91707df3a3e8ba6896c57ead2d11"
|
resolved "https://registry.yarnpkg.com/@types/trusted-types/-/trusted-types-2.0.7.tgz#baccb07a970b91707df3a3e8ba6896c57ead2d11"
|
||||||
integrity sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==
|
integrity sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==
|
||||||
|
|
||||||
|
"@types/use-sync-external-store@^0.0.3":
|
||||||
|
version "0.0.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/@types/use-sync-external-store/-/use-sync-external-store-0.0.3.tgz#b6725d5f4af24ace33b36fafd295136e75509f43"
|
||||||
|
integrity sha512-EwmlvuaxPNej9+T4v5AuBPJa2x2UOJVdjCtDHgcDqitUeOtjnJKJ+apYjVcAoBEMjKW1VVFGZLUb5+qqa09XFA==
|
||||||
|
|
||||||
"@types/warning@^3.0.0":
|
"@types/warning@^3.0.0":
|
||||||
version "3.0.3"
|
version "3.0.3"
|
||||||
resolved "https://registry.yarnpkg.com/@types/warning/-/warning-3.0.3.tgz#d1884c8cc4a426d1ac117ca2611bf333834c6798"
|
resolved "https://registry.yarnpkg.com/@types/warning/-/warning-3.0.3.tgz#d1884c8cc4a426d1ac117ca2611bf333834c6798"
|
||||||
@@ -5460,6 +5475,11 @@ image-size@~0.5.0:
|
|||||||
resolved "https://registry.yarnpkg.com/image-size/-/image-size-0.5.5.tgz#09dfd4ab9d20e29eb1c3e80b8990378df9e3cb9c"
|
resolved "https://registry.yarnpkg.com/image-size/-/image-size-0.5.5.tgz#09dfd4ab9d20e29eb1c3e80b8990378df9e3cb9c"
|
||||||
integrity sha512-6TDAlDPZxUFCv+fuOkIoXT/V/f3Qbq8e37p+YOiYrUv3v9cc3/6x78VdfPgFVaB9dZYeLUfKgHRebpkm/oP2VQ==
|
integrity sha512-6TDAlDPZxUFCv+fuOkIoXT/V/f3Qbq8e37p+YOiYrUv3v9cc3/6x78VdfPgFVaB9dZYeLUfKgHRebpkm/oP2VQ==
|
||||||
|
|
||||||
|
immer@^10.0.3:
|
||||||
|
version "10.0.4"
|
||||||
|
resolved "https://registry.yarnpkg.com/immer/-/immer-10.0.4.tgz#09af41477236b99449f9d705369a4daaf780362b"
|
||||||
|
integrity sha512-cuBuGK40P/sk5IzWa9QPUaAdvPHjkk1c+xYsd9oZw+YQQEV+10G0P5uMpGctZZKnyQ+ibRO08bD25nWLmYi2pw==
|
||||||
|
|
||||||
immer@^9.0.7:
|
immer@^9.0.7:
|
||||||
version "9.0.21"
|
version "9.0.21"
|
||||||
resolved "https://registry.yarnpkg.com/immer/-/immer-9.0.21.tgz#1e025ea31a40f24fb064f1fef23e931496330176"
|
resolved "https://registry.yarnpkg.com/immer/-/immer-9.0.21.tgz#1e025ea31a40f24fb064f1fef23e931496330176"
|
||||||
@@ -8250,6 +8270,14 @@ react-lifecycles-compat@^3.0.4:
|
|||||||
resolved "https://registry.yarnpkg.com/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz#4f1a273afdfc8f3488a8c516bfda78f872352362"
|
resolved "https://registry.yarnpkg.com/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz#4f1a273afdfc8f3488a8c516bfda78f872352362"
|
||||||
integrity sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA==
|
integrity sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA==
|
||||||
|
|
||||||
|
react-redux@^9.1.0:
|
||||||
|
version "9.1.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/react-redux/-/react-redux-9.1.0.tgz#46a46d4cfed4e534ce5452bb39ba18e1d98a8197"
|
||||||
|
integrity sha512-6qoDzIO+gbrza8h3hjMA9aq4nwVFCKFtY2iLxCtVT38Swyy2C/dJCGBXHeHLtx6qlg/8qzc2MrhOeduf5K32wQ==
|
||||||
|
dependencies:
|
||||||
|
"@types/use-sync-external-store" "^0.0.3"
|
||||||
|
use-sync-external-store "^1.0.0"
|
||||||
|
|
||||||
react-refresh@^0.11.0:
|
react-refresh@^0.11.0:
|
||||||
version "0.11.0"
|
version "0.11.0"
|
||||||
resolved "https://registry.yarnpkg.com/react-refresh/-/react-refresh-0.11.0.tgz#77198b944733f0f1f1a90e791de4541f9f074046"
|
resolved "https://registry.yarnpkg.com/react-refresh/-/react-refresh-0.11.0.tgz#77198b944733f0f1f1a90e791de4541f9f074046"
|
||||||
@@ -8393,6 +8421,16 @@ redent@^3.0.0:
|
|||||||
indent-string "^4.0.0"
|
indent-string "^4.0.0"
|
||||||
strip-indent "^3.0.0"
|
strip-indent "^3.0.0"
|
||||||
|
|
||||||
|
redux-thunk@^3.1.0:
|
||||||
|
version "3.1.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/redux-thunk/-/redux-thunk-3.1.0.tgz#94aa6e04977c30e14e892eae84978c1af6058ff3"
|
||||||
|
integrity sha512-NW2r5T6ksUKXCabzhL9z+h206HQw/NJkcLm1GPImRQ8IzfXwRGqjVhKJGauHirT0DAuyy6hjdnMZaRoAcy0Klw==
|
||||||
|
|
||||||
|
redux@^5.0.1:
|
||||||
|
version "5.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/redux/-/redux-5.0.1.tgz#97fa26881ce5746500125585d5642c77b6e9447b"
|
||||||
|
integrity sha512-M9/ELqF6fy8FwmkpnF0S3YKOqMyoWJ4+CS5Efg2ct3oY9daQvd/Pc71FpGZsVsbl3Cpb+IIcjBDUnnyBdQbq4w==
|
||||||
|
|
||||||
reflect.getprototypeof@^1.0.4:
|
reflect.getprototypeof@^1.0.4:
|
||||||
version "1.0.4"
|
version "1.0.4"
|
||||||
resolved "https://registry.yarnpkg.com/reflect.getprototypeof/-/reflect.getprototypeof-1.0.4.tgz#aaccbf41aca3821b87bb71d9dcbc7ad0ba50a3f3"
|
resolved "https://registry.yarnpkg.com/reflect.getprototypeof/-/reflect.getprototypeof-1.0.4.tgz#aaccbf41aca3821b87bb71d9dcbc7ad0ba50a3f3"
|
||||||
@@ -8498,6 +8536,11 @@ requires-port@^1.0.0:
|
|||||||
resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff"
|
resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff"
|
||||||
integrity sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==
|
integrity sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==
|
||||||
|
|
||||||
|
reselect@^5.0.1:
|
||||||
|
version "5.1.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/reselect/-/reselect-5.1.0.tgz#c479139ab9dd91be4d9c764a7f3868210ef8cd21"
|
||||||
|
integrity sha512-aw7jcGLDpSgNDyWBQLv2cedml85qd95/iszJjN988zX1t7AVRJi19d9kto5+W7oCfQ94gyo40dVbT6g2k4/kXg==
|
||||||
|
|
||||||
resolve-cwd@^3.0.0:
|
resolve-cwd@^3.0.0:
|
||||||
version "3.0.0"
|
version "3.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-3.0.0.tgz#0f0075f1bb2544766cf73ba6a6e2adfebcb13f2d"
|
resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-3.0.0.tgz#0f0075f1bb2544766cf73ba6a6e2adfebcb13f2d"
|
||||||
@@ -9665,6 +9708,11 @@ url-parse@^1.5.3:
|
|||||||
querystringify "^2.1.1"
|
querystringify "^2.1.1"
|
||||||
requires-port "^1.0.0"
|
requires-port "^1.0.0"
|
||||||
|
|
||||||
|
use-sync-external-store@^1.0.0:
|
||||||
|
version "1.2.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz#7dbefd6ef3fe4e767a0cf5d7287aacfb5846928a"
|
||||||
|
integrity sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA==
|
||||||
|
|
||||||
util-deprecate@^1.0.1, util-deprecate@^1.0.2, util-deprecate@~1.0.1:
|
util-deprecate@^1.0.1, util-deprecate@^1.0.2, util-deprecate@~1.0.1:
|
||||||
version "1.0.2"
|
version "1.0.2"
|
||||||
resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"
|
resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"
|
||||||
|
|||||||
Reference in New Issue
Block a user