diff --git a/frontend/app/components/Header/HealthStatus/HealthStatus.tsx b/frontend/app/components/Header/HealthStatus/HealthStatus.tsx
index 317b36279..283ba6f21 100644
--- a/frontend/app/components/Header/HealthStatus/HealthStatus.tsx
+++ b/frontend/app/components/Header/HealthStatus/HealthStatus.tsx
@@ -22,6 +22,7 @@ export interface IServiceStats {
function HealthStatus() {
const healthResponseSaved = localStorage.getItem(healthResponseKey) || '{}';
const [healthResponse, setHealthResponse] = React.useState(JSON.parse(healthResponseSaved));
+ const [isError, setIsError] = React.useState(false);
const [isLoading, setIsLoading] = React.useState(false);
const lastAskedSaved = localStorage.getItem(lastAskedKey);
const [lastAsked, setLastAsked] = React.useState(lastAskedSaved);
@@ -36,6 +37,7 @@ function HealthStatus() {
setLastAsked(asked.toString());
} catch (e) {
console.error(e);
+ setIsError(true);
} finally {
setIsLoading(false);
}
@@ -51,7 +53,7 @@ function HealthStatus() {
}
}, []);
- const icon = healthResponse?.overallHealth ? 'pulse' : ('exclamation-circle-fill' as const);
+ const icon = !isError && healthResponse?.overallHealth ? 'pulse' : ('exclamation-circle-fill' as const);
return (
<>
@@ -71,6 +73,7 @@ function HealthStatus() {
isLoading={isLoading}
lastAsked={lastAsked}
setShowModal={setShowModal}
+ isError={isError}
/>
{showModal ? (
diff --git a/frontend/app/components/Header/HealthStatus/HealthWidget.tsx b/frontend/app/components/Header/HealthStatus/HealthWidget.tsx
index 50b4de76d..6a184f854 100644
--- a/frontend/app/components/Header/HealthStatus/HealthWidget.tsx
+++ b/frontend/app/components/Header/HealthStatus/HealthWidget.tsx
@@ -10,12 +10,14 @@ function HealthWidget({
isLoading,
lastAsked,
setShowModal,
+ isError,
}: {
healthResponse: { overallHealth: boolean; healthMap: Record };
getHealth: Function;
isLoading: boolean;
lastAsked: string | null;
setShowModal: (visible: boolean) => void;
+ isError?: boolean;
}) {
const [lastAskedDiff, setLastAskedDiff] = React.useState(0);
const healthOk = healthResponse?.overallHealth;
@@ -28,8 +30,8 @@ function HealthWidget({
setLastAskedDiff(diffInMinutes);
}, [lastAsked]);
- const title = healthOk ? 'All Systems Operational' : 'Service disruption';
- const icon = healthOk ? ('check-circle-fill' as const) : ('exclamation-circle-fill' as const);
+ const title = !isError && healthOk ? 'All Systems Operational' : 'Service disruption';
+ const icon = !isError && healthOk ? ('check-circle-fill' as const) : ('exclamation-circle-fill' as const);
const problematicServices = Object.values(healthResponse?.healthMap || {}).filter(
(service: Record) => !service.healthOk
@@ -65,10 +67,12 @@ function HealthWidget({
+ {isError && Error getting service health status
}
+
- {!healthOk ? (
+ {!isError && !healthOk ? (
<>
Observed installation Issue with the following
diff --git a/frontend/app/player/common/types.ts b/frontend/app/player/common/types.ts
index 7df4f6f6b..308ec0659 100644
--- a/frontend/app/player/common/types.ts
+++ b/frontend/app/player/common/types.ts
@@ -7,7 +7,7 @@ export interface Indexed {
}
export interface Moveable {
- move(time: number, isJump?: boolean): void
+ move(time: number): void
}
export interface Cleanable {
diff --git a/frontend/app/player/player/Animator.ts b/frontend/app/player/player/Animator.ts
index 9423b5785..55d38432c 100644
--- a/frontend/app/player/player/Animator.ts
+++ b/frontend/app/player/player/Animator.ts
@@ -1,4 +1,5 @@
import type { Store, Moveable, Interval } from '../common/types';
+import MessageManager from 'App/player/web/MessageManager'
const fps = 60
const performance: { now: () => number } = window.performance || { now: Date.now.bind(Date) }
@@ -54,18 +55,18 @@ export default class Animator {
private animationFrameRequestId: number = 0
- constructor(private store: Store
, private mm: Moveable) {
+ constructor(private store: Store, private mm: MessageManager) {
// @ts-ignore
window.playerJump = this.jump.bind(this)
}
- private setTime(time: number, isJump?: boolean) {
+ private setTime(time: number) {
this.store.update({
time,
completed: false,
})
- this.mm.move(time, isJump)
+ this.mm.move(time)
}
private startAnimation() {
@@ -183,11 +184,11 @@ export default class Animator {
jump = (time: number) => {
if (this.store.get().playing) {
cancelAnimationFrame(this.animationFrameRequestId)
- this.setTime(time, true)
+ this.setTime(time)
this.startAnimation()
this.store.update({ livePlay: time === this.store.get().endTime })
} else {
- this.setTime(time, true)
+ this.setTime(time)
this.store.update({ livePlay: time === this.store.get().endTime })
}
}
diff --git a/frontend/app/player/web/MessageManager.ts b/frontend/app/player/web/MessageManager.ts
index 2772ccbd2..b343eef96 100644
--- a/frontend/app/player/web/MessageManager.ts
+++ b/frontend/app/player/web/MessageManager.ts
@@ -289,7 +289,7 @@ export default class MessageManager {
this.activityManager = new ActivityManager(this.session.duration.milliseconds);
}
- move(t: number, isJump?: boolean, index?: number): void {
+ move(t: number, index?: number): void {
const stateToUpdate: Partial = {};
/* == REFACTOR_ME == */
const lastLoadedLocationMsg = this.loadedLocationManager.moveGetLast(t, index);
@@ -339,7 +339,7 @@ export default class MessageManager {
if (!!lastResize) {
this.setSize(lastResize)
}
- this.pagesManager.moveReady(t, isJump).then(() => {
+ this.pagesManager.moveReady(t).then(() => {
const lastScroll = this.scrollManager.moveGetLast(t, index);
if (!!lastScroll && this.screen.window) {
diff --git a/frontend/app/player/web/WebLivePlayer.ts b/frontend/app/player/web/WebLivePlayer.ts
index 709692d20..7ed1e3400 100644
--- a/frontend/app/player/web/WebLivePlayer.ts
+++ b/frontend/app/player/web/WebLivePlayer.ts
@@ -56,7 +56,7 @@ export default class WebLivePlayer extends WebPlayer {
const bytes = await requestEFSDom(this.session.sessionId)
const fileReader = new MFileReader(bytes, this.session.startedAt)
for (let msg = fileReader.readNext();msg !== null;msg = fileReader.readNext()) {
- this.messageManager.distributeMessage(msg, msg._index)
+ this.messageManager.distributeMessage(msg)
}
this.wpState.update({
liveTimeTravel: true,
diff --git a/frontend/app/player/web/managers/DOM/DOMManager.ts b/frontend/app/player/web/managers/DOM/DOMManager.ts
index a5c2f2c2f..d54781028 100644
--- a/frontend/app/player/web/managers/DOM/DOMManager.ts
+++ b/frontend/app/player/web/managers/DOM/DOMManager.ts
@@ -142,7 +142,7 @@ export default class DOMManager extends ListWalker {
private setNodeAttribute(msg: { id: number, name: string, value: string }) {
let { name, value } = msg;
const vn = this.vElements.get(msg.id)
- if (!vn) { logger.error("Node not found", msg); return }
+ if (!vn) { logger.error("SetNodeAttribute: Node not found", msg); return }
if (vn.node.tagName === "INPUT" && name === "name") {
// Otherwise binds local autocomplete values (maybe should ignore on the tracker level)
@@ -169,7 +169,7 @@ export default class DOMManager extends ListWalker {
this.removeBodyScroll(msg.id, vn)
}
- private applyMessage = (msg: Message, isJump?: boolean): Promise | undefined => {
+ private applyMessage = (msg: Message): Promise | undefined => {
let vn: VNode | undefined
let doc: Document | null
let styleSheet: CSSStyleSheet | PostponedStyleSheet | undefined
@@ -230,14 +230,14 @@ export default class DOMManager extends ListWalker {
return
case MType.RemoveNode:
vn = this.vElements.get(msg.id) || this.vTexts.get(msg.id)
- if (!vn) { logger.error("Node not found", msg); return }
- if (!vn.parentNode) { logger.error("Parent node not found", msg); return }
+ if (!vn) { logger.error("RemoveNode: Node not found", msg); return }
+ if (!vn.parentNode) { logger.error("RemoveNode: Parent node not found", msg); return }
vn.parentNode.removeChild(vn)
this.vElements.delete(msg.id)
this.vTexts.delete(msg.id)
return
case MType.SetNodeAttribute:
- if (isJump && msg.name === 'href') this.attrsBacktrack.push(msg)
+ if (msg.name === 'href') this.attrsBacktrack.push(msg)
else this.setNodeAttribute(msg)
return
case MType.StringDict:
@@ -247,7 +247,7 @@ export default class DOMManager extends ListWalker {
this.stringDict[msg.nameKey] === undefined && logger.error("No dictionary key for msg 'name': ", msg)
this.stringDict[msg.valueKey] === undefined && logger.error("No dictionary key for msg 'value': ", msg)
if (this.stringDict[msg.nameKey] === undefined || this.stringDict[msg.valueKey] === undefined ) { return }
- if (isJump && this.stringDict[msg.nameKey] === 'href') this.attrsBacktrack.push(msg)
+ if (this.stringDict[msg.nameKey] === 'href') this.attrsBacktrack.push(msg)
else {
this.setNodeAttribute({
id: msg.id,
@@ -258,12 +258,12 @@ export default class DOMManager extends ListWalker {
return
case MType.RemoveNodeAttribute:
vn = this.vElements.get(msg.id)
- if (!vn) { logger.error("Node not found", msg); return }
+ if (!vn) { logger.error("RemoveNodeAttribute: Node not found", msg); return }
vn.removeAttribute(msg.name)
return
case MType.SetInputValue:
vn = this.vElements.get(msg.id)
- if (!vn) { logger.error("Node not found", msg); return }
+ if (!vn) { logger.error("SetInoputValue: Node not found", msg); return }
const nodeWithValue = vn.node
if (!(nodeWithValue instanceof HTMLInputElement
|| nodeWithValue instanceof HTMLTextAreaElement
@@ -283,13 +283,13 @@ export default class DOMManager extends ListWalker {
return
case MType.SetInputChecked:
vn = this.vElements.get(msg.id)
- if (!vn) { logger.error("Node not found", msg); return }
+ if (!vn) { logger.error("SetInputChecked: Node not found", msg); return }
(vn.node as HTMLInputElement).checked = msg.checked
return
case MType.SetNodeData:
case MType.SetCssData: // mbtodo: remove css transitions when timeflow is not natural (on jumps)
vn = this.vTexts.get(msg.id)
- if (!vn) { logger.error("Node not found", msg); return }
+ if (!vn) { logger.error("SetCssData: Node not found", msg); return }
vn.setData(msg.data)
if (vn.node instanceof HTMLStyleElement) {
doc = this.screen.document
@@ -304,7 +304,7 @@ export default class DOMManager extends ListWalker {
// @deprecated since 4.0.2 in favor of adopted_ss_insert/delete_rule + add_owner as being common case for StyleSheets
case MType.CssInsertRule:
vn = this.vElements.get(msg.id)
- if (!vn) { logger.error("Node not found", msg); return }
+ if (!vn) { logger.error("CssInsertRule: Node not found", msg); return }
if (!(vn instanceof VStyleElement)) {
logger.warn("Non-style node in CSS rules message (or sheet is null)", msg, vn);
return
@@ -313,7 +313,7 @@ export default class DOMManager extends ListWalker {
return
case MType.CssDeleteRule:
vn = this.vElements.get(msg.id)
- if (!vn) { logger.error("Node not found", msg); return }
+ if (!vn) { logger.error("CssDeleteRule: Node not found", msg); return }
if (!(vn instanceof VStyleElement)) {
logger.warn("Non-style node in CSS rules message (or sheet is null)", msg, vn);
return
@@ -324,7 +324,7 @@ export default class DOMManager extends ListWalker {
case MType.CreateIFrameDocument:
vn = this.vElements.get(msg.frameID)
- if (!vn) { logger.error("Node not found", msg); return }
+ if (!vn) { logger.error("CreateIFrameDocument: Node not found", msg); return }
vn.enforceInsertion()
const host = vn.node
if (host instanceof HTMLIFrameElement) {
@@ -384,7 +384,7 @@ export default class DOMManager extends ListWalker {
if (!vn) {
// non-constructed case
vn = this.vElements.get(msg.id)
- if (!vn) { logger.error("Node not found", msg); return }
+ if (!vn) { logger.error("AdoptedSsAddOwner: Node not found", msg); return }
if (!(vn instanceof VStyleElement)) { logger.error("Non-style owner", msg); return }
this.ppStyleSheets.set(msg.sheetID, new PostponedStyleSheet(vn.node))
return
@@ -411,13 +411,13 @@ export default class DOMManager extends ListWalker {
return
}
vn = this.vRoots.get(msg.id)
- if (!vn) { logger.error("Node not found", msg); return }
+ if (!vn) { logger.error("AdoptedSsRemoveOwner: Node not found", msg); return }
//@ts-ignore
vn.node.adoptedStyleSheets = [...vn.node.adoptedStyleSheets].filter(s => s !== styleSheet)
return
case MType.LoadFontFace:
vn = this.vRoots.get(msg.parentID)
- if (!vn) { logger.error("Node not found", msg); return }
+ if (!vn) { logger.error("LoadFontFace: Node not found", msg); return }
if (vn instanceof VShadowRoot) { logger.error(`Node ${vn} expected to be a Document`, msg); return }
let descr: Object
try {
@@ -460,7 +460,7 @@ export default class DOMManager extends ListWalker {
}
}
- async moveReady(t: number, isJump?: boolean): Promise {
+ async moveReady(t: number): Promise {
// MBTODO (back jump optimisation):
// - store intemediate virtual dom state
// - cancel previous moveReady tasks (is it possible?) if new timestamp is less
@@ -474,16 +474,13 @@ export default class DOMManager extends ListWalker {
* */
// http://0.0.0.0:3333/5/session/8452905874437457
// 70 iframe, 8 create element - STYLE tag
- await this.moveWait(t, (msg) => {
- this.applyMessage(msg, isJump)
- })
+ await this.moveWait(t, this.applyMessage)
+
+ this.attrsBacktrack.forEach(msg => {
+ this.applyBacktrack(msg)
+ })
+ this.attrsBacktrack = []
- if (isJump) {
- this.attrsBacktrack.forEach(msg => {
- this.applyBacktrack(msg)
- })
- this.attrsBacktrack = []
- }
this.vRoots.forEach(rt => rt.applyChanges()) // MBTODO (optimisation): affected set
// Thinkabout (read): css preload
// What if we go back before it is ready? We'll have two handlres?
diff --git a/frontend/app/player/web/managers/PagesManager.ts b/frontend/app/player/web/managers/PagesManager.ts
index b30f40372..dbc64bb72 100644
--- a/frontend/app/player/web/managers/PagesManager.ts
+++ b/frontend/app/player/web/managers/PagesManager.ts
@@ -33,14 +33,14 @@ export default class PagesManager extends ListWalker {
this.forEach(page => page.sort(comparator))
}
- moveReady(t: number, isJump?: boolean): Promise {
+ moveReady(t: number): Promise {
const requiredPage = this.moveGetLast(t)
if (requiredPage != null) {
this.currentPage = requiredPage
this.currentPage.reset() // Otherwise it won't apply create_document
}
if (this.currentPage != null) {
- return this.currentPage.moveReady(t, isJump)
+ return this.currentPage.moveReady(t)
}
return Promise.resolve()
}
diff --git a/frontend/app/services/HealthService.ts b/frontend/app/services/HealthService.ts
index 019863bb3..7d2b3cc7f 100644
--- a/frontend/app/services/HealthService.ts
+++ b/frontend/app/services/HealthService.ts
@@ -5,6 +5,5 @@ export default class HealthService extends BaseService {
return this.client.get('/health')
.then(r => r.json())
.then(j => j.data || {})
- .catch(Promise.reject)
}
}
\ No newline at end of file