Skip to content

Commit 4735279

Browse files
committed
fix: Various small UI fixes
1 parent e797964 commit 4735279

27 files changed

+395
-78
lines changed

.vscode/settings.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"editor.detectIndentation": true
3+
}

.yarn/install-state.gz

1.57 MB
Binary file not shown.

src/App.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import { TimezoneProvider } from '@components/TimezoneProvider';
1919
import { LoggingProvider } from '@hooks/useLogger';
2020
import { fetchFeaturesConfig } from '@utils/FEATURE';
2121
import { fetchServiceVersion } from '@utils/VERSION';
22+
import ThemeSwitcher from './components/ThemeSwitcher';
2223
import { appBasePath } from './constants';
2324

2425
const App: React.FC = () => {
@@ -41,6 +42,7 @@ const App: React.FC = () => {
4142
<PluginsProvider>
4243
<LoggingProvider>
4344
<GlobalStyle />
45+
<ThemeSwitcher />
4446
<Router basename={appBasePath}>
4547
<QueryParamProvider ReactRouterRoute={Route}>
4648
{flagsReceived ? (

src/components/AppBar/index.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ const Wrapper = styled.header`
5252
padding: var(--layout-application-bar-padding);
5353
margin: 0 auto;
5454
background: var(--color-bg-primary);
55+
border-radius: var(--layout-application-bar-radius);
5556
z-index: 999;
5657
flex-direction: column;
5758
`;

src/components/FilterInput/AutoCompleteFilter.tsx

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,16 @@ type Props = {
1717
onClear?: () => void;
1818
autoCompleteSettings?: InputAutocompleteSettings;
1919
optionLabelRenderer?: (value: string) => React.ReactNode;
20+
inputProps?: React.InputHTMLAttributes<HTMLInputElement>;
2021
} & Omit<FilterProps, 'content'>;
2122

22-
const AutoCompleteFilter: React.FC<Props> = ({ autoCompleteSettings, onClear, optionLabelRenderer, ...props }) => {
23+
const AutoCompleteFilter: React.FC<Props> = ({
24+
autoCompleteSettings,
25+
onClear,
26+
optionLabelRenderer,
27+
inputProps = {},
28+
...props
29+
}) => {
2330
const [inputValue, setInputValue] = useState('');
2431
const { result: autoCompleteResult } = useAutoComplete<string>(
2532
autoCompleteSettings
@@ -38,8 +45,8 @@ const AutoCompleteFilter: React.FC<Props> = ({ autoCompleteSettings, onClear, op
3845
content={({ selected, onClose }) => (
3946
<Content>
4047
<FilterPopupHeading>
41-
<InputWrapper active={true}>
42-
<input type="text" onChange={(event) => setInputValue(event.target.value)} />
48+
<InputWrapper active={true} size="sm">
49+
<input type="text" onChange={(event) => setInputValue(event.target.value)} {...inputProps} />
4350
</InputWrapper>
4451
</FilterPopupHeading>
4552

@@ -69,7 +76,7 @@ const AutoCompleteFilter: React.FC<Props> = ({ autoCompleteSettings, onClear, op
6976
},
7077
disabled: selected.length === 0,
7178
}}
72-
></FilterPopupTrailing>
79+
/>
7380
)}
7481
</Content>
7582
)}

src/components/FilterInput/Filter.tsx

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,17 @@ const Filter: React.FC<FilterProps> = ({ label, labelRenderer, value = '', onSel
1616
const [filterWindowOpen, setFilterWindowOpen] = useState(false);
1717
const selected = value?.split(',').filter((item) => item) || [];
1818

19-
const close = () => setFilterWindowOpen(false);
19+
const close = () => {
20+
setFilterWindowOpen(false);
21+
};
2022

2123
return (
2224
<FilterBase {...rest}>
23-
<FilterButton onClick={() => setFilterWindowOpen(!filterWindowOpen)}>
25+
<FilterButton
26+
onClick={() => {
27+
setFilterWindowOpen(!filterWindowOpen);
28+
}}
29+
>
2430
{labelRenderer ? labelRenderer(label, value) : DefaultLabelRenderer(label, value)}
2531
<FilterIcon>
2632
<Icon name="chevron" size="xs" rotate={filterWindowOpen ? -180 : 0} />

src/components/FilterInput/FilterPopup.tsx

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,15 @@ const FilterPopup: React.FC<{ children: React.ReactNode; onClose: () => void }>
77

88
useEffect(() => {
99
function handleClickOutside(event: MouseEvent) {
10-
if (ref.current && event.target instanceof Node && !ref.current.contains(event.target)) {
10+
const clickedParentOrPopup =
11+
ref.current && event.target instanceof Node && ref.current.parentNode?.contains(event.target);
12+
if (!clickedParentOrPopup) {
1113
onClose();
1214
}
1315
}
14-
document.addEventListener('mousedown', handleClickOutside);
16+
document.addEventListener('mouseup', handleClickOutside);
1517
return () => {
16-
document.removeEventListener('mousedown', handleClickOutside);
18+
document.removeEventListener('mouseup', handleClickOutside);
1719
};
1820
}, [ref, onClose]);
1921

src/components/FilterInput/FilterRows.tsx

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ export const FilterOptionRow: React.FC<{ onClick: () => void; selected: boolean;
1010
}) => (
1111
<FilterClickableRow onClick={onClick}>
1212
<CheckboxField checked={selected} />
13-
{children}
13+
<OptionValue>{children}</OptionValue>
1414
</FilterClickableRow>
1515
);
1616

@@ -33,6 +33,11 @@ export const FilterClickableRow = styled.div<{ disabled?: boolean; danger?: bool
3333
}
3434
`;
3535

36+
const OptionValue = styled.div`
37+
overflow: hidden;
38+
text-overflow: ellipsis;
39+
`;
40+
3641
type ClearFilterRowProps = {
3742
onClick: () => void;
3843
disabled: boolean;
@@ -58,3 +63,9 @@ export const FilterPopupTrailing: React.FC<{ clear?: ClearFilterRowProps; childr
5863
{children}
5964
</div>
6065
);
66+
67+
export const FilterTextRow = styled.div`
68+
padding: 0 0.5rem;
69+
margin: 0.5rem 0;
70+
color: var(--color-text-secondary);
71+
`;

src/components/Form/InputWrapper.tsx

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,16 +26,17 @@ const InputWrapper = styled.section<InputWrapperProps>`
2626
cursor: ${(p) => (p.active ? 'auto' : 'pointer')};
2727
background-color: transparent;
2828
padding-right: 1.5rem;
29-
font-size: var(--input-font-size);
29+
font-size: ${(p) => (p.size === 'sm' ? 'var(--input-font-size-sm)' : 'var(--input-font-size)')};
3030
3131
&:focus {
3232
outline: none;
3333
border: none;
3434
}
3535
3636
&::placeholder {
37-
color: var(--color-text-primary);
38-
font-weight: 500;
37+
color: var(--input-placeholder-color);
38+
font-size: var(--input-placeholder-font-size);
39+
font-weight: var(--input-placeholder-font-weight);
3940
opacity: 1;
4041
}
4142
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
// eslint-disable-next-line
2+
// @ts-ignore Load CSS as a string to be appended to injected plugin stylesheet.
3+
// eslint-disable-next-line import/no-webpack-loader-syntax
4+
import css from '!!css-loader?{"sourceMap":false,"exportType":"string"}!../../theme/ob-theme.css';
5+
import React, { useState } from 'react';
6+
import styled from 'styled-components';
7+
import Button from '../Button';
8+
9+
const ThemeSwitcher: React.FC = () => {
10+
const [enabled, setEnabled] = useState(false);
11+
12+
return (
13+
<>
14+
<style>{enabled ? css : ''}</style>
15+
<Switcher>
16+
<Button onClick={() => setEnabled(!enabled)} variant="primaryText">
17+
{enabled ? 'Disable' : 'Enable'} OB Theme
18+
</Button>
19+
</Switcher>
20+
</>
21+
);
22+
};
23+
24+
const Switcher = styled.div`
25+
position: fixed;
26+
bottom: 0;
27+
right: 0;
28+
z-index: 99999;
29+
`;
30+
31+
export default ThemeSwitcher;

src/components/Trigger/TriggeredByBadge.tsx

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,16 +16,25 @@ type Props = {
1616
};
1717

1818
const TriggeredByBadge: React.FC<Props> = ({ id, content }) => {
19+
const tooltipId = `trigger-tooltip-${id}`;
20+
1921
if (content.type === 'user') {
20-
return <Badge badgeType="user">{content.data}</Badge>;
22+
return (
23+
<>
24+
<Badge badgeType="user" data-tip data-for={tooltipId}>
25+
{content.data}
26+
</Badge>
27+
<Tooltip id={tooltipId} place="bottom">
28+
<div>{content.data}</div>
29+
</Tooltip>
30+
</>
31+
);
2132
}
2233

23-
const tooltipId = `trigger-tooltip-${id}`;
24-
2534
return (
2635
<Badges>
2736
{content.data.slice(0, 1).map((item) => (
28-
<Badge key={item.name} badgeType={item.type}>
37+
<Badge key={item.name} badgeType={item.type} data-tip data-for={tooltipId}>
2938
{item.name}
3039
</Badge>
3140
))}
@@ -57,7 +66,7 @@ const Badge = styled.div<{ badgeType: 'user' | 'event' | 'run' }>`
5766
color: var(--color-text-light);
5867
text-overflow: ellipsis;
5968
width: max-content;
60-
max-width: 150px;
69+
max-width: 13rem;
6170
white-space: nowrap;
6271
overflow: hidden;
6372
`;

src/mocks/browser.js

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -121,11 +121,13 @@ export const worker = setupWorker(
121121
args.params.id > 10 &&
122122
generateRunMetadata({
123123
field_name: 'execution-triggers',
124-
value: JSON.stringify([
125-
{ timestamp: 1709280139, id: '7d222e92-83dc-489c-a80e-4711f312dbd0', name: 'test_event', type: 'run' },
126-
{ timestamp: 1709280138, id: '7d222e91-83dc-489c-a80e-4711f312dbd0', name: 'other_event', type: 'event' },
127-
{ timestamp: 1709280137, id: '7d222e90-83dc-489c-a80e-4711f312dbd0', name: 'yahoo', type: 'event' },
128-
]),
124+
value: JSON.stringify(
125+
[
126+
{ timestamp: 1709280139, id: '7d222e92-83dc-489c-a80e-4711f312dbd0', name: 'test_event', type: 'run' },
127+
{ timestamp: 1709280138, id: '7d222e91-83dc-489c-a80e-4711f312dbd0', name: 'other_event', type: 'event' },
128+
{ timestamp: 1709280137, id: '7d222e90-83dc-489c-a80e-4711f312dbd0', name: 'yahoo', type: 'event' },
129+
].slice(0, Math.floor(Math.random() * 3)),
130+
),
129131
}),
130132
]),
131133
stantardGetEndpoint('api/flows/:flowid/runs/:runid/parameters', {
@@ -348,14 +350,14 @@ export const worker = setupWorker(
348350
]),
349351
rawGetEndpoint('api/plugin', []),
350352
rawGetEndpoint('api/features', {
351-
FEATURE_RUN_GROUPS: true,
353+
FEATURE_RUN_GROUPS: false,
352354
// FEATURE_DEBUG_VIEW: true,
353355
// FEATURE_HIDE_LOGO: true,
354356
// FEATURE_HIDE_HOME_BUTTON: true,
355357
// FEATURE_HIDE_STATUS_FILTERS: false,
356358
// FEATURE_HIDE_TABLE_HEADER: true,
357359
// FEATURE_HIDE_QUICK_LINKS: true,
358-
FEATURE_ARTIFACT_SEARCH: true,
360+
// FEATURE_HIDE_CONNECTION_STATUS: true,
359361
}),
360362
stantardGetEndpoint('api/links', []),
361363
rawGetEndpoint('api/notifications', [
@@ -369,14 +371,13 @@ export const worker = setupWorker(
369371
type: 'info',
370372
},
371373
]),
372-
stantardGetEndpoint('api/flows/autocomplete', ['BasicFlow', 'NewFlow']),
374+
stantardGetEndpoint('api/flows/autocomplete', ['BasicFlow', 'NewFlow', 'VerylooooooooooooooongFlowNaaaaaaaaaaame']),
373375
http.get('api/tags/autocomplete*', ({ request }) => {
374376
let response = [];
375-
console.log(request.url);
376377
if (request.url.includes('tag%3Are=project_branch')) {
377378
response = ['project_branch:user.whoever', 'project_branch:someone.else'];
378379
} else if (request.url.includes('tag%3Are=project')) {
379-
response = ['project:project1', 'project:project2'];
380+
response = ['project:project1', 'project:veryloooooooooooooooooooooooooongprojectnaaaaaaame'];
380381
} else if (request.url.includes('tag%3Are=user')) {
381382
response = ['user:[email protected]', 'user:[email protected]'];
382383
} else if (request.url.includes('tag%3Aco=')) {

src/pages/Home/Filters/StatusSelection.tsx

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -31,11 +31,11 @@ const StatusSelection: React.FC<Props> = ({ updateField, onClear, status }) => {
3131
return (
3232
<>
3333
{label}
34-
<StatusLights>
34+
<LabelStatusRow>
3535
{value
3636
?.split(',')
3737
.map((status) => isValidStatus(status) && <StatusIndicator status={status} key={status} />)}
38-
</StatusLights>
38+
</LabelStatusRow>
3939
</>
4040
);
4141
}}
@@ -45,8 +45,10 @@ const StatusSelection: React.FC<Props> = ({ updateField, onClear, status }) => {
4545
<div>
4646
{options.map(([key, label]) => (
4747
<FilterOptionRow key={key} onClick={() => updateField('status', key)} selected={!!status?.includes(key)}>
48-
{isValidStatus(key) && <StatusIndicator status={key} />}
49-
{label}
48+
<StatusRow>
49+
{isValidStatus(key) && <StatusIndicator status={key} />}
50+
{label}
51+
</StatusRow>
5052
</FilterOptionRow>
5153
))}
5254
<FilterPopupTrailing
@@ -69,14 +71,13 @@ function isAllSelected(status?: string | null) {
6971
return !status || ['completed', 'running', 'failed'].every((s) => status.includes(s));
7072
}
7173

72-
const StatusLights = styled.div`
74+
const StatusRow = styled.div`
7375
display: flex;
7476
align-items: center;
75-
margin-left: 0.5rem;
76-
77-
& > * {
78-
margin-right: 0.25rem;
79-
}
77+
gap: 0.25rem;
8078
`;
8179

80+
const LabelStatusRow = styled(StatusRow)`
81+
margin-left: 0.5rem;
82+
`;
8283
export default StatusSelection;

src/pages/Home/Filters/TagFilter.tsx

Lines changed: 3 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import React from 'react';
2-
import styled from 'styled-components';
32
import AutoCompleteFilter from '@components/FilterInput/AutoCompleteFilter';
43
import { DefaultLabelRenderer } from '@components/FilterInput/Filter';
54

@@ -8,6 +7,7 @@ type Props = {
87
onClear?: () => void;
98
tags: string;
109
prefix?: string;
10+
inputProps?: React.InputHTMLAttributes<HTMLInputElement>;
1111
label: string;
1212
autoCompleteInputTransform: (v: string) => Record<string, string>;
1313
};
@@ -44,21 +44,10 @@ function labelRenderer(label: string, value?: string | null, prefix?: string) {
4444

4545
function optionLabelRenderer(value: string, prefix?: string) {
4646
if (!prefix || !value.startsWith(prefix)) return value;
47-
const [tagType, label] = value.split(':');
48-
return (
49-
<div>
50-
<OptionLabelTagType>{tagType}:</OptionLabelTagType>
51-
<span>{label}</span>
52-
</div>
53-
);
47+
const [_, label] = value.split(':');
48+
return label;
5449
}
5550

56-
const OptionLabelTagType = styled.span`
57-
color: var(--color-text-light);
58-
margin-right: 0.25rem;
59-
text-transform: capitalize;
60-
`;
61-
6251
function extractTypesOfTag(tags: string, tagType?: string): string[] {
6352
if (!tags) return [];
6453
if (!tagType) return tags.split(',');

0 commit comments

Comments
 (0)