Skip to content

Commit f2ac013

Browse files
committed
fix: various UI fixes
1 parent e797964 commit f2ac013

22 files changed

+159
-78
lines changed

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
}

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(',');

src/pages/Home/Filters/TimerangeSelection.tsx

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,12 @@ import spacetime from 'spacetime';
55
import styled from 'styled-components';
66
import DateInput from '@/components/Form/DateInput';
77
import Filter from '@components/FilterInput/Filter';
8-
import { FilterClickableRow, FilterSeparator } from '@components/FilterInput/FilterRows';
8+
import {
9+
FilterClickableRow,
10+
FilterPopupTrailing,
11+
FilterSeparator,
12+
FilterTextRow,
13+
} from '@components/FilterInput/FilterRows';
914
import { TimezoneContext } from '@components/TimezoneProvider';
1015
import { getDateTimeLocalString, getTimeFromPastByDays, getTimeRangeString } from '@utils/date';
1116

@@ -24,7 +29,9 @@ const TimerangeSelection: React.FC<Props> = ({ value, onChange }) => {
2429
<Filter
2530
label="Time frame"
2631
value={labelValue}
27-
content={() => <TimeRangePopup label={labelValue} value={value} onChange={onChange} />}
32+
content={({ onClose }) => (
33+
<TimeRangePopup label={labelValue} value={value} onChange={onChange} onClose={onClose} />
34+
)}
2835
/>
2936
);
3037
};
@@ -33,7 +40,8 @@ const TimeRangePopup: React.FC<{
3340
value: TimerangeValues;
3441
label: string | null;
3542
onChange: (args: TimerangeValues) => void;
36-
}> = ({ value, onChange }) => {
43+
onClose: () => void;
44+
}> = ({ value, onChange, onClose }) => {
3745
const { t } = useTranslation();
3846
const { timezone } = useContext(TimezoneContext);
3947
const presets = [
@@ -51,9 +59,9 @@ const TimeRangePopup: React.FC<{
5159
</FilterClickableRow>
5260
))}
5361
<FilterSeparator />
54-
<p>{t('filters.custom')}</p>
62+
<FilterTextRow>{t('filters.custom')}</FilterTextRow>
5563

56-
<TimerangeFooter>
64+
<TimerangeFields>
5765
<DateInput
5866
inputType="datetime-local"
5967
onChange={(newValue) => onChange({ ...value, start: newValue ? spacetime(newValue, timezone).epoch : null })}
@@ -65,7 +73,17 @@ const TimeRangePopup: React.FC<{
6573
onChange={(newValue) => onChange({ ...value, end: newValue ? spacetime(newValue, timezone).epoch : null })}
6674
initialValue={value.end ? getDateTimeLocalString(new Date(value.end), timezone) : undefined}
6775
/>
68-
</TimerangeFooter>
76+
</TimerangeFields>
77+
78+
<FilterPopupTrailing
79+
clear={{
80+
onClick: () => {
81+
onChange({ start: null, end: null });
82+
onClose();
83+
},
84+
disabled: value.start === null && value.end === null,
85+
}}
86+
/>
6987
</div>
7088
);
7189
};
@@ -100,7 +118,7 @@ function getRawDateString(value: TimerangeValues, timezone: string): string {
100118
}`;
101119
}
102120

103-
const TimerangeFooter = styled.div`
121+
const TimerangeFields = styled.div`
104122
display: flex;
105123
flex-direction: column;
106124
gap: 0.5rem;

0 commit comments

Comments
 (0)