Skip to content

Commit

Permalink
UI bugs party (#1873)
Browse files Browse the repository at this point in the history
This pull request includes several updates to the frontend web
application, focusing on adding new components, refactoring existing
ones, and updating styles. The most important changes include the
addition of new dropdown components, updates to modals and
notifications, and various refactoring tasks to improve code readability
and maintainability.

### New Components and Features:
* Added `LanguageDropdown` component to the dropdowns directory.
(`frontend/webapp/components/common/dropdowns/language-dropdown/index.tsx`)
* Exported the new `LanguageDropdown` from the dropdowns index.
(`frontend/webapp/components/common/dropdowns/index.ts`)

### Refactoring and Code Simplification:
* Renamed and refactored `build-card-from-action-spec.ts` to
`build-card.ts` and updated its usage.
(`frontend/webapp/containers/main/actions/action-drawer/build-card.ts`,
`frontend/webapp/containers/main/actions/action-drawer/index.tsx`)
[[1]](diffhunk://#diff-dc7aa9e456bfd94740ecdfc9843bd6440126ab0d2c3cea06ccb0c825796d0ba7L3-R3)
[[2]](diffhunk://#diff-5f56695cd2d0ca6bcd28f372653c71d8c4dab572b08715c1f36b7acc5cf50f60R2-R50)
* Moved `AllDrawers` and `AllModals` components from containers to
components directory and updated imports accordingly.
(`frontend/webapp/components/overview/all-drawers/index.tsx`,
`frontend/webapp/components/overview/all-modals/index.tsx`)
[[1]](diffhunk://#diff-bf25245ffa5cb1c7ea54b941a97fc9f53caf28b7154cb4eda9b88c7b6f0944d1L3-R4)
[[2]](diffhunk://#diff-e669f68767681c3105913e5f1a53f358e0f77a9f8c866cef2dbe5c507188380bL3-R4)

### Style Updates:
* Updated background color for `HeaderContainer` in both main and setup
headers to use `darker_grey`.
(`frontend/webapp/components/main/header/index.tsx`,
`frontend/webapp/components/setup/header/index.tsx`)
[[1]](diffhunk://#diff-2c96f91ec30d2116981a9c0a562820ff9fd87c8292cb5dca11a45d6fb2ac6c04L19-R19)
[[2]](diffhunk://#diff-b797fa218a1303de084fa2eed814d4512fb9cb215a914c0adfaee658d7558db9L21-R21)

### Modals and Notifications:
* Updated `CancelWarning` and `DeleteWarning` modal button texts to be
more descriptive.
(`frontend/webapp/components/modals/cancel-warning/index.tsx`,
`frontend/webapp/components/modals/delete-warning/index.tsx`)
[[1]](diffhunk://#diff-c197a79280b54ef188b35a5e804a91ff95db0b8137b0f2c7f8dacd545a4f4650L18-R20)
[[2]](diffhunk://#diff-4f8fac3da993d379d6710a6607b6f25708649cb2da5b4a5f433f8e62dde1d03fL27-R32)
* Refactored `ToastList` component and updated its export method.
(`frontend/webapp/components/notification/toast-list.tsx`,
`frontend/webapp/components/notification/index.ts`)
[[1]](diffhunk://#diff-c6ead7587d1e5c52295c921dde2a1a5b9b06977ab3900c7dbf475c47cc1c664cL20-R20)
[[2]](diffhunk://#diff-b0bf2162cde911ad526b7496ce073fa39b64f7f7e030241c3a59610d7dea2081R1-R4)

### Utility and Hook Updates:
* Added `BACKEND_BOOLEAN` utility to the `ErrorDropdown` component for
better readability and consistency.
(`frontend/webapp/components/common/dropdowns/error-dropdown/index.tsx`)
[[1]](diffhunk://#diff-587e573502656d446fed8f02b5190cd43c67a9261dcb74cd077f37cbe8b93839R4)
[[2]](diffhunk://#diff-587e573502656d446fed8f02b5190cd43c67a9261dcb74cd077f37cbe8b93839L24-R25)

These changes collectively improve the structure, readability, and
functionality of the frontend web application.

---------

Co-authored-by: Alon Braymok <138359965+alonkeyval@users.noreply.github.com>
  • Loading branch information
BenElferink and alonkeyval authored Nov 28, 2024
1 parent 921a378 commit 1205f01
Show file tree
Hide file tree
Showing 89 changed files with 1,321 additions and 960 deletions.
10 changes: 7 additions & 3 deletions frontend/webapp/app/(overview)/overview/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,17 @@
import React from 'react';
import dynamic from 'next/dynamic';

const OverviewDataFlowContainer = dynamic(() => import('@/containers/main/overview/overview-data-flow'), {
ssr: false,
});
const ToastList = dynamic(() => import('@/components/notification/toast-list'), { ssr: false });
const AllDrawers = dynamic(() => import('@/components/overview/all-drawers'), { ssr: false });
const AllModals = dynamic(() => import('@/components/overview/all-modals'), { ssr: false });
const OverviewDataFlowContainer = dynamic(() => import('@/containers/main/overview/overview-data-flow'), { ssr: false });

export default function MainPage() {
return (
<>
<ToastList />
<AllDrawers />
<AllModals />
<OverviewDataFlowContainer />
</>
);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import React, { useMemo } from 'react';
import { useSourceCRUD } from '@/hooks';
import { DropdownOption } from '@/types';
import { BACKEND_BOOLEAN } from '@/utils';
import { Dropdown } from '@/reuseable-components';

interface Props {
Expand All @@ -21,7 +22,7 @@ export const ErrorDropdown: React.FC<Props> = ({ title = 'Error Message', value,

sources.forEach(({ instrumentedApplicationDetails: { conditions } }) => {
conditions.forEach(({ type, status, message }) => {
if (status === 'False' && !payload.find((opt) => opt.value === message)) {
if (status === BACKEND_BOOLEAN.FALSE && !payload.find((opt) => opt.id === message)) {
payload.push({ id: message, value: message });
}
});
Expand Down
1 change: 1 addition & 0 deletions frontend/webapp/components/common/dropdowns/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
export * from './error-dropdown';
export * from './language-dropdown';
export * from './monitor-dropdown';
export * from './namespace-dropdown';
export * from './type-dropdown';
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import React, { useMemo } from 'react';
import { useSourceCRUD } from '@/hooks';
import { DropdownOption } from '@/types';
import { Dropdown } from '@/reuseable-components';

interface Props {
title?: string;
value?: DropdownOption[];
onSelect: (val: DropdownOption) => void;
onDeselect: (val: DropdownOption) => void;
isMulti?: boolean;
required?: boolean;
showSearch?: boolean;
}

export const LanguageDropdown: React.FC<Props> = ({ title = 'Programming Languages', value, onSelect, onDeselect, ...props }) => {
const { sources } = useSourceCRUD();

const options = useMemo(() => {
const payload: DropdownOption[] = [];

sources.forEach(({ instrumentedApplicationDetails: { containers } }) => {
containers.forEach(({ language }) => {
if (!payload.find((opt) => opt.id === language)) {
payload.push({ id: language, value: language });
}
});
});

return payload.sort((a, b) => a.id.localeCompare(b.id));
}, [sources]);

return <Dropdown title={title} placeholder='All' options={options} value={value} onSelect={onSelect} onDeselect={onDeselect} {...props} />;
};
2 changes: 1 addition & 1 deletion frontend/webapp/components/main/header/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ const Flex = styled.div`
const HeaderContainer = styled(Flex)`
width: 100%;
padding: 12px 0;
background-color: ${({ theme }) => theme.colors.dark_grey};
background-color: ${({ theme }) => theme.colors.darker_grey};
border-bottom: 1px solid rgba(249, 249, 249, 0.16);
`;

Expand Down
4 changes: 2 additions & 2 deletions frontend/webapp/components/modals/cancel-warning/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@ const CancelWarning: React.FC<Props> = ({ isOpen, noOverlay, name, onApprove, on
isOpen={isOpen}
noOverlay={noOverlay}
title={`Cancel${name ? ` ${name}` : ''}`}
description='Are you sure you want to discard your changes?'
description='Are you sure you want to cancel?'
approveButton={{
text: 'Cancel',
text: 'Confirm',
variant: 'warning',
onClick: onApprove,
}}
Expand Down
4 changes: 2 additions & 2 deletions frontend/webapp/components/modals/delete-warning/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,12 @@ const DeleteWarning: React.FC<Props> = ({ isOpen, noOverlay, name, note, onAppro
description='Are you sure you want to delete?'
note={note}
approveButton={{
text: 'Delete',
text: 'Confirm',
variant: 'danger',
onClick: onApprove,
}}
denyButton={{
text: 'Cancel',
text: 'Go Back',
onClick: onDeny,
}}
/>
Expand Down
4 changes: 4 additions & 0 deletions frontend/webapp/components/notification/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export * from './notification-manager';
import ToastList from './toast-list';

export { ToastList };
2 changes: 0 additions & 2 deletions frontend/webapp/components/notification/index.tsx

This file was deleted.

4 changes: 3 additions & 1 deletion frontend/webapp/components/notification/toast-list.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ const Container = styled.div`
min-width: 600px;
`;

export const ToastList: React.FC = () => {
const ToastList: React.FC = () => {
const { notifications } = useNotificationStore();

return (
Expand Down Expand Up @@ -59,3 +59,5 @@ const Toast: React.FC<Notification> = (props) => {
/>
);
};

export default ToastList;
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
import React from 'react';
import { useDrawerStore } from '@/store';
import { SourceDrawer } from '../../sources';
import { ActionDrawer } from '../../actions';
import { OVERVIEW_ENTITY_TYPES } from '@/types';
import { DestinationDrawer } from '../../destinations';
import { RuleDrawer } from '../../instrumentation-rules';
import { ActionDrawer, DestinationDrawer, RuleDrawer, SourceDrawer } from '@/containers';

const AllDrawers = () => {
const selected = useDrawerStore(({ selectedItem }) => selectedItem);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
import React from 'react';
import { useModalStore } from '@/store';
import { ActionModal } from '../../actions';
import { OVERVIEW_ENTITY_TYPES } from '@/types';
import { DestinationModal } from '../../destinations';
import { RuleModal } from '../../instrumentation-rules';
import { AddSourceModal } from '../../sources/choose-sources/choose-source-modal';
import { ActionModal, AddSourceModal, DestinationModal, RuleModal } from '@/containers';

const AllModals = () => {
const selected = useModalStore(({ currentModal }) => currentModal);
Expand Down
6 changes: 6 additions & 0 deletions frontend/webapp/components/overview/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
export * from './add-entity';
import AllDrawers from './all-drawers';
import AllModals from './all-modals';
export * from './monitors-legend';

export { AllDrawers, AllModals };
2 changes: 0 additions & 2 deletions frontend/webapp/components/overview/index.tsx

This file was deleted.

2 changes: 1 addition & 1 deletion frontend/webapp/components/setup/header/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ const HeaderContainer = styled.div`
justify-content: space-between;
padding: 0 24px 0 32px;
align-items: center;
background-color: ${({ theme }) => theme.colors.dark_grey};
background-color: ${({ theme }) => theme.colors.darker_grey};
border-bottom: 1px solid rgba(249, 249, 249, 0.16);
height: 80px;
`;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import type { ActionDataParsed } from '@/types';

const buildCardFromActionSpec = (action: ActionDataParsed) => {
const buildCard = (action: ActionDataParsed) => {
const {
type,
spec: {
Expand All @@ -17,14 +17,14 @@ const buildCardFromActionSpec = (action: ActionDataParsed) => {
sampling_percentage,
endpoints_filters,
},
} = action as ActionDataParsed;
} = action;

const arr = [
{ title: 'Type', value: type || 'N/A' },
{ title: 'Type', value: type },
{ title: 'Status', value: String(!disabled) },
{ title: 'Monitors', value: signals.map((str) => str.toLowerCase()).join(', ') },
{ title: 'Name', value: actionName || 'N/A' },
{ title: 'Notes', value: notes || 'N/A' },
{ title: 'Monitors', value: signals.map((str) => str.toLowerCase()).join(', ') },
];

if (clusterAttributes) {
Expand Down Expand Up @@ -91,4 +91,4 @@ const buildCardFromActionSpec = (action: ActionDataParsed) => {
return arr;
};

export default buildCardFromActionSpec;
export default buildCard;
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { safeJsonParse } from '@/utils';
import type { ActionDataParsed, ActionInput } from '@/types';

const buildDrawerItem = (id: string, formData: ActionInput, drawerItem: ActionDataParsed): ActionDataParsed => {
const { type, name, notes, signals, disable, details } = formData;
const {} = drawerItem;

return {
id,
type,
spec: {
actionName: name,
notes: notes,
signals: signals,
disabled: disable,
...safeJsonParse(details, {}),
},
};
};

export default buildDrawerItem;
78 changes: 44 additions & 34 deletions frontend/webapp/containers/main/actions/action-drawer/index.tsx
Original file line number Diff line number Diff line change
@@ -1,30 +1,53 @@
import React, { useMemo, useState } from 'react';
import buildCard from './build-card';
import { ActionFormBody } from '../';
import styled from 'styled-components';
import { getActionIcon } from '@/utils';
import { useDrawerStore } from '@/store';
import { CardDetails } from '@/components';
import type { ActionDataParsed } from '@/types';
import { ACTION, getActionIcon } from '@/utils';
import buildDrawerItem from './build-drawer-item';
import { useActionCRUD, useActionFormData } from '@/hooks';
import OverviewDrawer from '../../overview/overview-drawer';
import { ACTION_OPTIONS } from '../action-modal/action-options';
import buildCardFromActionSpec from './build-card-from-action-spec';
import { OVERVIEW_ENTITY_TYPES, type ActionDataParsed } from '@/types';

interface Props {}

const ActionDrawer: React.FC<Props> = () => {
const selectedItem = useDrawerStore(({ selectedItem }) => selectedItem);
const FormContainer = styled.div`
width: 100%;
height: 100%;
max-height: calc(100vh - 220px);
overflow: overlay;
overflow-y: auto;
`;

export const ActionDrawer: React.FC<Props> = () => {
const { selectedItem, setSelectedItem } = useDrawerStore();
const { formData, formErrors, handleFormChange, resetFormData, validateForm, loadFormWithDrawerItem } = useActionFormData();

const { updateAction, deleteAction } = useActionCRUD({
onSuccess: (type) => {
setIsEditing(false);
setIsFormDirty(false);

if (type === ACTION.DELETE) {
setSelectedItem(null);
} else {
const { item } = selectedItem as { item: ActionDataParsed };
const { id } = item;
setSelectedItem({ id, type: OVERVIEW_ENTITY_TYPES.ACTION, item: buildDrawerItem(id, formData, item) });
}
},
});

const [isEditing, setIsEditing] = useState(false);
const [isFormDirty, setIsFormDirty] = useState(false);

const { formData, handleFormChange, resetFormData, validateForm, loadFormWithDrawerItem } = useActionFormData();
const { updateAction, deleteAction } = useActionCRUD();

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

const { item } = selectedItem as { item: ActionDataParsed };
const arr = buildCardFromActionSpec(item);
const arr = buildCard(item);

return arr;
}, [selectedItem]);
Expand All @@ -49,37 +72,33 @@ const ActionDrawer: React.FC<Props> = () => {
}, [selectedItem, isEditing]);

if (!selectedItem?.item) return null;
const { id, item } = selectedItem;
const { id, item } = selectedItem as { id: string; item: ActionDataParsed };

const handleEdit = (bool?: boolean) => {
if (typeof bool === 'boolean') {
setIsEditing(bool);
} else {
setIsEditing(true);
}
setIsEditing(typeof bool === 'boolean' ? bool : true);
};

const handleCancel = () => {
resetFormData();
setIsEditing(false);
setIsFormDirty(false);
};

const handleDelete = async () => {
await deleteAction(id as string, (item as ActionDataParsed).type);
await deleteAction(id, item.type);
};

const handleSave = async (newTitle: string) => {
if (validateForm({ withAlert: true })) {
const title = newTitle !== (item as ActionDataParsed).type ? newTitle : '';

await updateAction(id as string, { ...formData, name: title });
if (validateForm({ withAlert: true, alertTitle: ACTION.UPDATE })) {
const title = newTitle !== item.type ? newTitle : '';
handleFormChange('name', title);
await updateAction(id, { ...formData, name: title });
}
};

return (
<OverviewDrawer
title={(item as ActionDataParsed).spec.actionName || (item as ActionDataParsed).type}
imageUri={getActionIcon((item as ActionDataParsed).type)}
title={item.spec.actionName || item.type}
imageUri={getActionIcon(item.type)}
isEdit={isEditing}
isFormDirty={isFormDirty}
onEdit={handleEdit}
Expand All @@ -93,25 +112,16 @@ const ActionDrawer: React.FC<Props> = () => {
isUpdate
action={thisAction}
formData={formData}
formErrors={formErrors}
handleFormChange={(...params) => {
setIsFormDirty(true);
handleFormChange(...params);
}}
/>
</FormContainer>
) : (
<CardDetails data={cardData} />
<CardDetails title='Action Details' data={cardData} />
)}
</OverviewDrawer>
);
};

export { ActionDrawer };

const FormContainer = styled.div`
width: 100%;
height: 100%;
max-height: calc(100vh - 220px);
overflow: overlay;
overflow-y: auto;
`;
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,12 @@ import { KeyValueInputsList } from '@/reuseable-components';
type Props = {
value: string;
setValue: (value: string) => void;
errorMessage?: string;
};

type Parsed = AddClusterInfoSpec;

const AddClusterInfo: React.FC<Props> = ({ value, setValue }) => {
const AddClusterInfo: React.FC<Props> = ({ value, setValue, errorMessage }) => {
const mappedValue = useMemo(
() =>
safeJsonParse<Parsed>(value, { clusterAttributes: [] }).clusterAttributes.map((obj) => ({
Expand All @@ -33,7 +34,7 @@ const AddClusterInfo: React.FC<Props> = ({ value, setValue }) => {
setValue(str);
};

return <KeyValueInputsList title='Resource Attributes' required value={mappedValue} onChange={handleChange} />;
return <KeyValueInputsList title='Resource Attributes' value={mappedValue} onChange={handleChange} required errorMessage={errorMessage} />;
};

export default AddClusterInfo;
Loading

0 comments on commit 1205f01

Please sign in to comment.