Feat/62 logger (#79)

* feat/62-logger request log data in app
* feat/62-logger refact osc integration
* feat/62-logger feedback on osc
* feat/62-logger refact broadcast on triggers
* feat/62-logger log triggers
* feat/62-logger add link to studio
* feat/62-logger replace toasts with logger context
* feat/62-logger style improvements
* feat/62-logger refactor code duplications
* feat/62-logger cleanup and version bump
This commit is contained in:
Carlos Valente
2021-12-25 19:39:40 +01:00
committed by GitHub
parent 160ccabebc
commit 9fc154955a
46 changed files with 3830 additions and 598 deletions
@@ -0,0 +1,24 @@
import PropTypes from "prop-types";
import style from "../../../features/info/Info.module.scss";
import {Icon} from "@chakra-ui/react";
import {FiChevronUp} from "react-icons/fi";
export default function CollapseBar(props) {
const {title = 'Collapse bar', isCollapsed = false, onClick}= props;
return(
<div className={style.header}>
{title}
<Icon
className={isCollapsed ? style.moreCollapsed : style.moreExpanded}
as={FiChevronUp}
onClick={onClick}
/>
</div>
)
}
CollapseBar.propTypes = {
title: PropTypes.string,
isCollapsed: PropTypes.bool,
onClick: PropTypes.func,
}
@@ -0,0 +1,17 @@
.header,
.header__roll {
padding: 0;
margin: 0;
font-size: 0.9em;
color: #ccc;
display: flex;
justify-content: space-between;
}
.header {
color: #ccc;
}
.header__roll {
color: #2b6cb0;
}
@@ -1,6 +1,9 @@
import React from 'react';
import { LoggingContext } from '../../../app/context/LoggingContext';
class ErrorBoundary extends React.Component {
static contextType = LoggingContext;
constructor(props) {
super(props);
this.state = { error: null, errorInfo: null };
@@ -17,15 +20,11 @@ class ErrorBoundary extends React.Component {
errorInfo: info,
});
// TODO: Log the error to an error reporting service
this.logErrorToServices(error.toString(), info.componentStack);
this.context.emitError(error.toString());
}
// A fake logging service.
logErrorToServices = console.log;
render() {
if (this.state.errorMessage) {
// You can render any custom fallback UI
return <p>:/</p>;
}
return this.props.children;
@@ -1,23 +1,26 @@
import EditableTimer from 'common/input/EditableTimer';
import { showWarningToast } from 'common/helpers/toastManager';
import { useContext } from 'react';
import { LoggingContext } from '../../../app/context/LoggingContext';
export default function EventTimes(props) {
const { actionHandler, delay, timeStart, timeEnd } = props;
const { emitWarning } = useContext(LoggingContext);
const handleValidate = (entry, v) => {
// we dont inforce validation here
// we dont enforce validation here
if (v == null || timeStart == null || timeEnd == null) return true;
if (timeStart === 0) return true;
let validate = { value: true, catch: '' };
if (entry === 'timeStart' && v > timeEnd)
if (entry === 'timeStart' && v > timeEnd) {
validate.catch = 'Start time later than end time';
else if (entry === 'timeEnd' && v < timeStart)
} else if (entry === 'timeEnd' && v < timeStart) {
validate.catch = 'End time earlier than start time';
}
if (validate.catch !== '')
showWarningToast('Time Input Warning', validate.catch);
emitWarning(`Time Input Warning: ${validate.catch}`);
return validate.value;
};
@@ -1,6 +1,7 @@
import EditableTimer from 'common/input/EditableTimer';
import { showWarningToast } from 'common/helpers/toastManager';
import { stringFromMillis } from 'common/utils/dateConfig';
import { stringFromMillis } from 'ontime-server/utils/time';
import { useContext } from 'react';
import { LoggingContext } from '../../../app/context/LoggingContext';
const label = {
fontSize: '0.75em',
@@ -83,6 +84,8 @@ const Times = (props) => {
export default function EventTimesVertical(props) {
const { delay, timeStart, timeEnd, duration } = props;
const { emitWarning } = useContext(LoggingContext);
const handleValidate = (entry, v) => {
// we dont enforce validation here
@@ -90,32 +93,36 @@ export default function EventTimesVertical(props) {
if (timeStart === 0) return true;
let validate = { value: true, catch: '' };
if (entry === 'timeStart' && v > timeEnd)
if (entry === 'timeStart' && v > timeEnd) {
validate.catch = 'Start time later than end time';
else if (entry === 'timeEnd' && v < timeStart)
} else if (entry === 'timeEnd' && v < timeStart) {
validate.catch = 'End time earlier than start time';
}
if (validate.catch !== '')
showWarningToast('Time Input Warning', validate.catch);
if (validate.catch !== '') {
emitWarning(`Time Input Warning: ${validate.catch}`);
}
return validate.value;
};
return (delay != null) & (delay > 0) ? (
<TimesDelayed
handleValidate={handleValidate}
actionHandler={props.actionHandler}
delay={delay}
timeStart={timeStart}
timeEnd={timeEnd}
duration={duration}
/>
) : (
<Times
handleValidate={handleValidate}
actionHandler={props.actionHandler}
timeStart={timeStart}
timeEnd={timeEnd}
duration={duration}
/>
);
return (
(delay != null) && (delay > 0) ? (
<TimesDelayed
handleValidate={handleValidate}
actionHandler={props.actionHandler}
delay={delay}
timeStart={timeStart}
timeEnd={timeEnd}
duration={duration}
/>
) : (
<Times
handleValidate={handleValidate}
actionHandler={props.actionHandler}
timeStart={timeStart}
timeEnd={timeEnd}
duration={duration}
/>
)
)
}
@@ -1,4 +1,4 @@
import { stringFromMillis } from 'common/utils/dateConfig';
import { stringFromMillis } from 'ontime-server/utils/time';
import style from './Paginator.module.css';
export default function TodayItem(props) {
const { selected, timeStart, timeEnd, title, backstageEvent } = props;
@@ -19,7 +19,7 @@ export default function TodayItem(props) {
}`}
>{`${start} · ${end}`}</div>
<div className={style.entryTitle}>{title}</div>
{backstageEvent && <div className={style.backstageInd}></div>}
{backstageEvent && <div className={style.backstageInd}/>}
</div>
);
}
@@ -1,28 +0,0 @@
import { createStandaloneToast } from '@chakra-ui/react';
const toast = createStandaloneToast();
// const customToast = createStandaloneToast({ theme: yourCustomTheme })
// error toast
export const showErrorToast = (title, description) => {
toast({
title: title,
description: description,
position: 'top-left',
variant: 'subtle',
status: 'error',
isClosable: true,
});
};
// warning toast
export const showWarningToast = (title, description) => {
toast({
title: title,
description: description,
position: 'top-left',
variant: 'subtle',
status: 'warning',
isClosable: true,
});
};
+6 -5
View File
@@ -1,15 +1,16 @@
import { Editable, EditableInput, EditablePreview } from '@chakra-ui/editable';
import { useEffect, useState } from 'react';
import { useContext, useEffect, useState } from 'react';
import {
isTimeString,
stringFromMillis,
timeStringToMillis,
} from '../utils/dateConfig';
import { showErrorToast } from '../helpers/toastManager';
import { stringFromMillis } from 'ontime-server/utils/time';
import style from './EditableTimer.module.css';
import { LoggingContext } from '../../app/context/LoggingContext';
export default function EditableTimer(props) {
const { name, actionHandler, time, delay, validate } = props;
const { emitError } = useContext(LoggingContext);
const [value, setValue] = useState('');
// prepare time fields
@@ -18,9 +19,9 @@ export default function EditableTimer(props) {
try {
setValue(stringFromMillis(time + delay));
} catch (error) {
showErrorToast('Error parsing date', error.text);
emitError(`Unable to parse date: ${error.text}`);
}
}, [time, delay]);
}, [time, delay, emitError]);
const validateValue = (value) => {
const success = handleSubmit(value);
+1 -31
View File
@@ -4,37 +4,7 @@ export const timeFormatSeconds = 'HH:mm:ss';
const mts = 1000; // millis to seconds
const mtm = 1000 * 60; // millis to minutes
const mth = 1000 * 60 * 60; // millis to hours
const mtd = 1000 * 60 * 60 * 24; // millis to days
/**
* @description Converts milliseconds to string representing time
* @param {number} ms - time in milliseconds
* @param {boolean} showSeconds - wether to show the seconds
* @param {string} delim - character between HH MM SS
* @param {string} ifNull - what to return if value is null
* @returns {string} String representing time 00:12:02
*/
// This is shared and tested in backend in time.js
export const stringFromMillis = (
ms,
showSeconds = true,
delim = ':',
ifNull = '...'
) => {
if (ms === null || isNaN(ms)) return ifNull;
const isNegative = ms < 0 ? '-' : '';
const showWith0 = (value) => (value < 10 ? `0${value}` : value);
const hours = showWith0(Math.floor(((ms / mth) % 60) % 24));
const minutes = showWith0(Math.floor((ms / mtm) % 60));
const seconds = showWith0(Math.floor((ms / mts) % 60));
return showSeconds
? `${isNegative}${
parseInt(hours) ? `${hours}${delim}` : `00${delim}`
}${minutes}${delim}${seconds}`
: `${isNegative}${parseInt(hours) ? `${hours}` : '00'}${delim}${minutes}`;
};
/**
* another go at simpler string formatting (counters)
@@ -79,7 +49,7 @@ export const millisToMinutes = (millis) => {
};
/**
* @description Converts timestring to milliseconds
* @description Converts timestring to milliseconds
* @param {string} string - time string "23:00:12"
* @returns {number} Amount in milliseconds
*/
+2 -2
View File
@@ -1,10 +1,10 @@
import { stringFromMillis } from 'ontime-server/utils/time';
/**
* @description From a list of events, returns only events of type event with calculated delays
* @param {Object[]} events - given events
* @returns {Object[]} Filtered events with calculated delays
*/
import {stringFromMillis} from "./dateConfig";
export const getEventsWithDelay = (events) => {
if (events == null) return [];