Skip to content

Commit

Permalink
Add live logging view (#55)
Browse files Browse the repository at this point in the history
* Implement foundation for LoggingView

* Move stop tag to opmode types

* Add LoggingLayout to ViewPicker and layout enum

* Install libs

* Add col-resize cursor to tailwind config

* Progress on the logging view

* Finalize logging view functionality

* Slight styling tweaks

* Install headless ui

* Implement logging view column visibility

* Fix typescript complaint
  • Loading branch information
NoahBres committed Mar 15, 2021
1 parent e55ea16 commit fc113cf
Show file tree
Hide file tree
Showing 22 changed files with 2,288 additions and 1,439 deletions.
12 changes: 10 additions & 2 deletions FtcDashboard/dash/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,23 +4,27 @@
"private": true,
"dependencies": {
"@craco/craco": "^6.0.0",
"@headlessui/react": "^0.3.1",
"@tailwindcss/forms": "^0.2.1",
"@tailwindcss/postcss7-compat": "^2.0.2",
"@tailwindcss/postcss7-compat": "npm:@tailwindcss/postcss7-compat@^2.0.2",
"autoprefixer": "^9.8.6",
"husky": "^4.3.5",
"lint-staged": "^10.5.3",
"postcss": "^7.0.35",
"react": "17.0.1",
"react-dom": "^16.9.0",
"react-draggable": "^4.4.3",
"react-grid-layout": "^1.2.0",
"react-redux": "^7.1.1",
"react-scripts": "4.0.1",
"react-virtualized-auto-sizer": "^1.0.5",
"react-window": "^1.8.6",
"redux": "4.0.5",
"redux-logger": "^3.0.6",
"redux-thunk": "^2.3.0",
"styled-components": "^5.2.1",
"tailwindcss": "npm:@tailwindcss/postcss7-compat@^2.0.2",
"typescript": "^4.1.2",
"typescript": "^4.2.3",
"uuid": "^8.3.2"
},
"scripts": {
Expand Down Expand Up @@ -54,7 +58,11 @@
"@types/react-dom": "^17.0.0",
"@types/react-grid-layout": "^1.1.1",
"@types/react-redux": "^7.1.15",
"@types/react-virtualized-auto-sizer": "^1.0.0",
"@types/react-window": "^1.8.2",
"@types/redux": "^3.6.0",
"@types/redux-logger": "^3.0.8",
"@types/redux-thunk": "^2.1.0",
"@types/resize-observer-browser": "^0.1.4",
"@types/styled-components": "^5.1.5",
"@types/uuid": "^8.3.0",
Expand Down
1 change: 1 addition & 0 deletions FtcDashboard/dash/src/assets/icons/file_download.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions FtcDashboard/dash/src/assets/icons/file_download_off.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions FtcDashboard/dash/src/assets/icons/list.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions FtcDashboard/dash/src/assets/icons/more_vert.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
26 changes: 16 additions & 10 deletions FtcDashboard/dash/src/components/ConfigurableLayout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import LockIconURL from '../assets/icons/lock.svg';
import { ReactComponent as RemoveCircleIcon } from '../assets/icons/remove_circle.svg';
import { ReactComponent as RemoveCircleOutlineIcon } from '../assets/icons/remove_circle_outline.svg';
import CreateIconURL from '../assets/icons/create.svg';
import LoggingView from '../containers/LoggingView/LoggingView';

function maxArray(a: number[], b: number[]) {
if (a.length !== b.length) {
Expand All @@ -54,6 +55,7 @@ const VIEW_MAP: { [key in ConfigurableView]: ReactElement } = {
[ConfigurableView.TELEMETRY_VIEW]: <TelemetryView />,
[ConfigurableView.CAMERA_VIEW]: <CameraView />,
[ConfigurableView.OPMODE_VIEW]: <OpModeView />,
[ConfigurableView.LOGGING_VIEW]: <LoggingView />,
};

const LOCAL_STORAGE_LAYOUT_KEY = 'configurableLayoutStorage';
Expand Down Expand Up @@ -303,17 +305,21 @@ export default function ConfigurableLayout() {
});

useEffect(() => {
const containerResizerObserver = new ResizeObserver((entries) => {
for (const entry of entries) {
if (entry.target === gridWrapperRef.current) {
const width =
gridWrapperRef.current.clientWidth - 2 * GRID_DOT_PADDING;
setGridBgSize(
width / ((GRID_COL / 4) * Math.floor(width / 300) + 1) / 3,
);
const containerResizerObserver = new ResizeObserver(
(entries: ResizeObserverEntry[]) => {
if (gridWrapperRef.current) {
for (const entry of entries) {
if (entry.target === gridWrapperRef.current) {
const width =
gridWrapperRef.current.clientWidth - 2 * GRID_DOT_PADDING;
setGridBgSize(
width / ((GRID_COL / 4) * Math.floor(width / 300) + 1) / 3,
);
}
}
}
}
});
},
);

if (gridWrapperRef.current !== null)
containerResizerObserver.observe(gridWrapperRef.current);
Expand Down
17 changes: 8 additions & 9 deletions FtcDashboard/dash/src/components/RadialFab/RadialFabChild.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import { useRef } from 'react';
import styled from 'styled-components';

import { WithChildren } from '../../typeHelpers';
import useDelayedTooltip from '../../hooks/useDelayedTooltip';
import ToolTip from '../ToolTip';

type RadialFabChildProps = {
customClass?: string;
Expand Down Expand Up @@ -50,20 +52,17 @@ const Icon = styled.div<RadialFabChildProps>`
}deg)`};
`;

const ToolTip = styled.span.attrs<{ isShowing: boolean }>(({ isShowing }) => ({
className: `rounded-md px-3 py-1 absolute w-max bg-gray-800 bg-opacity-80 text-white text-sm pointer-events-none transform transition ${
isShowing ? '-translate-y-11 opacity-100' : '-translate-y-9 opacity-0'
}`,
}))<{ isShowing: boolean }>``;

const RadialFabChild = (props: WithChildren<RadialFabChildProps>) => {
const { isShowingTooltip, ref } = useDelayedTooltip(0.5);
const buttonRef = useRef(null);
const isShowingTooltip = useDelayedTooltip(0.5, buttonRef);

return (
<ButtonContainer {...props} onClick={props.clickEvent} ref={ref}>
<ButtonContainer {...props} onClick={props.clickEvent} ref={buttonRef}>
<Icon {...props}>{props.children}</Icon>
{props.toolTipText !== '' && (
<ToolTip isShowing={isShowingTooltip}>{props.toolTipText}</ToolTip>
<ToolTip isShowing={isShowingTooltip} hoverRef={buttonRef}>
{props.toolTipText}
</ToolTip>
)}
</ButtonContainer>
);
Expand Down
51 changes: 51 additions & 0 deletions FtcDashboard/dash/src/components/ToolTip.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import { useRef, FunctionComponent, RefObject, ReactNode } from 'react';
import { createPortal } from 'react-dom';

import styled from 'styled-components';

interface ToolTipElProps {
isShowing: boolean;
top: string;
left: string;
}

export const ToolTipEl = styled.span.attrs<ToolTipElProps>((props) => ({
className: `fixed rounded-md px-3 py-1 w-max bg-gray-800 bg-opacity-80 text-white text-sm pointer-events-none transform transition ${
props.isShowing ? '-translate-y-11 opacity-100' : '-translate-y-9 opacity-0'
}`,
}))<ToolTipElProps>`
top: ${(props) => props.top};
left: ${(props) => props.left};
`;

interface ToolTipProps {
children: ReactNode;
hoverRef: RefObject<HTMLElement | null>;
isShowing: boolean;
}

const ToolTip: FunctionComponent<ToolTipProps> = ({
children,
hoverRef,
isShowing,
}: ToolTipProps) => {
const tooltipRef = useRef<HTMLSpanElement | null>(null);

return createPortal(
<ToolTipEl
ref={tooltipRef}
isShowing={isShowing}
top={`${hoverRef.current?.getBoundingClientRect().top}px`}
left={`${
(hoverRef.current?.getBoundingClientRect().left ?? 0) +
(hoverRef.current?.clientWidth ?? 0) / 2 -
(tooltipRef.current?.clientWidth ?? 0) / 2
}px`}
>
{children}
</ToolTipEl>,
document.body,
);
};

export default ToolTip;
10 changes: 9 additions & 1 deletion FtcDashboard/dash/src/components/ViewPicker.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { ReactComponent as ChartIcon } from '../assets/icons/chart.svg';
import { ReactComponent as ApiIcon } from '../assets/icons/api.svg';
import { ReactComponent as SubjectIcon } from '../assets/icons/subject.svg';
import { ReactComponent as WidgetIcon } from '../assets/icons/widgets.svg';
import { ReactComponent as ListIcon } from '../assets/icons/list.svg';

type ViewPickerProps = {
isOpen: boolean;
Expand Down Expand Up @@ -77,10 +78,17 @@ const listContent = [
{
title: 'Telemetry View',
view: ConfigurableView.TELEMETRY_VIEW,
icon: <SubjectIcon className="w-6 h-6" />,
icon: <ListIcon className="w-7 h-7" />,
customStyles: 'focus:ring-yellow-600',
iconBg: 'bg-yellow-500',
},
{
title: 'Logging View',
view: ConfigurableView.LOGGING_VIEW,
icon: <SubjectIcon className="w-6 h-6" />,
customStyles: 'focus:ring-ping-600',
iconBg: 'bg-pink-500',
},
{
title: 'Camera View',
view: ConfigurableView.CAMERA_VIEW,
Expand Down
2 changes: 1 addition & 1 deletion FtcDashboard/dash/src/containers/Dashboard.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ class Dashboard extends Component {
<h1 className="text-2xl font-medium">FTC Dashboard</h1>
<div className="flex-center">
<select
className="text-black text-sm rounded mx-2 py-1 bg-blue-100 border-blue-300 focus:ring focus:ring-blue-200"
className="text-black text-sm rounded mx-2 py-1 bg-blue-100 border-blue-300 focus:border-blue-100 focus:ring-2 focus:ring-white focus:ring-opacity-40"
value={this.props.layoutPreset}
onChange={(evt) =>
this.props.dispatch(saveLayoutPreset(evt.target.value))
Expand Down
Loading

0 comments on commit fc113cf

Please sign in to comment.