change(ui): remove isjump, improve error logging for dommanager; improve healthstatus API display
This commit is contained in:
parent
d53de951ff
commit
a4a2089698
9 changed files with 46 additions and 42 deletions
|
|
@ -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 (
|
||||
<>
|
||||
<div className={'relative group h-full hover:bg-figmaColors-secondary-outlined-hover-background'}>
|
||||
|
|
@ -71,6 +73,7 @@ function HealthStatus() {
|
|||
isLoading={isLoading}
|
||||
lastAsked={lastAsked}
|
||||
setShowModal={setShowModal}
|
||||
isError={isError}
|
||||
/>
|
||||
</div>
|
||||
{showModal ? (
|
||||
|
|
|
|||
|
|
@ -10,12 +10,14 @@ function HealthWidget({
|
|||
isLoading,
|
||||
lastAsked,
|
||||
setShowModal,
|
||||
isError,
|
||||
}: {
|
||||
healthResponse: { overallHealth: boolean; healthMap: Record<string, IServiceStats> };
|
||||
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<string, any>) => !service.healthOk
|
||||
|
|
@ -65,10 +67,12 @@ function HealthWidget({
|
|||
<Icon name={'arrow-repeat'} size={16} color={'main'} />
|
||||
</div>
|
||||
</div>
|
||||
{isError && <div className={'text-secondary text-sm'}>Error getting service health status</div>}
|
||||
|
||||
<div className={'divider w-full border border-b-light-gray'} />
|
||||
|
||||
<div className={'w-full'}>
|
||||
{!healthOk ? (
|
||||
{!isError && !healthOk ? (
|
||||
<>
|
||||
<div className={'text-secondary pb-2'}>
|
||||
Observed installation Issue with the following
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ export interface Indexed {
|
|||
}
|
||||
|
||||
export interface Moveable {
|
||||
move(time: number, isJump?: boolean): void
|
||||
move(time: number): void
|
||||
}
|
||||
|
||||
export interface Cleanable {
|
||||
|
|
|
|||
|
|
@ -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<GetState>, private mm: Moveable) {
|
||||
constructor(private store: Store<GetState>, 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 })
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<State> = {};
|
||||
/* == 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) {
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -142,7 +142,7 @@ export default class DOMManager extends ListWalker<Message> {
|
|||
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<Message> {
|
|||
this.removeBodyScroll(msg.id, vn)
|
||||
}
|
||||
|
||||
private applyMessage = (msg: Message, isJump?: boolean): Promise<any> | undefined => {
|
||||
private applyMessage = (msg: Message): Promise<any> | undefined => {
|
||||
let vn: VNode | undefined
|
||||
let doc: Document | null
|
||||
let styleSheet: CSSStyleSheet | PostponedStyleSheet | undefined
|
||||
|
|
@ -230,14 +230,14 @@ export default class DOMManager extends ListWalker<Message> {
|
|||
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<Message> {
|
|||
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<Message> {
|
|||
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<Message> {
|
|||
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<Message> {
|
|||
// @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<Message> {
|
|||
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<Message> {
|
|||
|
||||
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<Message> {
|
|||
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<Message> {
|
|||
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<Message> {
|
|||
}
|
||||
}
|
||||
|
||||
async moveReady(t: number, isJump?: boolean): Promise<void> {
|
||||
async moveReady(t: number): Promise<void> {
|
||||
// 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<Message> {
|
|||
* */
|
||||
// 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?
|
||||
|
|
|
|||
|
|
@ -33,14 +33,14 @@ export default class PagesManager extends ListWalker<DOMManager> {
|
|||
this.forEach(page => page.sort(comparator))
|
||||
}
|
||||
|
||||
moveReady(t: number, isJump?: boolean): Promise<void> {
|
||||
moveReady(t: number): Promise<void> {
|
||||
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()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue