add a gest mode for editor if user is not connected

pull/38/head
Override-6 1 year ago
parent 3de131d112
commit d1564a3549
Signed by untrusted user who does not match committer: maxime.batista
GPG Key ID: 8002CC4B4DD9ECA5

@ -4,6 +4,10 @@ export interface SaveState {
}
export class SaveStates {
static readonly Guest: SaveState = {
className: "save-state-guest",
message: "you are not connected, your changes will not be saved.",
}
static readonly Ok: SaveState = {
className: "save-state-ok",
message: "saved",

@ -85,6 +85,7 @@
color: green;
}
.save-state-saving {
.save-state-saving,
.save-state-guest {
color: gray;
}

@ -29,7 +29,7 @@ const ERROR_STYLE: CSSProperties = {
export interface EditorViewProps {
tactic: Tactic
onContentChange: (tactic: TacticContent) => Promise<boolean>
onContentChange: (tactic: TacticContent) => Promise<SaveState>
onNameChange: (name: string) => Promise<boolean>
}
@ -50,31 +50,43 @@ export default function Editor({
name: string
content: string
}) {
const isInGuestMode = id == -1
return (
<EditorView
tactic={{ name, id, content: JSON.parse(content) }}
onContentChange={(content: TacticContent) =>
fetchAPI(`tactic/${id}/save`, { content }).then((r) => r.ok)
}
onNameChange={(name: string) =>
fetchAPI(`tactic/${id}/edit/name`, { name }).then((r) => r.ok)
}
onContentChange={async (content: TacticContent) => {
if (isInGuestMode) {
return SaveStates.Guest
}
return fetchAPI(`tactic/${id}/save`, { content }).then((r) =>
r.ok ? SaveStates.Ok : SaveStates.Err,
)
}}
onNameChange={async (name: string) => {
if (isInGuestMode) {
return true //simulate that the name has been changed
}
return fetchAPI(`tactic/${id}/edit/name`, { name }).then(
(r) => r.ok,
)
}}
/>
)
}
function EditorView({
tactic: { name, content: initialContent },
tactic: { id, name, content: initialContent },
onContentChange,
onNameChange,
}: EditorViewProps) {
const isInGuestMode = id == -1
const [style, setStyle] = useState<CSSProperties>({})
const [content, setContent, saveState] = useContentState(
initialContent,
(content) =>
onContentChange(content).then((success) =>
success ? SaveStates.Ok : SaveStates.Err,
),
isInGuestMode ? SaveStates.Guest : SaveStates.Ok,
onContentChange,
)
const [allies, setAllies] = useState(
getRackPlayers(Team.Allies, content.players),
@ -220,26 +232,30 @@ function getRackPlayers(team: Team, players: Player[]): RackedPlayer[] {
function useContentState<S>(
initialContent: S,
initialSaveState: SaveState,
saveStateCallback: (s: S) => Promise<SaveState>,
): [S, Dispatch<SetStateAction<S>>, SaveState] {
const [content, setContent] = useState(initialContent)
const [savingState, setSavingState] = useState(SaveStates.Ok)
const [savingState, setSavingState] = useState(initialSaveState)
const setContentSynced = useCallback((newState: SetStateAction<S>) => {
setContent((content) => {
const state =
typeof newState === "function"
? (newState as (state: S) => S)(content)
: newState
if (state !== content) {
setSavingState(SaveStates.Saving)
saveStateCallback(state)
.then(setSavingState)
.catch(() => setSavingState(SaveStates.Err))
}
return state
})
}, [saveStateCallback])
const setContentSynced = useCallback(
(newState: SetStateAction<S>) => {
setContent((content) => {
const state =
typeof newState === "function"
? (newState as (state: S) => S)(content)
: newState
if (state !== content) {
setSavingState(SaveStates.Saving)
saveStateCallback(state)
.then(setSavingState)
.catch(() => setSavingState(SaveStates.Err))
}
return state
})
},
[saveStateCallback],
)
return [content, setContentSynced, savingState]
}

@ -88,7 +88,9 @@ function getRoutes(): AltoRouter {
//tactic-related
$ar->map("GET", "/tactic/[i:id]/view", Action::auth(fn(int $id, SessionHandle $s) => getVisualizerController()->openVisualizer($id, $s)));
$ar->map("GET", "/tactic/[i:id]/edit", Action::auth(fn(int $id, SessionHandle $s) => getEditorController()->openEditor($id, $s)));
$ar->map("GET", "/tactic/new", Action::auth(fn(SessionHandle $s) => getEditorController()->createNew($s)));
// don't require an authentication to run this action.
// If the user is not connected, the tactic will never save.
$ar->map("GET", "/tactic/new", Action::noAuth(fn(SessionHandle $s) => getEditorController()->createNew($s)));
//team-related
$ar->map("GET", "/team/new", Action::auth(fn(SessionHandle $s) => getTeamController()->displayCreateTeam($s)));

@ -19,7 +19,7 @@ class API {
if ($response instanceof JsonHttpResponse) {
header('Content-type: application/json');
echo $response->getJson();
} else if (get_class($response) != HttpResponse::class) {
} elseif (get_class($response) != HttpResponse::class) {
throw new Exception("API returned unknown Http Response");
}
}

@ -28,13 +28,31 @@ class EditorController {
]);
}
/**
* @return ViewHttpResponse the editor view for a test tactic.
*/
private function openTestEditor(): ViewHttpResponse {
return ViewHttpResponse::react("views/Editor.tsx", [
"id" => -1, //-1 id means that the editor will not support saves
"content" => '{"players": []}',
"name" => TacticModel::TACTIC_DEFAULT_NAME,
]);
}
/**
* creates a new empty tactic, with default name
* If the given session does not contain a connected account,
* open a test editor.
* @param SessionHandle $session
* @return ViewHttpResponse the editor view
*/
public function createNew(SessionHandle $session): ViewHttpResponse {
$tactic = $this->model->makeNewDefault($session->getAccount()->getId());
$account = $session->getAccount();
if ($account == null) {
return $this->openTestEditor();
}
$tactic = $this->model->makeNewDefault($account->getId());
return $this->openEditorFor($tactic);
}
@ -55,6 +73,4 @@ class EditorController {
return $this->openEditorFor($tactic);
}
}

@ -20,7 +20,7 @@ class VisualizerController {
}
/**
* opens a visualisation page for the tactic specified by its identifier in the url.
* Opens a visualisation page for the tactic specified by its identifier in the url.
* @param int $id
* @param SessionHandle $session
* @return HttpResponse

@ -99,5 +99,4 @@ class TacticInfoGateway {
]);
return $stmnt->rowCount() == 1;
}
}

Loading…
Cancel
Save