Skip to content

Commit

Permalink
Merge branch 'main' into gen-2074
Browse files Browse the repository at this point in the history
  • Loading branch information
BenElferink authored Dec 19, 2024
2 parents 1a7021f + 4a1debf commit 1ce6bff
Show file tree
Hide file tree
Showing 12 changed files with 90 additions and 59 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,6 @@ export const ActionDrawer: React.FC<Props> = () => {
ACTION_OPTIONS.find(({ id }) => id === 'attributes')?.items?.find(({ type }) => type === item.type) ||
ACTION_OPTIONS.find(({ id }) => id === 'sampler')?.items?.find(({ type }) => type === item.type);

if (!found) return undefined;

loadFormWithDrawerItem(selectedItem);

return found;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ const buildMonitorsList = (exportedSignals: ExportedSignals): string =>
.filter((key) => exportedSignals[key])
.join(', ');

const buildCard = (destination: ActualDestination, destinationTypeDetails: DestinationDetailsResponse['destinationTypeDetails']) => {
const buildCard = (destination: ActualDestination, destinationTypeDetails?: DestinationDetailsResponse['destinationTypeDetails']) => {
const { exportedSignals, destinationType, fields } = destination;

const arr: DataCardRow[] = [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,24 +56,22 @@ export const DestinationDrawer: React.FC<Props> = () => {
const [isFormDirty, setIsFormDirty] = useState(false);

const cardData = useMemo(() => {
if (!selectedItem || !destinationTypeDetails) return [];
if (!selectedItem) return [];

const { item } = selectedItem as { item: ActualDestination };
const arr = buildCard(item, destinationTypeDetails);

return arr;
}, [selectedItem, destinationTypeDetails]);

const thisDestination = useMemo(() => {
const thisDestinationType = useMemo(() => {
if (!destinationTypes.length || !selectedItem || !isEditing) {
resetFormData();
return undefined;
}

const { item } = selectedItem as { item: ActualDestination };
const found = destinationTypes.map(({ items }) => items.filter(({ type }) => type === item.destinationType.type)).filter((arr) => !!arr.length)[0][0];

if (!found) return undefined;
const found = destinationTypes.map(({ items }) => items.filter(({ type }) => type === item.destinationType.type)).filter((arr) => !!arr.length)?.[0]?.[0];

loadFormWithDrawerItem(selectedItem);

Expand Down Expand Up @@ -119,7 +117,7 @@ export const DestinationDrawer: React.FC<Props> = () => {
<FormContainer>
<DestinationFormBody
isUpdate
destination={thisDestination}
destination={thisDestinationType}
formData={formData}
formErrors={formErrors}
validateForm={validateForm}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,6 @@ export const RuleDrawer: React.FC<Props> = () => {
const { item } = selectedItem as { item: InstrumentationRuleSpecMapped };
const found = RULE_OPTIONS.find(({ type }) => type === item.type);

if (!found) return undefined;

loadFormWithDrawerItem(selectedItem);

return found;
Expand Down
5 changes: 4 additions & 1 deletion frontend/webapp/hooks/sources/useSourceFormData.ts
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,10 @@ export const useSourceFormData = (params?: UseSourceFormDataParams): UseSourceFo
} else {
setSelectedSources((prev) => ({ ...prev, [namespace]: bool ? nsAvailableSources : [] }));
setSelectAllForNamespace('');
if (!!nsAvailableSources.length && !namespaceWasSelected.current) setSelectedNamespace('');

// Note: if we want to select all, but not open the expanded view, we can use the following:
// if (!!nsAvailableSources.length && !namespaceWasSelected.current) setSelectedNamespace('');

namespaceWasSelected.current = false;
}
} else {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React, { useState, type ChangeEvent, type KeyboardEvent, type FC } from 'react';
import { SVG } from '@/assets';
import { Text } from '../text';
import styled from 'styled-components';
import React, { useState, ChangeEvent, KeyboardEvent, FC } from 'react';

export interface Option {
id: string;
Expand Down Expand Up @@ -43,6 +43,8 @@ export const AutocompleteInput: FC<Props> = ({ placeholder = 'Type to search...'
const Icon = selectedOption?.icon;

const handleChange = (e: ChangeEvent<HTMLInputElement>) => {
e.stopPropagation();

const input = e.target.value;
const filtered = filterOptions(options, input);
const matched = filtered.length === 1 && filtered[0].label === input ? filtered[0] : undefined;
Expand All @@ -69,8 +71,11 @@ export const AutocompleteInput: FC<Props> = ({ placeholder = 'Type to search...'
};

const handleKeyDown = (e: KeyboardEvent<HTMLInputElement>) => {
e.stopPropagation();

// Flatten the options to handle keyboard navigation - TODO: Refactor this
return;

const flatOptions = flattenOptions(filteredOptions);
if (e.key === 'ArrowDown' && activeIndex < flatOptions.length - 1) {
setActiveIndex(activeIndex + 1);
Expand Down
17 changes: 15 additions & 2 deletions frontend/webapp/reuseable-components/input-list/index.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { useEffect, useMemo, useRef, useState } from 'react';
import React, { type KeyboardEventHandler, useEffect, useMemo, useRef, useState } from 'react';
import styled from 'styled-components';
import { PlusIcon, TrashIcon } from '@/assets';
import { Button, FieldError, FieldLabel, Input, Text } from '@/reuseable-components';
Expand Down Expand Up @@ -103,6 +103,10 @@ const InputList: React.FC<InputListProps> = ({ initialValues = [], value, onChan
});
};

const handleKeyDown: KeyboardEventHandler<HTMLInputElement> = (e) => {
e.stopPropagation();
};

// Check if any input field is empty
const isAddButtonDisabled = rows.some((input) => input.trim() === '');
const isDelButtonDisabled = rows.length <= 1;
Expand All @@ -114,7 +118,16 @@ const InputList: React.FC<InputListProps> = ({ initialValues = [], value, onChan
<ListContainer>
{rows.map((val, idx) => (
<RowWrapper key={`input-list-${idx}`}>
<Input value={val} onChange={(e) => handleInputChange(e.target.value, idx)} hasError={!!errorMessage} autoFocus={!val && rows.length > 1 && idx === rows.length - 1} />
<Input
value={val}
onChange={(e) => {
e.stopPropagation();
handleInputChange(e.target.value, idx);
}}
onKeyDown={handleKeyDown}
hasError={!!errorMessage}
autoFocus={!val && rows.length > 1 && idx === rows.length - 1}
/>
<DeleteButton disabled={isDelButtonDisabled} onClick={() => handleDeleteInput(idx)}>
<TrashIcon />
</DeleteButton>
Expand Down
12 changes: 10 additions & 2 deletions frontend/webapp/reuseable-components/input-table/index.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { useState, useEffect, useRef, useMemo } from 'react';
import React, { useState, useEffect, useRef, useMemo, type KeyboardEventHandler } from 'react';
import styled from 'styled-components';
import { PlusIcon, TrashIcon } from '@/assets';
import { Button, FieldError, FieldLabel, Input, Text } from '@/reuseable-components';
Expand Down Expand Up @@ -104,6 +104,10 @@ export const InputTable: React.FC<Props> = ({ columns, initialValues = [], value
});
};

const handleKeyDown: KeyboardEventHandler<HTMLInputElement> = (e) => {
e.stopPropagation();
};

// Check if any key or value field is empty
const isAddButtonDisabled = rows.some((row) => !!Object.values(row).filter((val) => !val).length);
const isDelButtonDisabled = rows.length <= 1;
Expand Down Expand Up @@ -139,7 +143,11 @@ export const InputTable: React.FC<Props> = ({ columns, initialValues = [], value
type={type}
placeholder={placeholder}
value={value}
onChange={({ target: { value: val } }) => handleChange(keyName, type === 'number' ? Number(val) : val, idx)}
onChange={({ stopPropagation, target: { value: val } }) => {
stopPropagation();
handleChange(keyName, type === 'number' ? Number(val) : val, idx);
}}
onKeyDown={handleKeyDown}
autoFocus={!value && rows.length > 1 && idx === rows.length - 1 && innerIdx === 0}
style={{ maxWidth, paddingLeft: 10 }}
hasError={!!errorMessage && (!required || (required && !value))}
Expand Down
23 changes: 13 additions & 10 deletions frontend/webapp/reuseable-components/input/index.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
import React, { useState, forwardRef } from 'react';
import Image from 'next/image';
import React, { useState, forwardRef, type ChangeEvent, type KeyboardEventHandler } from 'react';
import theme from '@/styles/theme';
import styled, { css } from 'styled-components';
import { EyeClosedIcon, EyeOpenIcon, SVG } from '@/assets';
import { FieldError, FieldLabel } from '@/reuseable-components';
import theme from '@/styles/theme';

interface InputProps extends React.InputHTMLAttributes<HTMLInputElement> {
title?: string;
Expand Down Expand Up @@ -122,11 +121,14 @@ const Input = forwardRef<HTMLInputElement, InputProps>(
const [revealSecret, setRevealSecret] = useState(false);
const [value, setValue] = useState<string>(initialValue || '');

const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {
const handleInputChange = (e: ChangeEvent<HTMLInputElement>) => {
e.stopPropagation();
setValue(e.target.value);
if (onChange) {
onChange(e);
}
onChange?.(e);
};

const handleKeyDown: KeyboardEventHandler<HTMLInputElement> = (e) => {
e.stopPropagation();
};

return (
Expand All @@ -145,13 +147,14 @@ const Input = forwardRef<HTMLInputElement, InputProps>(
) : null}

<StyledInput
ref={ref} // Pass ref to the StyledInput
ref={ref}
data-id={name}
name={name}
type={revealSecret ? 'text' : type}
$hasIcon={!!Icon || isSecret}
name={name}
value={value}
onChange={handleInputChange}
type={revealSecret ? 'text' : type}
onKeyDown={handleKeyDown}
{...props}
/>

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { useState, useEffect, useRef, useMemo } from 'react';
import React, { useState, useEffect, useRef, useMemo, type KeyboardEventHandler } from 'react';
import theme from '@/styles/theme';
import styled from 'styled-components';
import { ArrowIcon, PlusIcon, TrashIcon } from '@/assets';
Expand Down Expand Up @@ -111,6 +111,10 @@ export const KeyValueInputsList: React.FC<KeyValueInputsListProps> = ({ initialK
});
};

const handleKeyDown: KeyboardEventHandler<HTMLInputElement> = (e) => {
e.stopPropagation();
};

// Check if any key or value field is empty
const isAddButtonDisabled = rows.some(({ key, value }) => key.trim() === '' || value.trim() === '');
const isDelButtonDisabled = rows.length <= 1;
Expand All @@ -125,7 +129,11 @@ export const KeyValueInputsList: React.FC<KeyValueInputsListProps> = ({ initialK
<Input
placeholder='Attribute name'
value={key}
onChange={(e) => handleChange('key', e.target.value, idx)}
onChange={(e) => {
e.stopPropagation();
handleChange('key', e.target.value, idx);
}}
onKeyDown={handleKeyDown}
hasError={!!errorMessage && (!required || (required && !key))}
autoFocus={!value && rows.length > 1 && idx === rows.length - 1}
/>
Expand All @@ -135,7 +143,11 @@ export const KeyValueInputsList: React.FC<KeyValueInputsListProps> = ({ initialK
<Input
placeholder='Attribute value'
value={value}
onChange={(e) => handleChange('value', e.target.value, idx)}
onChange={(e) => {
e.stopPropagation();
handleChange('value', e.target.value, idx);
}}
onKeyDown={handleKeyDown}
hasError={!!errorMessage && (!required || (required && !value))}
autoFocus={false}
/>
Expand Down
18 changes: 7 additions & 11 deletions frontend/webapp/reuseable-components/tab-list/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ interface TabProps {
icon: SVG;
selected: boolean;
disabled?: boolean;
onClick: () => void;
onClick?: () => void;
}

// Define types for the TabList component props
Expand All @@ -21,18 +21,18 @@ interface TabListProps {
}

// Styled-components for Tab and TabList
const TabContainer = styled.div<{ $selected: TabProps['selected']; $disabled: TabProps['disabled'] }>`
const TabContainer = styled.div<{ $selected: TabProps['selected']; $disabled: TabProps['disabled']; $noClick: boolean }>`
display: flex;
align-items: center;
padding: 10px 12px;
border-radius: 32px;
cursor: ${({ $disabled }) => ($disabled ? 'not-allowed' : 'pointer')};
background-color: ${({ $selected, theme }) => ($selected ? theme.colors.majestic_blue + hexPercentValues['024'] : theme.colors.card)};
cursor: ${({ $noClick, $disabled }) => ($noClick ? 'unset' : $disabled ? 'not-allowed' : 'pointer')};
background-color: ${({ $noClick, $selected, theme }) => ($noClick ? 'transparent' : $selected ? theme.colors.majestic_blue + hexPercentValues['024'] : theme.colors.card)};
opacity: ${({ $disabled }) => ($disabled ? 0.5 : 1)};
transition: background-color 0.3s, color 0.3s;
&:hover {
background-color: ${({ $disabled, theme }) => ($disabled ? 'none' : theme.colors.majestic_blue + hexPercentValues['024'])};
background-color: ${({ $noClick, $disabled, theme }) => ($noClick || $disabled ? 'none' : theme.colors.majestic_blue + hexPercentValues['024'])};
}
svg {
Expand All @@ -45,11 +45,10 @@ const TabListContainer = styled.div`
gap: 8px;
`;

// Tab component
const Tab: React.FC<TabProps> = ({ title, tooltip, icon: Icon, selected, disabled, onClick }) => {
return (
<Tooltip text={tooltip}>
<TabContainer $selected={selected} $disabled={disabled} onClick={onClick}>
<TabContainer $selected={selected} $disabled={disabled} $noClick={!onClick} onClick={onClick}>
<Icon size={14} />
<Text size={14}>{title}</Text>
</TabContainer>
Expand All @@ -62,7 +61,6 @@ const TABS = [
title: 'Overview',
icon: OverviewIcon,
selected: true,
onClick: () => {},
},
// {
// title: 'Service Map',
Expand All @@ -82,7 +80,7 @@ const TABS = [
// },
];

const TabList: React.FC<TabListProps> = ({ tabs = TABS }) => {
export const TabList: React.FC<TabListProps> = ({ tabs = TABS }) => {
return (
<TabListContainer>
{tabs.map((tab) => (
Expand All @@ -91,5 +89,3 @@ const TabList: React.FC<TabListProps> = ({ tabs = TABS }) => {
</TabListContainer>
);
};

export { TabList };
33 changes: 15 additions & 18 deletions frontend/webapp/reuseable-components/textarea/index.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { useRef } from 'react';
import React, { type ChangeEventHandler, type KeyboardEventHandler, useRef } from 'react';
import styled, { css } from 'styled-components';
import { FieldError, FieldLabel } from '@/reuseable-components';

Expand Down Expand Up @@ -79,39 +79,36 @@ const StyledTextArea = styled.textarea`
}
`;

const TextArea: React.FC<TextAreaProps> = ({ errorMessage, title, tooltip, required, onChange, name, ...props }) => {
export const TextArea: React.FC<TextAreaProps> = ({ errorMessage, title, tooltip, required, onChange, name, ...props }) => {
const ref = useRef<HTMLTextAreaElement>(null);

const resize = () => {
const resize = (focused: boolean) => {
// this is to auto-resize the textarea according to the number of rows typed
if (ref.current) {
ref.current.style.height = 'auto';
ref.current.style.height = `${ref.current.scrollHeight}px`;
if (focused) ref.current.style.height = `${ref.current.scrollHeight}px`;
}
};

const handleChange: ChangeEventHandler<HTMLTextAreaElement> = (e) => {
e.stopPropagation();
resize(true);
onChange?.(e);
};

const handleKeyDown: KeyboardEventHandler<HTMLTextAreaElement> = (e) => {
e.stopPropagation();
};

return (
<Container>
<FieldLabel title={title} required={required} tooltip={tooltip} />

<InputWrapper $disabled={props.disabled} $hasError={!!errorMessage} $isActive={!!props.autoFocus}>
<StyledTextArea
ref={ref}
data-id={name}
name={name}
onFocus={resize}
onBlur={resize}
onChange={(e) => {
resize();
onChange?.(e);
}}
{...props}
/>
<StyledTextArea ref={ref} data-id={name} name={name} onFocus={() => resize(true)} onBlur={() => resize(false)} onChange={handleChange} onKeyDown={handleKeyDown} {...props} />
</InputWrapper>

{!!errorMessage && <FieldError>{errorMessage}</FieldError>}
</Container>
);
};

export { TextArea };

0 comments on commit 1ce6bff

Please sign in to comment.