enable history navigation
The previous implementation only looked at the URL (and state) during initialization. This allowed users to open a specific session via URL (e.g. when reloading the page). History navigation, however, was completely ignored. I.e. if the user pressed the back button the URL would change, but the content would remain the same. This has now been corrected.
This commit is contained in:
parent
b5ead20f0b
commit
de0fc8c917
8
index.js
8
index.js
@ -6,8 +6,12 @@ import BaseView from "/ui/base_view.js";
|
|||||||
m.route.prefix = "";
|
m.route.prefix = "";
|
||||||
m.route(document.body, "/", {
|
m.route(document.body, "/", {
|
||||||
"/": {
|
"/": {
|
||||||
render: function() {
|
render: function(vnode) {
|
||||||
return m(Layout, m(BaseView));
|
let newSession = vnode.attrs.newSession ?? false;
|
||||||
|
let session = newSession ? null : parseInt(vnode.attrs.session);
|
||||||
|
session = isNaN(session) ? null : session;
|
||||||
|
|
||||||
|
return m(Layout, m(BaseView, { newSession, session }));
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|||||||
@ -9,27 +9,22 @@ export default class BaseView {
|
|||||||
#model = new BaseViewModel();
|
#model = new BaseViewModel();
|
||||||
|
|
||||||
oninit() {
|
oninit() {
|
||||||
let id = m.route.param("session");
|
|
||||||
id = parseInt(id);
|
|
||||||
if (Number.isNaN(id))
|
|
||||||
id = null;
|
|
||||||
|
|
||||||
this.#model.current = id;
|
|
||||||
this.#model.loadAllSessions();
|
this.#model.loadAllSessions();
|
||||||
}
|
}
|
||||||
|
|
||||||
view() {
|
view(vnode) {
|
||||||
|
if (vnode.attrs.newSession)
|
||||||
|
this.#model.newSession();
|
||||||
|
else
|
||||||
|
this.#model.current = vnode.attrs.session;
|
||||||
|
|
||||||
if (this.#model.current !== null)
|
if (this.#model.current !== null)
|
||||||
return m(SessionView, {
|
return m(SessionView, { model: this.#model.current });
|
||||||
model: this.#model.current,
|
|
||||||
onDeselect: () => this.#model.current = null,
|
|
||||||
});
|
|
||||||
|
|
||||||
if (this.#model.sessions !== null)
|
if (this.#model.sessions !== null)
|
||||||
return m(SessionList, {
|
return m(SessionList, {
|
||||||
models: this.#model.sessions,
|
models: this.#model.sessions,
|
||||||
onSelect: (session) => this.#model.current = session,
|
onSelect: (session) => this.#model.current = session,
|
||||||
onNew: () => this.#model.newSession(),
|
|
||||||
});
|
});
|
||||||
|
|
||||||
return m("p", "Wart kurz, i lad grad die Spiele…");
|
return m("p", "Wart kurz, i lad grad die Spiele…");
|
||||||
@ -48,30 +43,32 @@ class BaseViewModel {
|
|||||||
if (value instanceof Session) {
|
if (value instanceof Session) {
|
||||||
this.#current = value;
|
this.#current = value;
|
||||||
this.#currentLoading = null;
|
this.#currentLoading = null;
|
||||||
m.route.set("/", { session: value.id });
|
|
||||||
|
|
||||||
} else if (typeof value === "number") {
|
} else if (typeof value === "number") {
|
||||||
if (value === this.#current?.id || value === this.#currentLoading)
|
if (value === this.#current?.id || value === this.#currentLoading)
|
||||||
return;
|
return;
|
||||||
this.#currentLoading = value;
|
this.#currentLoading = value;
|
||||||
m.route.set("/", { session: value });
|
|
||||||
SessionRepo
|
SessionRepo
|
||||||
.get(value)
|
.get(value)
|
||||||
.then((s) => {
|
.then((s) => {
|
||||||
if (this.#currentLoading === s?.id)
|
if (this.#currentLoading === s?.id)
|
||||||
this.#current = s;
|
this.#current = s;
|
||||||
})
|
})
|
||||||
|
.catch((e) => {
|
||||||
|
console.error("failed to load session: ", e);
|
||||||
|
})
|
||||||
.finally(() => {
|
.finally(() => {
|
||||||
|
m.redraw();
|
||||||
if (this.#currentLoading === value)
|
if (this.#currentLoading === value)
|
||||||
this.#currentLoading = null;
|
this.#currentLoading = null;
|
||||||
m.redraw();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
} else if (value === null) {
|
} else if (value === null) {
|
||||||
|
if (this.#current === null)
|
||||||
|
return;
|
||||||
this.#current = null;
|
this.#current = null;
|
||||||
this.#currentLoading = null;
|
this.#currentLoading = null;
|
||||||
this.loadAllSessions();
|
this.loadAllSessions();
|
||||||
m.route.set("/");
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
throw new TypeError("current session must be session or id or null");
|
throw new TypeError("current session must be session or id or null");
|
||||||
@ -96,13 +93,22 @@ class BaseViewModel {
|
|||||||
.then(() => {
|
.then(() => {
|
||||||
if (this.#currentLoading === BaseViewModel.#newSessionMarker) {
|
if (this.#currentLoading === BaseViewModel.#newSessionMarker) {
|
||||||
this.#current = session;
|
this.#current = session;
|
||||||
m.route.set("/", { session: session.id });
|
m.route.set("/", { session: session.id }, { replace: true });
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
.catch((e) => {
|
||||||
|
console.error("failed to create new session: ", e);
|
||||||
|
if (this.#currentLoading === BaseViewModel.#newSessionMarker)
|
||||||
|
m.route.set(
|
||||||
|
"/",
|
||||||
|
{ session: this.#current?.id ?? undefined },
|
||||||
|
{ replace: true });
|
||||||
|
else
|
||||||
|
m.redraw();
|
||||||
|
})
|
||||||
.finally(() => {
|
.finally(() => {
|
||||||
if (this.#currentLoading === BaseViewModel.#newSessionMarker)
|
if (this.#currentLoading === BaseViewModel.#newSessionMarker)
|
||||||
this.#currentLoading = null;
|
this.#currentLoading = null;
|
||||||
m.redraw();
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -6,12 +6,12 @@ import RoundView from "/ui/round.js";
|
|||||||
|
|
||||||
export default class SessionView {
|
export default class SessionView {
|
||||||
/** @param {{ attrs: { model: Session } }} param The session model to use. */
|
/** @param {{ attrs: { model: Session } }} param The session model to use. */
|
||||||
view({ attrs: { model, onDeselect } }) {
|
view({ attrs: { model } }) {
|
||||||
|
|
||||||
let res = model.result;
|
let res = model.result;
|
||||||
|
|
||||||
return m("article.session-view", [
|
return m("article.session-view", [
|
||||||
m("button", { onclick: () => onDeselect() }, "Zruck"),
|
m(m.route.Link, { href: "/", selector: "button" }, "Zruck"),
|
||||||
m("table", [
|
m("table", [
|
||||||
m("thead", [
|
m("thead", [
|
||||||
m("tr", [
|
m("tr", [
|
||||||
|
|||||||
@ -4,17 +4,32 @@ import Session from "/models/session.js";
|
|||||||
|
|
||||||
export default class SessionList {
|
export default class SessionList {
|
||||||
/** @param {{ attrs: { models: Session[] } }} param The sessions to show. */
|
/** @param {{ attrs: { models: Session[] } }} param The sessions to show. */
|
||||||
view({attrs: { models, onSelect, onNew } }) {
|
view({attrs: { models, onSelect } }) {
|
||||||
return m("section", [
|
return m("section", [
|
||||||
m("button", { onclick: () => onNew() }, "Neie Session"),
|
m(m.route.Link, {
|
||||||
|
href: "/",
|
||||||
|
selector: "button",
|
||||||
|
options: {
|
||||||
|
state: { newSession: true },
|
||||||
|
},
|
||||||
|
}, "Neie Session"),
|
||||||
m("ol", [
|
m("ol", [
|
||||||
models.map((s) => m("li", [
|
models.map((s) => m("li", [
|
||||||
m("button", { onclick: () => onSelect(s) }, [
|
m(
|
||||||
m("p", s.ourTeam !== "" ? s.ourTeam : "Unbnannts Team"),
|
m.route.Link,
|
||||||
m("p", s.theirTeam !== "" ? s.theirTeam : "Unbnannts Team"),
|
{
|
||||||
m("p", "•".repeat(s.result.ourPoints)),
|
href: "/",
|
||||||
m("p", "•".repeat(s.result.theirPoints)),
|
selector: "button",
|
||||||
])
|
params: { session: s.id },
|
||||||
|
onclick: () => onSelect(s),
|
||||||
|
},
|
||||||
|
[
|
||||||
|
m("p", s.ourTeam !== "" ? s.ourTeam : "Unbnannts Team"),
|
||||||
|
m("p", s.theirTeam !== "" ? s.theirTeam : "Unbnannts Team"),
|
||||||
|
m("p", "•".repeat(s.result.ourPoints)),
|
||||||
|
m("p", "•".repeat(s.result.theirPoints)),
|
||||||
|
],
|
||||||
|
),
|
||||||
]))
|
]))
|
||||||
])
|
])
|
||||||
]);
|
]);
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user