mirror of
https://github.com/cpvalente/ontime.git
synced 2026-08-22 07:29:08 +00:00
refactor: network interfaces can be copied or followed
This commit is contained in:
committed by
Carlos Valente
parent
78fa1df99c
commit
e46948772e
@@ -1,5 +1,6 @@
|
|||||||
import { PropsWithChildren } from 'react';
|
import { PropsWithChildren, useState } from 'react';
|
||||||
import { Button, ButtonGroup, IconButton, Tooltip } from '@chakra-ui/react';
|
import { Button, ButtonGroup, IconButton, Tooltip } from '@chakra-ui/react';
|
||||||
|
import { IoCheckmark } from '@react-icons/all-files/io5/IoCheckmark';
|
||||||
import { IoCopy } from '@react-icons/all-files/io5/IoCopy';
|
import { IoCopy } from '@react-icons/all-files/io5/IoCopy';
|
||||||
|
|
||||||
import { tooltipDelayFast } from '../../../ontimeConfig';
|
import { tooltipDelayFast } from '../../../ontimeConfig';
|
||||||
@@ -7,26 +8,34 @@ import { Size } from '../../models/Util.type';
|
|||||||
import copyToClipboard from '../../utils/copyToClipboard';
|
import copyToClipboard from '../../utils/copyToClipboard';
|
||||||
|
|
||||||
interface CopyTagProps {
|
interface CopyTagProps {
|
||||||
|
copyValue: string;
|
||||||
label: string;
|
label: string;
|
||||||
className?: string;
|
|
||||||
size?: Size;
|
size?: Size;
|
||||||
disabled?: boolean;
|
disabled?: boolean;
|
||||||
|
onClick?: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function CopyTag(props: PropsWithChildren<CopyTagProps>) {
|
export default function CopyTag(props: PropsWithChildren<CopyTagProps>) {
|
||||||
const { label, className, size = 'xs', disabled, children } = props;
|
const { copyValue, label, size = 'xs', disabled, children, onClick } = props;
|
||||||
|
const [copied, setCopied] = useState(false);
|
||||||
|
|
||||||
const handleClick = () => copyToClipboard(children as string);
|
const handleClick = () => {
|
||||||
|
copyToClipboard(copyValue);
|
||||||
|
setCopied(true);
|
||||||
|
|
||||||
|
// reset copied state
|
||||||
|
setTimeout(() => setCopied(false), 1000);
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Tooltip label={label} openDelay={tooltipDelayFast}>
|
<Tooltip label={label} openDelay={tooltipDelayFast}>
|
||||||
<ButtonGroup size={size} isAttached className={className}>
|
<ButtonGroup size={size} isAttached>
|
||||||
<Button variant='ontime-subtle' tabIndex={-1} isDisabled={disabled}>
|
<Button variant='ontime-subtle' tabIndex={-1} onClick={onClick} isDisabled={disabled}>
|
||||||
{children}
|
{children}
|
||||||
</Button>
|
</Button>
|
||||||
<IconButton
|
<IconButton
|
||||||
aria-label={label}
|
aria-label={label}
|
||||||
icon={<IoCopy />}
|
icon={copied ? <IoCheckmark /> : <IoCopy />}
|
||||||
variant='ontime-filled'
|
variant='ontime-filled'
|
||||||
tabIndex={-1}
|
tabIndex={-1}
|
||||||
onClick={handleClick}
|
onClick={handleClick}
|
||||||
|
|||||||
+5
@@ -4,3 +4,8 @@
|
|||||||
gap: $section-spacing;
|
gap: $section-spacing;
|
||||||
row-gap: $element-inner-spacing;
|
row-gap: $element-inner-spacing;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.goIcon {
|
||||||
|
transform: rotate(45deg);
|
||||||
|
margin-left: 0.25rem;
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,19 +1,33 @@
|
|||||||
|
import { IoArrowUp } from '@react-icons/all-files/io5/IoArrowUp';
|
||||||
|
|
||||||
import { serverPort } from '../../../../common/api/constants';
|
import { serverPort } from '../../../../common/api/constants';
|
||||||
import AppLink from '../../../../common/components/app-link/AppLink';
|
import CopyTag from '../../../../common/components/copy-tag/CopyTag';
|
||||||
import useInfo from '../../../../common/hooks-query/useInfo';
|
import useInfo from '../../../../common/hooks-query/useInfo';
|
||||||
|
import { openLink } from '../../../../common/utils/linkUtils';
|
||||||
|
|
||||||
import style from './NetworkInterfaces.module.scss';
|
import style from './NetworkInterfaces.module.scss';
|
||||||
|
|
||||||
export default function InfoNif() {
|
export default function InfoNif() {
|
||||||
const { data } = useInfo();
|
const { data } = useInfo();
|
||||||
|
|
||||||
|
const handleClick = (address: string) => openLink(address);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={style.interfaces}>
|
<div className={style.interfaces}>
|
||||||
{data?.networkInterfaces?.map((nif) => (
|
{data?.networkInterfaces?.map((nif) => {
|
||||||
<AppLink key={nif.address} href={`http://${nif.address}:${serverPort}`}>
|
const address = `http://${nif.address}:${serverPort}`;
|
||||||
{`${nif.name} - ${nif.address}`}
|
|
||||||
</AppLink>
|
return (
|
||||||
))}
|
<CopyTag
|
||||||
|
key={nif.name}
|
||||||
|
copyValue={address}
|
||||||
|
onClick={() => handleClick(address)}
|
||||||
|
label='Copy IP or navigate to address'
|
||||||
|
>
|
||||||
|
{`${nif.name} - ${nif.address}`} <IoArrowUp className={style.goIcon} />
|
||||||
|
</CopyTag>
|
||||||
|
);
|
||||||
|
})}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -193,7 +193,7 @@ export default function GSheetSetup(props: GSheetSetupProps) {
|
|||||||
<Panel.ListGroup>
|
<Panel.ListGroup>
|
||||||
<div className={style.buttonRow}>
|
<div className={style.buttonRow}>
|
||||||
{isAuthenticating && <Spinner />}
|
{isAuthenticating && <Spinner />}
|
||||||
<CopyTag label='Google Auth Key' disabled={!canAuthenticate} size='sm'>
|
<CopyTag copyValue={authKey ?? ''} label='Google Auth Key' disabled={!canAuthenticate} size='sm'>
|
||||||
{authKey ? authKey : 'Upload files to generate Auth Key'}
|
{authKey ? authKey : 'Upload files to generate Auth Key'}
|
||||||
</CopyTag>
|
</CopyTag>
|
||||||
<Button
|
<Button
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { CSSProperties, useCallback, useEffect, useState } from 'react';
|
import { CSSProperties, memo, useCallback, useEffect, useState } from 'react';
|
||||||
import { useSearchParams } from 'react-router-dom';
|
import { useSearchParams } from 'react-router-dom';
|
||||||
import { Button } from '@chakra-ui/react';
|
import { Button } from '@chakra-ui/react';
|
||||||
import { CustomFieldLabel, isOntimeEvent, OntimeEvent } from 'ontime-types';
|
import { CustomFieldLabel, isOntimeEvent, OntimeEvent } from 'ontime-types';
|
||||||
@@ -126,10 +126,32 @@ export default function EventEditor() {
|
|||||||
})}
|
})}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className={style.footer}>
|
<EventEditorFooter id={event.id} cue={event.cue} />
|
||||||
<CopyTag label='OSC trigger by id'>{`/ontime/load/id "${event.id}"`}</CopyTag>
|
</div>
|
||||||
<CopyTag label='OSC trigger by cue'>{`/ontime/load/cue "${event.cue}"`}</CopyTag>
|
);
|
||||||
</div>
|
}
|
||||||
|
|
||||||
|
interface EventEditorFooterProps {
|
||||||
|
id: string;
|
||||||
|
cue: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const EventEditorFooter = memo(_EventEditorFooter);
|
||||||
|
|
||||||
|
function _EventEditorFooter(props: EventEditorFooterProps) {
|
||||||
|
const { id, cue } = props;
|
||||||
|
|
||||||
|
const loadById = `/ontime/load/id "${id}"`;
|
||||||
|
const loadByCue = `/ontime/load/cue "${cue}"`;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={style.footer}>
|
||||||
|
<CopyTag copyValue={loadById} label='OSC trigger by ID'>
|
||||||
|
{loadById}
|
||||||
|
</CopyTag>
|
||||||
|
<CopyTag copyValue={loadByCue} label='OSC trigger by cue'>
|
||||||
|
{loadByCue}
|
||||||
|
</CopyTag>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user