ui: shrink icons when no space, adjust player area for events export … (#3217)
* ui: shrink icons when no space, adjust player area for events export panel, fix panel size * ui: rm log
This commit is contained in:
parent
bef91a6136
commit
1d6fb0ae9e
10 changed files with 85 additions and 28 deletions
|
|
@ -91,7 +91,7 @@ function PlayerBlockHeader(props: Props) {
|
|||
)}
|
||||
</div>
|
||||
</div>
|
||||
<div className="relative border-l" style={{ minWidth: '270px' }}>
|
||||
<div className="relative border-l" style={{ minWidth: activeTab === 'EXPORT' ? '360px' : '270px' }}>
|
||||
<Tabs
|
||||
tabs={TABS}
|
||||
active={activeTab}
|
||||
|
|
|
|||
|
|
@ -61,7 +61,7 @@ function PlayerContent({
|
|||
className="w-full"
|
||||
style={
|
||||
activeTab && !fullscreen
|
||||
? { maxWidth: 'calc(100% - 270px)' }
|
||||
? { maxWidth: `calc(100% - ${activeTab === 'EXPORT' ? '360px' : '270px'})` }
|
||||
: undefined
|
||||
}
|
||||
>
|
||||
|
|
|
|||
|
|
@ -126,7 +126,7 @@ function PlayerBlockHeader(props: any) {
|
|||
</div>
|
||||
<div
|
||||
className="px-2 relative border-l border-l-gray-lighter"
|
||||
style={{ minWidth: '270px' }}
|
||||
style={{ minWidth: activeTab === 'EXPORT' ? '360px' : '270px' }}
|
||||
>
|
||||
<Tabs
|
||||
tabs={TABS}
|
||||
|
|
|
|||
|
|
@ -65,7 +65,7 @@ function PlayerContent({
|
|||
className="w-full"
|
||||
style={
|
||||
activeTab && !fullscreen
|
||||
? { maxWidth: 'calc(100% - 270px)' }
|
||||
? { maxWidth: `calc(100% - ${activeTab === 'EXPORT' ? '360px' : '270px'})` }
|
||||
: undefined
|
||||
}
|
||||
>
|
||||
|
|
|
|||
|
|
@ -182,6 +182,7 @@ function Player(props: IProps) {
|
|||
setActiveTab={(tab: string) =>
|
||||
activeTab === tab ? props.setActiveTab('') : props.setActiveTab(tab)
|
||||
}
|
||||
activeTab={activeTab}
|
||||
speedDown={playerContext.player.speedDown}
|
||||
speedUp={playerContext.player.speedUp}
|
||||
jump={playerContext.player.jump}
|
||||
|
|
|
|||
|
|
@ -7,13 +7,16 @@ import { Icon } from 'UI';
|
|||
function LogsButton({
|
||||
integrated,
|
||||
onClick,
|
||||
shorten,
|
||||
}: {
|
||||
integrated: string[];
|
||||
onClick: () => void;
|
||||
shorten?: boolean;
|
||||
}) {
|
||||
return (
|
||||
<ControlButton
|
||||
label="Traces"
|
||||
label={shorten ? null : "Traces"}
|
||||
customKey="traces"
|
||||
customTags={
|
||||
<Avatar.Group>
|
||||
{integrated.map((name) => (
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import { Popover, Button } from 'antd';
|
|||
import stl from './controlButton.module.css';
|
||||
|
||||
interface IProps {
|
||||
label: string;
|
||||
label: React.ReactNode;
|
||||
icon?: string;
|
||||
disabled?: boolean;
|
||||
onClick?: () => void;
|
||||
|
|
@ -18,6 +18,7 @@ interface IProps {
|
|||
noIcon?: boolean;
|
||||
popover?: React.ReactNode;
|
||||
customTags?: React.ReactNode;
|
||||
customKey?: string;
|
||||
}
|
||||
|
||||
function ControlButton({
|
||||
|
|
@ -28,29 +29,28 @@ function ControlButton({
|
|||
active = false,
|
||||
popover = undefined,
|
||||
customTags,
|
||||
customKey,
|
||||
}: IProps) {
|
||||
return (
|
||||
<Popover content={popover} open={popover ? undefined : false}>
|
||||
<Button
|
||||
size="small"
|
||||
onClick={onClick}
|
||||
id={`control-button-${label.toLowerCase()}`}
|
||||
id={`control-button-${customKey ? customKey.toLowerCase() : label!.toString().toLowerCase()}`}
|
||||
disabled={disabled}
|
||||
>
|
||||
{customTags}
|
||||
{hasErrors && (
|
||||
<div className={stl.labels}>
|
||||
<div className={stl.errorSymbol} />
|
||||
</div>
|
||||
<div className="w-2 h-2 rounded-full bg-red" />
|
||||
)}
|
||||
<span
|
||||
{label && <span
|
||||
className={cn(
|
||||
'font-semibold hover:text-main',
|
||||
active ? 'color-main' : 'color-gray-darkest',
|
||||
)}
|
||||
>
|
||||
{label}
|
||||
</span>
|
||||
</span>}
|
||||
</Button>
|
||||
</Popover>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -32,6 +32,8 @@ import {
|
|||
} from 'App/mstore/uiPlayerStore';
|
||||
import { Icon } from 'UI';
|
||||
import LogsButton from 'App/components/Session/Player/SharedComponents/BackendLogs/LogsButton';
|
||||
import { CodeOutlined, DashboardOutlined, ClusterOutlined } from '@ant-design/icons';
|
||||
import { ArrowDownUp, ListCollapse, Merge, Waypoints } from 'lucide-react'
|
||||
|
||||
import ControlButton from './ControlButton';
|
||||
import Timeline from './Timeline';
|
||||
|
|
@ -52,23 +54,23 @@ export const SKIP_INTERVALS = {
|
|||
function getStorageName(type: any) {
|
||||
switch (type) {
|
||||
case STORAGE_TYPES.REDUX:
|
||||
return 'Redux';
|
||||
return { name: 'Redux', icon: <Icon name='integrations/redux' size={14} /> };
|
||||
case STORAGE_TYPES.MOBX:
|
||||
return 'Mobx';
|
||||
return { name: 'Mobx', icon: <Icon name='integrations/mobx' size={14} /> };
|
||||
case STORAGE_TYPES.VUEX:
|
||||
return 'Vuex';
|
||||
return { name: 'Vuex', icon: <Icon name='integrations/vuejs' size={14} /> };
|
||||
case STORAGE_TYPES.NGRX:
|
||||
return 'NgRx';
|
||||
return { name: 'NgRx', icon: <Icon name='integrations/ngrx' size={14} /> };
|
||||
case STORAGE_TYPES.ZUSTAND:
|
||||
return 'Zustand';
|
||||
return { name: 'Zustand', icon: <Icon name='integrations/zustand' size={14} /> };
|
||||
case STORAGE_TYPES.NONE:
|
||||
return 'State';
|
||||
return { name: 'State', icon: <ClusterOutlined size={14} /> };
|
||||
default:
|
||||
return 'State';
|
||||
return { name: 'State', icon: <ClusterOutlined size={14} /> };
|
||||
}
|
||||
}
|
||||
|
||||
function Controls({ setActiveTab }: any) {
|
||||
function Controls({ setActiveTab, activeTab }: any) {
|
||||
const { player, store } = React.useContext(PlayerContext);
|
||||
const {
|
||||
uxtestingStore,
|
||||
|
|
@ -191,6 +193,7 @@ function Controls({ setActiveTab }: any) {
|
|||
bottomBlock={bottomBlock}
|
||||
disabled={disabled}
|
||||
events={events}
|
||||
activeTab={activeTab}
|
||||
/>
|
||||
)}
|
||||
|
||||
|
|
@ -212,6 +215,7 @@ interface IDevtoolsButtons {
|
|||
bottomBlock: number;
|
||||
disabled: boolean;
|
||||
events: any[];
|
||||
activeTab?: string;
|
||||
}
|
||||
|
||||
const DevtoolsButtons = observer(
|
||||
|
|
@ -221,6 +225,7 @@ const DevtoolsButtons = observer(
|
|||
bottomBlock,
|
||||
disabled,
|
||||
events,
|
||||
activeTab,
|
||||
}: IDevtoolsButtons) => {
|
||||
const { t } = useTranslation();
|
||||
const { aiSummaryStore, integrationsStore } = useStore();
|
||||
|
|
@ -262,6 +267,36 @@ const DevtoolsButtons = observer(
|
|||
const possibleAudio = events.filter((e) => e.name.includes('media/audio'));
|
||||
const integratedServices =
|
||||
integrationsStore.integrations.backendLogIntegrations;
|
||||
|
||||
const showIcons = activeTab === 'EXPORT'
|
||||
const labels = {
|
||||
console: {
|
||||
icon: <CodeOutlined size={14} />,
|
||||
label: t('Console'),
|
||||
},
|
||||
performance: {
|
||||
icon: <DashboardOutlined size={14} />,
|
||||
label: t('Performance'),
|
||||
},
|
||||
network: {
|
||||
icon: <ArrowDownUp size={14} strokeWidth={2} />,
|
||||
label: t('Network'),
|
||||
},
|
||||
events: {
|
||||
icon: <ListCollapse size={14} strokeWidth={2} />,
|
||||
label: t('Events'),
|
||||
},
|
||||
state: {
|
||||
icon: getStorageName(storageType).icon,
|
||||
label: getStorageName(storageType).name,
|
||||
},
|
||||
graphql: {
|
||||
icon: <Merge size={14} strokeWidth={2} />,
|
||||
label: 'Graphql',
|
||||
}
|
||||
}
|
||||
// @ts-ignore
|
||||
const getLabel = (block: string) => labels[block][showIcons ? 'icon' : 'label']
|
||||
return (
|
||||
<>
|
||||
{isSaas ? <SummaryButton onClick={showSummary} /> : null}
|
||||
|
|
@ -274,6 +309,7 @@ const DevtoolsButtons = observer(
|
|||
</div>
|
||||
</div>
|
||||
}
|
||||
customKey="xray"
|
||||
label="X-Ray"
|
||||
onClick={() => toggleBottomTools(OVERVIEW)}
|
||||
active={bottomBlock === OVERVIEW && !inspectorMode}
|
||||
|
|
@ -286,10 +322,11 @@ const DevtoolsButtons = observer(
|
|||
<div>{t('Launch Console')}</div>
|
||||
</div>
|
||||
}
|
||||
customKey="console"
|
||||
disabled={disableButtons}
|
||||
onClick={() => toggleBottomTools(CONSOLE)}
|
||||
active={bottomBlock === CONSOLE && !inspectorMode}
|
||||
label={t('Console')}
|
||||
label={getLabel('console')}
|
||||
hasErrors={logRedCount > 0 || showExceptions}
|
||||
/>
|
||||
|
||||
|
|
@ -300,10 +337,11 @@ const DevtoolsButtons = observer(
|
|||
<div>{t('Launch Network')}</div>
|
||||
</div>
|
||||
}
|
||||
customKey="network"
|
||||
disabled={disableButtons}
|
||||
onClick={() => toggleBottomTools(NETWORK)}
|
||||
active={bottomBlock === NETWORK && !inspectorMode}
|
||||
label={t('Network')}
|
||||
label={getLabel('network')}
|
||||
hasErrors={resourceRedCount > 0}
|
||||
/>
|
||||
|
||||
|
|
@ -314,10 +352,11 @@ const DevtoolsButtons = observer(
|
|||
<div>{t('Launch Performance')}</div>
|
||||
</div>
|
||||
}
|
||||
customKey="performance"
|
||||
disabled={disableButtons}
|
||||
onClick={() => toggleBottomTools(PERFORMANCE)}
|
||||
active={bottomBlock === PERFORMANCE && !inspectorMode}
|
||||
label="Performance"
|
||||
label={getLabel('performance')}
|
||||
/>
|
||||
|
||||
{showGraphql && (
|
||||
|
|
@ -325,7 +364,8 @@ const DevtoolsButtons = observer(
|
|||
disabled={disableButtons}
|
||||
onClick={() => toggleBottomTools(GRAPHQL)}
|
||||
active={bottomBlock === GRAPHQL && !inspectorMode}
|
||||
label="Graphql"
|
||||
label={getLabel('graphql')}
|
||||
customKey="graphql"
|
||||
/>
|
||||
)}
|
||||
|
||||
|
|
@ -337,10 +377,11 @@ const DevtoolsButtons = observer(
|
|||
<div>{t('Launch State')}</div>
|
||||
</div>
|
||||
}
|
||||
customKey="state"
|
||||
disabled={disableButtons}
|
||||
onClick={() => toggleBottomTools(STORAGE)}
|
||||
active={bottomBlock === STORAGE && !inspectorMode}
|
||||
label={getStorageName(storageType) as string}
|
||||
label={getLabel('state')}
|
||||
/>
|
||||
)}
|
||||
<ControlButton
|
||||
|
|
@ -350,14 +391,16 @@ const DevtoolsButtons = observer(
|
|||
<div>{t('Launch Events')}</div>
|
||||
</div>
|
||||
}
|
||||
customKey="events"
|
||||
disabled={disableButtons}
|
||||
onClick={() => toggleBottomTools(STACKEVENTS)}
|
||||
active={bottomBlock === STACKEVENTS && !inspectorMode}
|
||||
label={t('Events')}
|
||||
label={getLabel('events')}
|
||||
hasErrors={stackRedCount > 0}
|
||||
/>
|
||||
{showProfiler && (
|
||||
<ControlButton
|
||||
customKey="profiler"
|
||||
disabled={disableButtons}
|
||||
onClick={() => toggleBottomTools(PROFILER)}
|
||||
active={bottomBlock === PROFILER && !inspectorMode}
|
||||
|
|
@ -368,6 +411,7 @@ const DevtoolsButtons = observer(
|
|||
<LogsButton
|
||||
integrated={integratedServices.map((service) => service.name)}
|
||||
onClick={() => toggleBottomTools(BACKENDLOGS)}
|
||||
shorten={showIcons}
|
||||
/>
|
||||
) : null}
|
||||
{possibleAudio.length ? (
|
||||
|
|
|
|||
|
|
@ -202,7 +202,7 @@ function UnitStepsModal({ onClose }: Props) {
|
|||
<div className={'w-full'}>
|
||||
<CodeBlock
|
||||
width={340}
|
||||
height={'calc(100vh - 146px)'}
|
||||
height={'calc(100vh - 174px)'}
|
||||
extra={`${events.length} Events`}
|
||||
copy
|
||||
code={eventStr}
|
||||
|
|
|
|||
|
|
@ -5,6 +5,15 @@ import { Tooltip } from 'antd';
|
|||
import cn from 'classnames';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
interface Props {
|
||||
code?: string;
|
||||
extra?: string;
|
||||
language?: string;
|
||||
copy?: boolean;
|
||||
width?: string;
|
||||
height?: string;
|
||||
}
|
||||
|
||||
export default function CodeBlock({
|
||||
code = '',
|
||||
extra = '',
|
||||
|
|
@ -12,7 +21,7 @@ export default function CodeBlock({
|
|||
copy = false,
|
||||
width = undefined,
|
||||
height = undefined,
|
||||
}) {
|
||||
}: Props) {
|
||||
const { t } = useTranslation();
|
||||
useEffect(() => {
|
||||
setTimeout(() => {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue