mirror of
https://github.com/monkeytypegame/monkeytype.git
synced 2024-09-20 07:16:17 +08:00
feat: last signed out result modal
the website will now show the last signed out result and ask the user if they want to save or discard it (instead of always saving)
This commit is contained in:
parent
ddebf57454
commit
7306cf8a9f
|
@ -4,6 +4,44 @@
|
|||
</div>
|
||||
</dialog>
|
||||
|
||||
<dialog id="lastSignedOutResult" class="modalWrapper hidden">
|
||||
<div class="modal">
|
||||
<div class="title">Last signed out result</div>
|
||||
<div class="question">Would you like to save it?</div>
|
||||
<div class="divider"></div>
|
||||
<div class="result">
|
||||
<div class="group wpm">
|
||||
<div class="sub">wpm</div>
|
||||
<div class="val">-</div>
|
||||
</div>
|
||||
<div class="group acc">
|
||||
<div class="sub">accuracy</div>
|
||||
<div class="val">-</div>
|
||||
</div>
|
||||
<div class="group raw">
|
||||
<div class="sub">raw</div>
|
||||
<div class="val">-</div>
|
||||
</div>
|
||||
<div class="group con">
|
||||
<div class="sub">consistency</div>
|
||||
<div class="val">-</div>
|
||||
</div>
|
||||
<div class="group chardata">
|
||||
<div class="sub">characters</div>
|
||||
<div class="val">-</div>
|
||||
</div>
|
||||
<div class="group testType">
|
||||
<div class="sub">test type</div>
|
||||
<div class="val">-</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="buttons">
|
||||
<button class="save">save</button>
|
||||
<button class="discard">discard</button>
|
||||
</div>
|
||||
</div>
|
||||
</dialog>
|
||||
|
||||
<dialog id="devOptionsModal" class="modalWrapper hidden">
|
||||
<div class="modal">
|
||||
<div class="title">Dev options</div>
|
||||
|
|
|
@ -635,6 +635,45 @@ body.darkMode {
|
|||
}
|
||||
}
|
||||
|
||||
#lastSignedOutResult {
|
||||
.modal {
|
||||
max-width: 600px;
|
||||
|
||||
.buttons {
|
||||
display: flex;
|
||||
flex-direction: row-reverse;
|
||||
gap: 0.5rem;
|
||||
button {
|
||||
flex-grow: 1;
|
||||
}
|
||||
}
|
||||
.result {
|
||||
display: grid;
|
||||
gap: 0.5rem;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
}
|
||||
.divider {
|
||||
background: var(--sub-alt-color);
|
||||
width: 100%;
|
||||
height: 0.25rem;
|
||||
border-radius: var(--roundness);
|
||||
}
|
||||
.group {
|
||||
.sub {
|
||||
font-size: 0.75em;
|
||||
color: var(--sub-color);
|
||||
}
|
||||
&.testType {
|
||||
grid-column: 1;
|
||||
}
|
||||
&.wpm,
|
||||
&.acc {
|
||||
font-size: 2em;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#devOptionsModal {
|
||||
.modal {
|
||||
max-width: 400px;
|
||||
|
|
|
@ -15,6 +15,7 @@ import * as LoginPage from "../pages/login";
|
|||
import * as ResultFilters from "../elements/account/result-filters";
|
||||
import * as TagController from "./tag-controller";
|
||||
import * as RegisterCaptchaModal from "../modals/register-captcha";
|
||||
import * as LastSignedOutResultModal from "../modals/last-signed-out-result";
|
||||
import * as URLHandler from "../utils/url-handler";
|
||||
import * as Account from "../pages/account";
|
||||
import * as Alerts from "../elements/alerts";
|
||||
|
@ -45,8 +46,6 @@ import * as ConnectionState from "../states/connection";
|
|||
import { navigate } from "./route-controller";
|
||||
import { getHtmlByUserFlags } from "./user-flag-controller";
|
||||
|
||||
let signedOutThisSession = false;
|
||||
|
||||
export const gmailProvider = new GoogleAuthProvider();
|
||||
export const githubProvider = new GithubAuthProvider();
|
||||
|
||||
|
@ -209,18 +208,9 @@ export async function loadUser(user: UserType): Promise<void> {
|
|||
|
||||
// showFavouriteThemesAtTheTop();
|
||||
|
||||
if (TestLogic.notSignedInLastResult !== null && !signedOutThisSession) {
|
||||
if (TestLogic.notSignedInLastResult !== null) {
|
||||
TestLogic.setNotSignedInUid(user.uid);
|
||||
|
||||
const response = await Ape.results.save(TestLogic.notSignedInLastResult);
|
||||
|
||||
if (response.status !== 200) {
|
||||
Notifications.add("Failed to save last result: " + response.message, -1);
|
||||
return;
|
||||
}
|
||||
|
||||
TestLogic.clearNotSignedInResult();
|
||||
Notifications.add("Last test result saved", 1);
|
||||
LastSignedOutResultModal.show();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -647,7 +637,6 @@ $("header .signInOut").on("click", () => {
|
|||
}
|
||||
if (isAuthenticated()) {
|
||||
signOut();
|
||||
signedOutThisSession = true;
|
||||
} else {
|
||||
navigate("/login");
|
||||
}
|
||||
|
|
147
frontend/src/ts/modals/last-signed-out-result.ts
Normal file
147
frontend/src/ts/modals/last-signed-out-result.ts
Normal file
|
@ -0,0 +1,147 @@
|
|||
import AnimatedModal from "../utils/animated-modal";
|
||||
import Ape from "../ape";
|
||||
import * as TestLogic from "../test/test-logic";
|
||||
import * as Notifications from "../elements/notifications";
|
||||
import { CompletedEvent } from "@monkeytype/shared-types";
|
||||
|
||||
function reset(): void {
|
||||
(modal.getModal().querySelector(".result") as HTMLElement).innerHTML = `
|
||||
<div class="group wpm">
|
||||
<div class="sub">wpm</div>
|
||||
<div class="val">-</div>
|
||||
</div>
|
||||
<div class="group acc">
|
||||
<div class="sub">accuracy</div>
|
||||
<div class="val">-</div>
|
||||
</div>
|
||||
<div class="group raw">
|
||||
<div class="sub">raw</div>
|
||||
<div class="val">-</div>
|
||||
</div>
|
||||
<div class="group con">
|
||||
<div class="sub">consistency</div>
|
||||
<div class="val">-</div>
|
||||
</div>
|
||||
<div class="group chardata">
|
||||
<div class="sub">characters</div>
|
||||
<div class="val">-</div>
|
||||
</div>
|
||||
<div class="group testType">
|
||||
<div class="sub">test type</div>
|
||||
<div class="val">-</div>
|
||||
</div>`;
|
||||
}
|
||||
|
||||
function fillData(): void {
|
||||
//safe because we check if it exists before showing the modal
|
||||
const r = TestLogic.notSignedInLastResult as CompletedEvent;
|
||||
|
||||
// const r: CompletedEvent = {
|
||||
// wpm: 100,
|
||||
// acc: 100,
|
||||
// rawWpm: 100,
|
||||
// consistency: 100,
|
||||
// mode: "time",
|
||||
// mode2: "60",
|
||||
// numbers: true,
|
||||
// punctuation: true,
|
||||
// difficulty: "master",
|
||||
// language: "english",
|
||||
// blindMode: true,
|
||||
// lazyMode: true,
|
||||
// funbox: "read_ahead",
|
||||
// tags: ["asdf", "sdfsdf"],
|
||||
// charStats: [10, 10, 10, 10],
|
||||
// };
|
||||
|
||||
fillGroup("wpm", r.wpm);
|
||||
fillGroup("acc", r.acc + "%");
|
||||
fillGroup("raw", r.rawWpm);
|
||||
fillGroup("con", r.consistency + "%");
|
||||
fillGroup("chardata", r.charStats.join("/"));
|
||||
|
||||
let tt = r.mode + " " + r.mode2;
|
||||
|
||||
tt += "<br>" + r.language;
|
||||
|
||||
if (r.numbers) tt += "<br>numbers";
|
||||
if (r.punctuation) tt += "<br>punctuation";
|
||||
if (r.blindMode) tt += "<br>blind";
|
||||
if (r.lazyMode) tt += "<br>lazy";
|
||||
if (r.funbox !== "none") {
|
||||
tt += "<br>" + r.funbox.replace(/_/g, " ").replace(/#/g, ", ");
|
||||
}
|
||||
if (r.difficulty !== "normal") tt += "<br>" + r.difficulty;
|
||||
if (r.tags.length > 0) tt += "<br>" + r.tags.length + " tags";
|
||||
|
||||
fillGroup("testType", tt, true);
|
||||
}
|
||||
|
||||
function fillGroup(
|
||||
groupClass: string,
|
||||
text: string | number,
|
||||
html = false
|
||||
): void {
|
||||
if (html) {
|
||||
$(modal.getModal()).find(`.group.${groupClass} .val`).html(`${text}`);
|
||||
} else {
|
||||
$(modal.getModal()).find(`.group.${groupClass} .val`).text(text);
|
||||
}
|
||||
}
|
||||
|
||||
export function show(): void {
|
||||
if (!TestLogic.notSignedInLastResult) {
|
||||
Notifications.add(
|
||||
"Failed to show last signed out result modal: no last result",
|
||||
-1
|
||||
);
|
||||
return;
|
||||
}
|
||||
reset();
|
||||
void modal.show({
|
||||
beforeAnimation: async (): Promise<void> => {
|
||||
fillData();
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
function hide(): void {
|
||||
void modal.hide();
|
||||
}
|
||||
|
||||
async function saveLastResult(): Promise<void> {
|
||||
//safe because we check if it exists before showing the modal
|
||||
const response = await Ape.results.save(
|
||||
TestLogic.notSignedInLastResult as CompletedEvent
|
||||
);
|
||||
if (response.status !== 200) {
|
||||
Notifications.add("Failed to save last result: " + response.message, -1);
|
||||
return;
|
||||
}
|
||||
|
||||
TestLogic.clearNotSignedInResult();
|
||||
Notifications.add(
|
||||
`Last test result saved ${response.data?.isPb ? `(new pb!)` : ""}`,
|
||||
1
|
||||
);
|
||||
}
|
||||
|
||||
const modal = new AnimatedModal({
|
||||
dialogId: "lastSignedOutResult",
|
||||
setup: async (modalEl): Promise<void> => {
|
||||
modalEl
|
||||
.querySelector("button.save")
|
||||
?.addEventListener("click", async (e) => {
|
||||
void saveLastResult();
|
||||
hide();
|
||||
});
|
||||
modalEl.querySelector("button.discard")?.addEventListener("click", (e) => {
|
||||
TestLogic.clearNotSignedInResult();
|
||||
Notifications.add("Last test result discarded", 0);
|
||||
hide();
|
||||
});
|
||||
},
|
||||
customWrapperClickHandler: (): void => {
|
||||
//do nothing
|
||||
},
|
||||
});
|
Loading…
Reference in a new issue