Skip to content

Commit

Permalink
feat: introduce EnvironmentTable component and enhance design table f…
Browse files Browse the repository at this point in the history
…unctionality

Signed-off-by: Amit Amrutiya <[email protected]>
  • Loading branch information
amitamrutiya committed Nov 22, 2024
1 parent 3e5764e commit e797e5e
Show file tree
Hide file tree
Showing 7 changed files with 539 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import AssignmentModal from './AssignmentModal';
import EditButton from './EditButton';
import useDesignAssignment from './hooks/useDesignAssignment';
import { TableHeader, TableRightActionHeader } from './styles';
import { ColumnVisibility } from './types';

export interface DesignTableProps {
workspaceId: string;
Expand Down Expand Up @@ -62,9 +63,6 @@ export interface PublishModalState {
pattern: Partial<Pattern>;
}

export interface ColumnVisibility {
[key: string]: boolean;
}
export interface TableColumn {
name: string;
label: string;
Expand Down
300 changes: 300 additions & 0 deletions src/custom/Workspaces/EnvironmentTable.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,300 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
import ExpandMoreIcon from '@mui/icons-material/ExpandMore';
import { MUIDataTableMeta } from 'mui-datatables';
import React, { useState } from 'react';
import { Accordion, AccordionDetails, AccordionSummary, Typography } from '../../base';
import { DeleteIcon, EnvironmentIcon } from '../../icons';
import { CHARCOAL, SistentThemeProvider } from '../../theme';
import { CustomColumnVisibilityControl } from '../CustomColumnVisibilityControl';
import { CustomTooltip } from '../CustomTooltip';
import { ConditionalTooltip } from '../Helpers/CondtionalTooltip';
import { useWindowDimensions } from '../Helpers/Dimension';
import {
ColView,
updateVisibleColumns
} from '../Helpers/ResponsiveColumns/responsive-coulmns.tsx/responsive-column';
import ResponsiveDataTable, { IconWrapper } from '../ResponsiveDataTable';
import AssignmentModal from './AssignmentModal';
import EditButton from './EditButton';
import TooltipIcon from './TooltipIcon';
import useEnvironmentAssignment from './hooks/useEnvironmentAssignment';
import { CellStyle, CustomBodyRenderStyle, TableHeader, TableRightActionHeader } from './styles';
import { ColumnVisibility } from './types';

interface EnvironmentTableProps {
workspaceId: string;
workspaceName: string;
useGetEnvironmentsOfWorkspaceQuery: any;
useUnassignEnvironmentFromWorkspaceMutation: any;
useAssignEnvironmentToWorkspaceMutation: any;
isRemoveDisabled: boolean;
isAssignDisabled: boolean;
}

const colViews: ColView[] = [
['id', 'na'],
['name', 'xs'],
['description', 'm'],
['organization_id', 'l'],
['created_at', 'na'],
['updated_at', 'xl'],
['actions', 'xs']
];

export const ResizableDescriptionCell = ({ value }: { value: string }) => (
<div style={{ position: 'relative', height: '20px' }}>
<CustomBodyRenderStyle>
<CellStyle>
<CustomTooltip title={value} placement="top-start">
<span style={{ cursor: 'pointer' }}>{value}</span>
</CustomTooltip>
</CellStyle>
</CustomBodyRenderStyle>
</div>
);

const EnvironmentTable: React.FC<EnvironmentTableProps> = ({
workspaceId,
workspaceName,
isRemoveDisabled,
useGetEnvironmentsOfWorkspaceQuery,
useUnassignEnvironmentFromWorkspaceMutation,
useAssignEnvironmentToWorkspaceMutation,
isAssignDisabled
}) => {
const [expanded, setExpanded] = useState<boolean>(true);
const handleAccordionChange = () => {
setExpanded(!expanded);
};
const [page, setPage] = useState<number>(0);
const [pageSize, setPageSize] = useState<number>(10);
const [sortOrder, setSortOrder] = useState<string>('');
const { data: environmentsOfWorkspace } = useGetEnvironmentsOfWorkspaceQuery({
workspaceId,
page: page,
pageSize: pageSize,
order: sortOrder
});
const { width } = useWindowDimensions();
const [unassignEnvironmentFromWorkspace] = useUnassignEnvironmentFromWorkspaceMutation();
const columns: any[] = [
{
name: 'id',
label: 'ID',
options: {
filter: false,
customBodyRender: (value: string) => <ConditionalTooltip value={value} maxLength={10} />
}
},
{
name: 'name',
label: 'Name',
options: {
filter: false,
sort: true,
searchable: true,
customBodyRender: (value: string) => <ConditionalTooltip value={value} maxLength={10} />
}
},
{
name: 'organization_id',
label: 'Organization ID',
options: {
filter: false,
sort: false,
searchable: false
}
},

{
name: 'description',
label: 'Description',
options: {
filter: false,
sort: true,
searchable: true,
customBodyRender: (value: string) => <ResizableDescriptionCell value={value} />
}
},
{
name: 'created_at',
label: 'Created At',
options: {
filter: false,
sort: true,
searchable: true,
setCellHeaderProps: () => {
return { align: 'center' };
}
}
},
{
name: 'updated_at',
label: 'Updated At',
options: {
filter: false,
sort: true,
searchable: true,
setCellHeaderProps: () => {
return { align: 'center' };
}
}
},
{
name: 'actions',
label: 'Actions',
options: {
filter: false,
sort: false,
searchable: false,
customBodyRender: (_: any, tableMeta: MUIDataTableMeta) => (
<IconWrapper disabled={isRemoveDisabled}>
<TooltipIcon
id={`delete_team-${tableMeta.rowIndex}`}
title="Remove Environment"
onClick={() => {
!isRemoveDisabled &&
unassignEnvironmentFromWorkspace({
workspaceId,
environmentId: tableMeta.rowData[0]
});
}}
iconType="delete"
>
<DeleteIcon
height={28}
width={28}
style={{
color: CHARCOAL
}}
/>
</TooltipIcon>
</IconWrapper>
)
}
}
];

const environmentAssignment = useEnvironmentAssignment({
workspaceId,
useGetEnvironmentsOfWorkspaceQuery,
useUnassignEnvironmentFromWorkspaceMutation,
useAssignEnvironmentToWorkspaceMutation
});

const [columnVisibility, setColumnVisibility] = useState<ColumnVisibility>(() => {
const showCols = updateVisibleColumns(colViews, width);
const initialVisibility: ColumnVisibility = {};
columns.forEach((col) => {
initialVisibility[col.name] = showCols[col.name];
});
return initialVisibility;
});

const options = {
filter: false,
responsive: 'standard',
selectableRows: 'none',
count: environmentsOfWorkspace?.total_count,
rowsPerPage: pageSize,
page,
elevation: 0,
serverSide: true,
onTableChange: (action: string, tableState: any) => {
const sortInfo = tableState.announceText ? tableState.announceText.split(' : ') : [];
let order = '';
if (tableState.activeColumn) {
order = `${columns[tableState.activeColumn].name} desc`;
}

switch (action) {
case 'changePage':
setPage(tableState.page);
break;
case 'changeRowsPerPage':
setPageSize(tableState.rowsPerPage);
break;
case 'sort':
if (sortInfo.length == 2) {
if (sortInfo[1] === 'ascending') {
order = `${columns[tableState.activeColumn].name} asc`;
} else {
order = `${columns[tableState.activeColumn].name} desc`;
}
}
if (order !== sortOrder) {
setSortOrder(order);
}
break;
}
}
};
const [tableCols, updateCols] = useState(columns);

return (
<SistentThemeProvider>
<Accordion expanded={expanded} onChange={handleAccordionChange} style={{ margin: 0 }}>
<AccordionSummary
expandIcon={<ExpandMoreIcon />}
sx={{
backgroundColor: 'background.paper'
}}
>
<TableHeader>
<Typography variant="h6" fontWeight={'bold'}>
Assigned Environments
</Typography>
<TableRightActionHeader>
<CustomColumnVisibilityControl
columns={columns}
customToolsProps={{
columnVisibility,
setColumnVisibility
}}
id={'environments-table'}
/>
<EditButton
onClick={environmentAssignment.handleAssignModal}
disabled={isAssignDisabled}
/>
</TableRightActionHeader>
</TableHeader>
</AccordionSummary>
<AccordionDetails style={{ padding: 0 }}>
<ResponsiveDataTable
columns={columns}
data={environmentsOfWorkspace?.environments}
options={options}
colViews={colViews}
tableCols={tableCols}
updateCols={updateCols}
columnVisibility={columnVisibility}
/>
</AccordionDetails>
</Accordion>

<AssignmentModal
open={environmentAssignment.assignModal}
onClose={environmentAssignment.handleAssignModalClose}
title={`Assign Environments to ${workspaceName}`}
headerIcon={<EnvironmentIcon height="40" width="40" fill={'white'} />}
name="Environments"
assignableData={environmentAssignment.data}
handleAssignedData={environmentAssignment.handleAssignData}
originalAssignedData={environmentAssignment.workspaceData}
emptyStateIcon={<EnvironmentIcon height="5rem" width="5rem" fill={'#808080'} />}
handleAssignablePage={environmentAssignment.handleAssignablePage}
handleAssignedPage={environmentAssignment.handleAssignedPage}
originalLeftCount={environmentAssignment.data?.length || 0}
originalRightCount={environmentsOfWorkspace?.total_count || 0}
onAssign={environmentAssignment.handleAssign}
disableTransfer={environmentAssignment.disableTransferButton}
helpText={`Assign Environments to ${workspaceName}`}
isAssignDisabled={!isAssignDisabled}
isRemoveDisabled={!isRemoveDisabled}
/>
</SistentThemeProvider>
);
};

export default EnvironmentTable;
54 changes: 54 additions & 0 deletions src/custom/Workspaces/TooltipIcon.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import { IconButton } from '@mui/material';
import { useTheme } from '../../theme';
import { CustomTooltip } from '../CustomTooltip';
import { IconWrapper } from '../ResponsiveDataTable';

interface TooltipIconProps {
children: React.ReactNode;
onClick: (event: React.MouseEvent<HTMLButtonElement>) => void;
title: string;
iconType: string;
id: string;
style?: React.CSSProperties;
placement?: 'bottom' | 'top' | 'left' | 'right';
disabled?: boolean;
}

const TooltipIcon: React.FC<TooltipIconProps> = ({
children,
onClick,
title,
iconType,
id,
style,
placement,
disabled = false
}) => {
const theme = useTheme();
return (
<CustomTooltip key={id} title={title} placement={placement}>
<IconWrapper disabled={disabled}>
<IconButton
disabled={disabled}
onClick={onClick}
sx={{
'&:hover': {
'& svg': {
fill:
iconType === 'delete'
? theme.palette.error.main
: theme.palette.primary.brand?.default
}
},
...style
}}
disableRipple
>
{children}
</IconButton>
</IconWrapper>
</CustomTooltip>
);
};

export default TooltipIcon;
Loading

0 comments on commit e797e5e

Please sign in to comment.