Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: incoming webhook events UI #6317

Merged
merged 6 commits into from
Feb 23, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions frontend/src/component/common/FormTemplate/FormTemplate.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ interface ICreateProps {
formatApiCode?: () => string;
footer?: ReactNode;
compact?: boolean;
showGuidance?: boolean;
}

const StyledContainer = styled('section', {
Expand Down Expand Up @@ -202,6 +203,7 @@ const FormTemplate: React.FC<ICreateProps> = ({
showLink = true,
footer,
compact,
showGuidance = true,
}) => {
const { setToastData } = useToast();
const smallScreen = useMediaQuery(`(max-width:${1099}px)`);
Expand Down Expand Up @@ -252,7 +254,7 @@ const FormTemplate: React.FC<ICreateProps> = ({
return (
<StyledContainer modal={modal} compact={compact}>
<ConditionallyRender
condition={smallScreen}
condition={showGuidance && smallScreen}
show={
<StyledRelativeDiv>
<MobileGuidance
Expand Down Expand Up @@ -293,7 +295,7 @@ const FormTemplate: React.FC<ICreateProps> = ({
/>
</StyledMain>
<ConditionallyRender
condition={!smallScreen}
condition={showGuidance && !smallScreen}
show={
<Guidance
description={description}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,11 @@ import 'vanilla-jsoneditor/themes/jse-theme-dark.css';
import { styled } from '@mui/material';
import UIContext from 'contexts/UIContext';

const JSONEditorThemeWrapper = styled('div')(({ theme }) => ({
type EditorStyle = 'default' | 'sidePanel';

const JSONEditorThemeWrapper = styled('div', {
shouldForwardProp: (prop) => prop !== 'editorStyle',
})<{ editorStyle?: EditorStyle }>(({ theme, editorStyle = 'default' }) => ({
'&.jse-theme-dark': {
'--jse-background-color': theme.palette.background.default,
'--jse-panel-background': theme.palette.background.default,
Expand All @@ -24,9 +28,40 @@ const JSONEditorThemeWrapper = styled('div')(({ theme }) => ({
borderBottomLeftRadius: theme.shape.borderRadius,
borderBottomRightRadius: theme.shape.borderRadius,
},
...(editorStyle === 'sidePanel' && {
'&&&': {
'& .jse-main': {
minHeight: 0,
},
'--jse-main-border': 0,
'& > div': {
height: '100%',
},
'& .jse-focus': {
'--jse-main-border': 0,
},
'& .cm-gutters': {
'--jse-panel-background': 'transparent',
'--jse-panel-border': 'transparent',
},
'& .cm-gutter-lint': {
width: 0,
},
'& .jse-text-mode': {
borderBottomRightRadius: theme.shape.borderRadiusMedium,
},
'& .cm-scroller': {
'--jse-delimiter-color': theme.palette.text.primary,
},
},
}),
Comment on lines +31 to +57
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This felt a tad noisy, but I guess this is where it belongs

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, can't think of a better way of doing this right now, as I want this specific style for this component when used on the new side panel component.

}));

const VanillaJSONEditor: React.FC<JSONEditorPropsOptional> = (props) => {
interface IReactJSONEditorProps extends JSONEditorPropsOptional {
editorStyle?: EditorStyle;
}

const VanillaJSONEditor: React.FC<IReactJSONEditorProps> = (props) => {
const refContainer = useRef<HTMLDivElement | null>(null);
const refEditor = useRef<JSONEditor | null>(null);

Expand Down Expand Up @@ -58,11 +93,12 @@ const VanillaJSONEditor: React.FC<JSONEditorPropsOptional> = (props) => {
return <div ref={refContainer} />;
};

const ReactJSONEditor: React.FC<JSONEditorPropsOptional> = (props) => {
const ReactJSONEditor: React.FC<IReactJSONEditorProps> = (props) => {
const { themeMode } = useContext(UIContext);
return (
<JSONEditorThemeWrapper
className={themeMode === 'dark' ? 'jse-theme-dark' : ''}
editorStyle={props.editorStyle}
>
<VanillaJSONEditor
mainMenuBar={false}
Expand Down
122 changes: 122 additions & 0 deletions frontend/src/component/common/SidePanelList/SidePanelList.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
import { styled } from '@mui/material';
import { ReactNode, useState } from 'react';
import { SidePanelListHeader } from './SidePanelListHeader';
import { SidePanelListItem } from './SidePanelListItem';

const StyledSidePanelListWrapper = styled('div')({
display: 'flex',
flexDirection: 'column',
width: '100%',
});

const StyledSidePanelListBody = styled('div')({
display: 'flex',
flexDirection: 'row',
});

const StyledSidePanelHalf = styled('div')({
display: 'flex',
flexDirection: 'column',
flex: 1,
});

const StyledSidePanelHalfLeft = styled(StyledSidePanelHalf, {
shouldForwardProp: (prop) => prop !== 'height',
})<{ height?: number }>(({ theme, height }) => ({
border: `1px solid ${theme.palette.divider}`,
borderTop: 0,
borderBottomLeftRadius: theme.shape.borderRadiusMedium,
overflow: 'auto',
...(height && { height }),
}));

const StyledSidePanelHalfRight = styled(StyledSidePanelHalf)(({ theme }) => ({
border: `1px solid ${theme.palette.divider}`,
borderTop: 0,
borderLeft: 0,
borderBottomRightRadius: theme.shape.borderRadiusMedium,
}));

type ColumnAlignment = 'start' | 'end' | 'center';

export const StyledSidePanelListColumn = styled('div', {
shouldForwardProp: (prop) => prop !== 'maxWidth' && prop !== 'align',
})<{ maxWidth?: number; align?: ColumnAlignment }>(
({ theme, maxWidth, align = 'start' }) => ({
flex: 1,
padding: theme.spacing(2),
fontSize: theme.fontSizes.smallBody,
justifyContent: align,
...(maxWidth && { maxWidth }),
textAlign: align,
}),
);

export type SidePanelListColumn<T> = {
header: string;
maxWidth?: number;
align?: ColumnAlignment;
cell: (item: T) => ReactNode;
};

interface ISidePanelListProps<T> {
items: T[];
columns: SidePanelListColumn<T>[];
sidePanelHeader: string;
renderContent: (item: T) => ReactNode;
height?: number;
listEnd?: ReactNode;
}

export const SidePanelList = <T extends { id: string | number }>({
items,
columns,
sidePanelHeader,
renderContent,
height,
listEnd,
}: ISidePanelListProps<T>) => {
const [selectedItem, setSelectedItem] = useState<T>(items[0]);

if (items.length === 0) {
return null;
}

const activeItem = selectedItem || items[0];

return (
<StyledSidePanelListWrapper>
<SidePanelListHeader
columns={columns}
sidePanelHeader={sidePanelHeader}
/>
<StyledSidePanelListBody>
<StyledSidePanelHalfLeft height={height}>
{items.map((item) => (
<SidePanelListItem
key={item.id}
selected={activeItem.id === item.id}
onClick={() => setSelectedItem(item)}
>
{columns.map(
({ header, maxWidth, align, cell }) => (
<StyledSidePanelListColumn
key={header}
maxWidth={maxWidth}
align={align}
>
{cell(item)}
</StyledSidePanelListColumn>
),
)}
</SidePanelListItem>
))}
{listEnd}
</StyledSidePanelHalfLeft>
<StyledSidePanelHalfRight>
{renderContent(activeItem)}
</StyledSidePanelHalfRight>
</StyledSidePanelListBody>
</StyledSidePanelListWrapper>
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import { styled } from '@mui/material';
import {
SidePanelListColumn,
StyledSidePanelListColumn,
} from './SidePanelList';

const StyledHeader = styled('div')(({ theme }) => ({
display: 'flex',
flexDirection: 'row',
alignItems: 'center',
borderTopLeftRadius: theme.shape.borderRadiusMedium,
borderTopRightRadius: theme.shape.borderRadiusMedium,
backgroundColor: theme.palette.table.headerBackground,
}));

const StyledHeaderHalf = styled('div')({
display: 'flex',
flex: 1,
});

interface ISidePanelListHeaderProps<T> {
columns: SidePanelListColumn<T>[];
sidePanelHeader: string;
}

export const SidePanelListHeader = <T,>({
columns,
sidePanelHeader,
}: ISidePanelListHeaderProps<T>) => (
<StyledHeader>
<StyledHeaderHalf>
{columns.map(({ header, maxWidth, align }) => (
<StyledSidePanelListColumn
key={header}
maxWidth={maxWidth}
align={align}
>
{header}
</StyledSidePanelListColumn>
))}
</StyledHeaderHalf>
<StyledHeaderHalf>
<StyledSidePanelListColumn>
{sidePanelHeader}
</StyledSidePanelListColumn>
</StyledHeaderHalf>
</StyledHeader>
);
58 changes: 58 additions & 0 deletions frontend/src/component/common/SidePanelList/SidePanelListItem.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import { Button, styled } from '@mui/material';
import { ReactNode } from 'react';

const StyledItemRow = styled('div')(({ theme }) => ({
borderBottom: `1px solid ${theme.palette.divider}`,
}));

const StyledItem = styled(Button, {
shouldForwardProp: (prop) => prop !== 'selected',
})<{ selected: boolean }>(({ theme, selected }) => ({
'&.MuiButton-root': {
width: '100%',
backgroundColor: selected
? theme.palette.secondary.light
: 'transparent',
borderRight: `${theme.spacing(0.5)} solid ${
selected ? theme.palette.background.alternative : 'transparent'
}`,
padding: 0,
borderRadius: 0,
justifyContent: 'start',
transition: 'background-color 0.2s ease',
color: theme.palette.text.primary,
textAlign: 'left',
fontWeight: selected ? theme.fontWeight.bold : theme.fontWeight.medium,
fontSize: theme.fontSizes.smallBody,
overflow: 'auto',
},
'&:hover': {
backgroundColor: selected
? theme.palette.secondary.light
: theme.palette.neutral.light,
},
'&.Mui-disabled': {
pointerEvents: 'auto',
},
'&:focus-visible': {
outline: `2px solid ${theme.palette.primary.main}`,
},
}));

interface ISidePanelListItemProps<T> {
selected: boolean;
onClick: () => void;
children: ReactNode;
}

export const SidePanelListItem = <T,>({
selected,
onClick,
children,
}: ISidePanelListItemProps<T>) => (
<StyledItemRow>
<StyledItem selected={selected} onClick={onClick}>
{children}
</StyledItem>
</StyledItemRow>
);
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,9 @@ import { WeightType } from 'constants/variantTypes';
import { IFeatureVariantEdit } from '../EnvironmentVariantsModal';
import { Delete } from '@mui/icons-material';

const LazyReactJSONEditor = React.lazy(() => import('./ReactJSONEditor'));
const LazyReactJSONEditor = React.lazy(
() => import('component/common/ReactJSONEditor/ReactJSONEditor'),
);

const StyledVariantForm = styled('div')(({ theme }) => ({
position: 'relative',
Expand Down
Loading
Loading