Apply suggestion
continuous-integration/drone/push Build is passing Details

maxime 1 year ago
parent 7e8a15398c
commit 2e1efeeb25

@ -1,8 +1,23 @@
import { ReactNode, useCallback, useEffect, useMemo, useRef, useState } from "react" import {
ReactNode,
useCallback,
useEffect,
useMemo,
useRef,
useState,
} from "react"
import { APITacticService } from "../service/APITacticService.ts" import { APITacticService } from "../service/APITacticService.ts"
import { CourtType, StepContent, StepInfoNode, TacticComponent } from "../model/tactic/Tactic.ts" import {
CourtType,
StepContent,
StepInfoNode,
TacticComponent,
} from "../model/tactic/Tactic.ts"
import { getParent } from "../domains/StepsDomain.ts" import { getParent } from "../domains/StepsDomain.ts"
import { computeRelativePositions, getPhantomInfo } from "../domains/PlayerDomains.ts" import {
computeRelativePositions,
getPhantomInfo,
} from "../domains/PlayerDomains.ts"
import { PlayerInfo, PlayerLike } from "../model/tactic/Player.ts" import { PlayerInfo, PlayerLike } from "../model/tactic/Player.ts"
import { CourtPlayer } from "./editor/CourtPlayer.tsx" import { CourtPlayer } from "./editor/CourtPlayer.tsx"
import { BALL_TYPE } from "../model/tactic/CourtObjects.ts" import { BALL_TYPE } from "../model/tactic/CourtObjects.ts"
@ -11,7 +26,6 @@ import { CourtAction } from "./editor/CourtAction.tsx"
import { BasketCourt, Court } from "./editor/BasketCourt.tsx" import { BasketCourt, Court } from "./editor/BasketCourt.tsx"
import { TacticService } from "../service/MutableTacticService.ts" import { TacticService } from "../service/MutableTacticService.ts"
export interface VisualizerProps { export interface VisualizerProps {
tacticId: number tacticId: number
stepId?: number stepId?: number
@ -33,13 +47,11 @@ export function Visualizer({ tacticId, stepId }: VisualizerProps) {
return return
} }
const rootStep = contextResult.stepsTree const rootStep = contextResult.stepsTree
setStepsTree(rootStep) setStepsTree(rootStep)
setCourtType(contextResult.courtType) setCourtType(contextResult.courtType)
} }
if (isNotInit) if (isNotInit) init()
init()
}, [isNotInit, service]) }, [isNotInit, service])
if (panicMessage) { if (panicMessage) {
@ -49,12 +61,14 @@ export function Visualizer({ tacticId, stepId }: VisualizerProps) {
return <p>Loading...</p> return <p>Loading...</p>
} }
return <StepVisualizer return (
courtType={courtType} <StepVisualizer
stepsTree={stepsTree} courtType={courtType}
stepId={stepId} stepsTree={stepsTree}
service={service} stepId={stepId}
/> service={service}
/>
)
} }
export interface StepVisualizerProps { export interface StepVisualizerProps {
@ -64,7 +78,12 @@ export interface StepVisualizerProps {
service: TacticService service: TacticService
} }
export function StepVisualizer({stepId, stepsTree, courtType, service}: StepVisualizerProps) { export function StepVisualizer({
stepId,
stepsTree,
courtType,
service,
}: StepVisualizerProps) {
const [panicMessage, setPanicMessage] = useState<string | null>(null) const [panicMessage, setPanicMessage] = useState<string | null>(null)
const [content, setContent] = useState<StepContent | null>(null) const [content, setContent] = useState<StepContent | null>(null)
const [parentContent, setParentContent] = useState<StepContent | null>() const [parentContent, setParentContent] = useState<StepContent | null>()
@ -73,7 +92,6 @@ export function StepVisualizer({stepId, stepsTree, courtType, service}: StepVisu
useEffect(() => { useEffect(() => {
async function init() { async function init() {
const contentStepId = stepId ?? stepsTree.id const contentStepId = stepId ?? stepsTree.id
const contentResult = await service.getContent(contentStepId) const contentResult = await service.getContent(contentStepId)
@ -124,11 +142,10 @@ export interface VisualizerFrameProps {
} }
export function VisualizerFrame({ export function VisualizerFrame({
content, content,
parentContent, parentContent,
courtType, courtType,
}: VisualizerFrameProps) { }: VisualizerFrameProps) {
const courtRef = useRef<HTMLDivElement>(null) const courtRef = useRef<HTMLDivElement>(null)
const courtBounds = useCallback( const courtBounds = useCallback(

@ -2,7 +2,11 @@ import { ReactElement, ReactNode, RefObject, useEffect, useState } from "react"
import { Action } from "../../model/tactic/Action" import { Action } from "../../model/tactic/Action"
import { CourtAction } from "./CourtAction" import { CourtAction } from "./CourtAction"
import { ComponentId, TacticComponent } from "../../model/tactic/Tactic" import {
ComponentId,
CourtType,
TacticComponent,
} from "../../model/tactic/Tactic"
import PlainCourt from "../../assets/court/full_court.svg?react" import PlainCourt from "../../assets/court/full_court.svg?react"
import HalfCourt from "../../assets/court/half_court.svg?react" import HalfCourt from "../../assets/court/half_court.svg?react"
@ -34,7 +38,6 @@ export function BasketCourt({
courtImage, courtImage,
courtRef, courtRef,
}: BasketCourtProps) { }: BasketCourtProps) {
const [court, setCourt] = useState(courtRef.current) const [court, setCourt] = useState(courtRef.current)
//force update once the court reference is set //force update once the court reference is set
@ -49,15 +52,11 @@ export function BasketCourt({
style={{ position: "relative" }}> style={{ position: "relative" }}>
{courtImage} {courtImage}
{court && {court && parentComponents?.map((i) => renderComponent(i, true))}
parentComponents?.map((i) => renderComponent(i, true))} {court && parentComponents?.flatMap((i) => renderActions(i, true))}
{court &&
parentComponents?.flatMap((i) => renderActions(i, true))}
{court && {court && components.map((i) => renderComponent(i, false))}
components.map((i) => renderComponent(i, false))} {court && components.flatMap((i) => renderActions(i, false))}
{court &&
components.flatMap((i) => renderActions(i, false))}
{previewAction && ( {previewAction && (
<CourtAction <CourtAction
@ -75,14 +74,11 @@ export function BasketCourt({
) )
} }
export function Court({ courtType }: { courtType: string }) { export function Court({ courtType }: { courtType: CourtType }) {
const CourtSvg = courtType === "PLAIN" ? PlainCourt : HalfCourt
return ( return (
<div className="court-image-div"> <div className="court-image-div">
{courtType == "PLAIN" ? ( <CourtSvg className="court-image" />
<PlainCourt className="court-image" />
) : (
<HalfCourt className="court-image" />
)}
</div> </div>
) )
} }

@ -15,12 +15,12 @@ export interface StepsTreeProps {
} }
export default function StepsTree({ export default function StepsTree({
root, root,
selectedStepId, selectedStepId,
onAddChildren, onAddChildren,
onRemoveNode, onRemoveNode,
onStepSelected, onStepSelected,
}: StepsTreeProps) { }: StepsTreeProps) {
return ( return (
<div className="steps-tree"> <div className="steps-tree">
<StepsTreeNode <StepsTreeNode
@ -46,13 +46,13 @@ interface StepsTreeContentProps {
} }
function StepsTreeNode({ function StepsTreeNode({
node, node,
rootNode, rootNode,
selectedStepId, selectedStepId,
onAddChildren, onAddChildren,
onRemoveNode, onRemoveNode,
onStepSelected, onStepSelected,
}: StepsTreeContentProps) { }: StepsTreeContentProps) {
const ref = useRef<HTMLDivElement>(null) const ref = useRef<HTMLDivElement>(null)
return ( return (
@ -67,8 +67,7 @@ function StepsTreeNode({
next: "step-piece-" + child.id, next: "step-piece-" + child.id,
}, },
]} ]}
onSegmentsChanges={() => { onSegmentsChanges={() => {}}
}}
forceStraight={true} forceStraight={true}
wavy={false} wavy={false}
readOnly={true} readOnly={true}
@ -80,9 +79,8 @@ function StepsTreeNode({
<StepPiece <StepPiece
id={node.id} id={node.id}
isSelected={selectedStepId === node.id} isSelected={selectedStepId === node.id}
onAddButtonClicked={onAddChildren onAddButtonClicked={
? () => onAddChildren(node) onAddChildren ? () => onAddChildren(node) : undefined
: undefined
} }
onRemoveButtonClicked={ onRemoveButtonClicked={
rootNode.id === node.id || !onRemoveNode rootNode.id === node.id || !onRemoveNode
@ -126,13 +124,13 @@ interface StepPieceProps {
} }
function StepPiece({ function StepPiece({
id, id,
isSelected, isSelected,
onAddButtonClicked, onAddButtonClicked,
onRemoveButtonClicked, onRemoveButtonClicked,
onSelected, onSelected,
children, children,
}: StepPieceProps) { }: StepPieceProps) {
return ( return (
<div <div
id={"step-piece-" + id} id={"step-piece-" + id}

@ -408,7 +408,6 @@ export function drainTerminalStateOnChildContent(
childContent.components, childContent.components,
) )
if (!childComponent) { if (!childComponent) {
//if the child does not contain the parent's component, add it to the children's content. //if the child does not contain the parent's component, add it to the children's content.
childContent = { childContent = {
@ -432,7 +431,6 @@ export function drainTerminalStateOnChildContent(
}, },
childContent, childContent,
) )
} }
// ensure that the component is a player // ensure that the component is a player

@ -715,7 +715,7 @@ function EditorPage({
const contentNode = ( const contentNode = (
<div id="content-div"> <div id="content-div">
<div id="racks" > <div id="racks">
<PlayerRack <PlayerRack
id={"allies"} id={"allies"}
objects={allies} objects={allies}

@ -1,7 +1,11 @@
import { ServiceError, TacticService } from "../service/MutableTacticService.ts" import { ServiceError, TacticService } from "../service/MutableTacticService.ts"
import { useNavigate, useParams } from "react-router-dom" import { useNavigate, useParams } from "react-router-dom"
import { useCallback, useEffect, useMemo, useReducer, useState } from "react" import { useCallback, useEffect, useMemo, useState } from "react"
import { VisualizerState, VisualizerStateActionKind, visualizerStateReducer } from "../visualizer/VisualizerState.ts" import {
useVisualizer,
VisualizerState,
VisualizerStateActionKind,
} from "../visualizer/VisualizerState.ts"
import { getParent } from "../domains/StepsDomain.ts" import { getParent } from "../domains/StepsDomain.ts"
import { mapToParentContent } from "../domains/TacticContentDomains.ts" import { mapToParentContent } from "../domains/TacticContentDomains.ts"
import StepsTree from "../components/editor/StepsTree.tsx" import StepsTree from "../components/editor/StepsTree.tsx"
@ -23,14 +27,18 @@ export function VisualizerPage({ guestMode }: VisualizerPageProps) {
if (guestMode || !idStr) { if (guestMode || !idStr) {
return ( return (
<ServedVisualizerPage service={LocalStorageTacticService.init()} <ServedVisualizerPage
openEditor={() => navigate("/tactic/edit-guest")} /> service={LocalStorageTacticService.init()}
openEditor={() => navigate("/tactic/edit-guest")}
/>
) )
} }
return ( return (
<ServedVisualizerPage service={new APITacticService(parseInt(idStr))} <ServedVisualizerPage
openEditor={() => navigate(`/tactic/${idStr}/edit`)} /> service={new APITacticService(parseInt(idStr))}
openEditor={() => navigate(`/tactic/${idStr}/edit`)}
/>
) )
} }
@ -45,9 +53,12 @@ interface ServedVisualizerPageProps {
openEditor: () => void openEditor: () => void
} }
function ServedVisualizerPage({ service, openEditor }: ServedVisualizerPageProps) { function ServedVisualizerPage({
service,
openEditor,
}: ServedVisualizerPageProps) {
const [panicMessage, setPanicMessage] = useState<string>() const [panicMessage, setPanicMessage] = useState<string>()
const [state, dispatch] = useReducer(visualizerStateReducer, null) const [state, dispatch] = useVisualizer(null)
const [canEdit, setCanEdit] = useState(false) const [canEdit, setCanEdit] = useState(false)
useEffect(() => { useEffect(() => {
@ -56,7 +67,7 @@ function ServedVisualizerPage({ service, openEditor }: ServedVisualizerPageProps
if (typeof contextResult === "string") { if (typeof contextResult === "string") {
setPanicMessage( setPanicMessage(
"There has been an error retrieving the editor initial context : " + "There has been an error retrieving the editor initial context : " +
contextResult, contextResult,
) )
return return
} }
@ -67,7 +78,7 @@ function ServedVisualizerPage({ service, openEditor }: ServedVisualizerPageProps
if (typeof contentResult === "string") { if (typeof contentResult === "string") {
setPanicMessage( setPanicMessage(
"There has been an error retrieving the tactic's root step content : " + "There has been an error retrieving the tactic's root step content : " +
contentResult, contentResult,
) )
return return
} }
@ -116,7 +127,6 @@ function ServedVisualizerPage({ service, openEditor }: ServedVisualizerPageProps
[openEditor, service, state], [openEditor, service, state],
) )
if (panicMessage) { if (panicMessage) {
return <p>{panicMessage}</p> return <p>{panicMessage}</p>
} }
@ -125,7 +135,13 @@ function ServedVisualizerPage({ service, openEditor }: ServedVisualizerPageProps
return <p>Retrieving tactic context. Please wait...</p> return <p>Retrieving tactic context. Please wait...</p>
} }
return <VisualizerPageContent state={state} service={visualizerService} showEditButton={canEdit} /> return (
<VisualizerPageContent
state={state}
service={visualizerService}
showEditButton={canEdit}
/>
)
} }
interface VisualizerPageContentProps { interface VisualizerPageContentProps {
@ -135,10 +151,10 @@ interface VisualizerPageContentProps {
} }
function VisualizerPageContent({ function VisualizerPageContent({
state: { content, parentContent, stepId, stepsTree, courtType, tacticName }, state: { content, parentContent, stepId, stepsTree, courtType, tacticName },
service, service,
showEditButton, showEditButton,
}: VisualizerPageContentProps) { }: VisualizerPageContentProps) {
const [isStepsTreeVisible, setStepsTreeVisible] = useState(true) const [isStepsTreeVisible, setStepsTreeVisible] = useState(true)
const [editorContentCurtainWidth, setEditorContentCurtainWidth] = const [editorContentCurtainWidth, setEditorContentCurtainWidth] =
@ -177,12 +193,12 @@ function VisualizerPageContent({
onClick={() => setStepsTreeVisible((b) => !b)}> onClick={() => setStepsTreeVisible((b) => !b)}>
ETAPES ETAPES
</button> </button>
{showEditButton && <button {showEditButton && (
onClick={() => service.openEditor()}> <button onClick={() => service.openEditor()}>
EDITER EDITER
</button>} </button>
)}
</div> </div>
</div> </div>
<div id="editor-div"> <div id="editor-div">

@ -33,7 +33,7 @@ export class LocalStorageTacticService implements MutableTacticService {
) )
localStorage.setItem( localStorage.setItem(
GUEST_MODE_STEP_CONTENT_STORAGE_KEY + 1, GUEST_MODE_STEP_CONTENT_STORAGE_KEY + 1,
JSON.stringify(<StepContent>{components: []}) JSON.stringify(<StepContent>{ components: [] }),
) )
} }

@ -1,4 +1,5 @@
import { CourtType, StepContent, StepInfoNode } from "../model/tactic/Tactic.ts" import { CourtType, StepContent, StepInfoNode } from "../model/tactic/Tactic.ts"
import { useReducer } from "react"
export interface VisualizerState { export interface VisualizerState {
stepId: number stepId: number
@ -9,7 +10,7 @@ export interface VisualizerState {
parentContent: StepContent | null parentContent: StepContent | null
} }
export enum VisualizerStateActionKind { export const enum VisualizerStateActionKind {
INIT, INIT,
SET_CONTENTS, SET_CONTENTS,
} }
@ -26,7 +27,11 @@ export type VisualizerStateAction =
stepId: number stepId: number
} }
export function visualizerStateReducer( export function useVisualizer(initialState: VisualizerState | null) {
return useReducer(visualizerStateReducer, initialState)
}
function visualizerStateReducer(
state: VisualizerState | null, state: VisualizerState | null,
action: VisualizerStateAction, action: VisualizerStateAction,
): VisualizerState | null { ): VisualizerState | null {

Loading…
Cancel
Save