Skip to content

Commit

Permalink
feat add column improvements (#792)
Browse files Browse the repository at this point in the history
  • Loading branch information
chavda-bhavik authored Sep 11, 2024
2 parents 70e1881 + e8ba11b commit db15191
Show file tree
Hide file tree
Showing 7 changed files with 129 additions and 66 deletions.
1 change: 1 addition & 0 deletions apps/web/components/import-feed/History.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ export function History() {
return item.originalFileName ? (
<Tooltip label="Download original file" withArrow>
<ActionIcon
radius={0}
variant="transparent"
onClick={() => downloadOriginalFile([item._id, item.originalFileName])}
>
Expand Down
123 changes: 71 additions & 52 deletions apps/web/components/imports/schema/ColumnsTable.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,20 @@
import { useEffect, useRef, useState } from 'react';
import { useEffect, useState } from 'react';
import { Controller } from 'react-hook-form';
import { ActionIcon, Flex, Tooltip, TextInput as Input, Group, Badge, SelectItem } from '@mantine/core';
import {
ActionIcon,
Flex,
Tooltip,
TextInput as Input,
Group,
Badge,
SelectItem,
Text,
useMantineTheme,
LoadingOverlay,
} from '@mantine/core';

import { colors as appColors } from '@config';
import { useSchema } from '@hooks/useSchema';
import { colors } from '@config';
import { ColumnTypesEnum, IColumn } from '@impler/shared';

import { Button } from '@ui/button';
Expand All @@ -23,7 +34,7 @@ interface ColumnsTableProps {
}

export function ColumnsTable({ templateId }: ColumnsTableProps) {
const ValidationRef = useRef(false);
const { colors: themeColors } = useMantineTheme();
const { getColumnTypes } = useSchema({ templateId });
const [columnTypes, setColumnType] = useState<SelectItem[]>(getColumnTypes());

Expand All @@ -33,10 +44,12 @@ export function ColumnsTable({ templateId }: ColumnsTableProps) {
register,
getValues,
showAddRow,
handleSubmit,
onMoveColumns,
validationRef,
setShowAddRow,
onCancelAddColumn,
onEditColumnClick,
onAddColumnSubmit,
onValidationsClick,
onDeleteColumnClick,
isColumnCreateLoading,
Expand All @@ -45,6 +58,7 @@ export function ColumnsTable({ templateId }: ColumnsTableProps) {
});

const onValidationsButtonClick = () => {
validationRef.current = true;
const values = getValues();
onValidationsClick({ ...values, key: values.key || values.name });
};
Expand All @@ -54,16 +68,9 @@ export function ColumnsTable({ templateId }: ColumnsTableProps) {
}, []);

return (
<form
onSubmit={(e) => {
handleSubmit();
e.preventDefault();
ValidationRef.current = false;
}}
id="columns"
>
<form id="columns" onSubmit={onAddColumnSubmit}>
<DraggableTable<IColumn>
emptyDataText='No columns found click on "+" to add new column'
emptyDataText='No columns found click on "+" to add a new column'
headings={[
{
title: 'Name',
Expand All @@ -79,7 +86,7 @@ export function ColumnsTable({ templateId }: ColumnsTableProps) {
title: 'Frozen?',
key: 'isFrozen',
width: '10%',
Cell: (item) => item.isFrozen && <CheckIcon color={colors.success} />,
Cell: (item) => item.isFrozen && <CheckIcon color={appColors.success} />,
},
{
title: 'Validations',
Expand Down Expand Up @@ -107,12 +114,12 @@ export function ColumnsTable({ templateId }: ColumnsTableProps) {
Cell: (item) => (
<Flex gap="xs">
<IconButton label="Edit" onClick={() => onEditColumnClick(item._id)}>
<EditIcon color={colors.blue} />
<EditIcon color={appColors.blue} />
</IconButton>
<IconButton label="Delete" onClick={() => onDeleteColumnClick(item._id)}>
<DeleteIcon color={colors.danger} />
<DeleteIcon color={appColors.danger} />
</IconButton>
<GripIcon color={colors.yellow} style={{ cursor: 'grab' }} />
<GripIcon color={appColors.yellow} style={{ cursor: 'grab' }} />
</Flex>
),
width: '15%',
Expand All @@ -122,54 +129,66 @@ export function ColumnsTable({ templateId }: ColumnsTableProps) {
<tr>
{showAddRow ? (
<>
<td colSpan={4} style={{ borderRight: 'none' }}>
<Flex gap="xs" align={'center'}>
<Input autoFocus required placeholder="Column Name" {...register('name')} />
<Controller
control={control}
name="type"
render={({ field }) => (
<NativeSelect data={columnTypes} placeholder="Select Type" variant="default" register={field} />
)}
/>
<Button
size="xs"
color="blue"
onClick={() => {
ValidationRef.current = true;
onValidationsButtonClick();
}}
>
Validations
</Button>
</Flex>
</td>
<td style={{ borderLeft: 'none' }}>
<Flex justify={'end'}>
<td colSpan={5} style={{ borderRight: 'none', position: 'relative' }}>
<LoadingOverlay visible={isColumnCreateLoading} />
<Flex gap="xs" align={'center'} justify="space-between">
<Group>
<Input autoFocus required placeholder="Column Name" {...register('name')} />
<Controller
control={control}
name="type"
render={({ field }) => (
<NativeSelect
data={columnTypes}
placeholder="Select Type"
variant="default"
register={field}
/>
)}
/>
<Button color="blue" onClick={onValidationsButtonClick}>
Validations
</Button>
</Group>

<ActionIcon
color="green"
type="submit"
autoFocus={ValidationRef.current}
loading={isColumnCreateLoading}
radius={0}
id="add-column"
bg={appColors.danger}
variant="transparent"
onClick={onCancelAddColumn}
>
<CheckIcon color={colors.green} />
</ActionIcon>
<ActionIcon color="red" onClick={() => setShowAddRow(false)}>
<CloseIcon color={colors.dangerDark} />
<CloseIcon color={appColors.white} />
</ActionIcon>
</Flex>
<Text size="xs" mt="xs" color={themeColors.gray[6]}>
* Press{' '}
<Text size="sm" span>
ENTER
</Text>{' '}
to save,{' '}
<Text size="sm" span>
ESC
</Text>{' '}
to cancel or click on{' '}
<Text size="sm" span>
VALIDATIONS
</Text>{' '}
to configure column behavior
</Text>
</td>
</>
) : (
<td colSpan={6}>
<Tooltip label="Add new column" withArrow position="top-start">
<ActionIcon
radius={0}
id="add-column"
bg={colors.yellow}
bg={appColors.yellow}
variant="transparent"
onClick={() => setShowAddRow(true)}
>
<AddIcon color={colors.white} />
<AddIcon color={appColors.white} />
</ActionIcon>
</Tooltip>
</td>
Expand Down
2 changes: 1 addition & 1 deletion apps/web/components/imports/schema/Schema.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ export function Schema({ templateId }: SchemaProps) {
<Flex gap="sm" direction="column">
<Flex justify="flex-end">
<Tooltip label="Edit JSON" withArrow>
<ActionIcon title="Edit JSON" variant="light" onClick={() => setShowJsonEditor(!showJsonEditor)}>
<ActionIcon radius={0} title="Edit JSON" variant="light" onClick={() => setShowJsonEditor(!showJsonEditor)}>
<BracesIcon size="md" color={colors.yellow} />
</ActionIcon>
</Tooltip>
Expand Down
2 changes: 1 addition & 1 deletion apps/web/components/settings/GenerateAccessToken.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ export function GenerateAccessToken() {
value={accessToken}
rightSection={
<Tooltip label={clipboardApiKey.copied ? 'Copied!' : 'Copy Key'}>
<ActionIcon variant="transparent" onClick={() => clipboardApiKey.copy(accessToken)}>
<ActionIcon radius={0} variant="transparent" onClick={() => clipboardApiKey.copy(accessToken)}>
{clipboardApiKey.copied ? <CheckIcon /> : <CopyIcon />}
</ActionIcon>
</Tooltip>
Expand Down
30 changes: 30 additions & 0 deletions apps/web/hooks/useKeyboardEvent.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { useEffect, useRef } from 'react';

export function useKeyboardEvent(key: string, callback: () => void) {
const listenerRef = useRef<any>(null);

useEffect(() => {
if (listenerRef.current) return; // Skip if listener is already set

const handleKeyDown = (e: globalThis.KeyboardEvent) => {
if (e.key === key) callback();
};

document.body.addEventListener('keydown', handleKeyDown, {
capture: false,
});

// Store the listener reference
listenerRef.current = handleKeyDown;

// Cleanup function
return () => {
if (listenerRef.current) {
document.body.removeEventListener('keydown', listenerRef.current, {
capture: false,
});
listenerRef.current = null;
}
};
}, [callback, key]);
}
35 changes: 24 additions & 11 deletions apps/web/hooks/useSchema.tsx
Original file line number Diff line number Diff line change
@@ -1,20 +1,21 @@
import { useEffect, useState } from 'react';
import { useEffect, useRef, useState } from 'react';
import dynamic from 'next/dynamic';

import { modals } from '@mantine/modals';
import { useForm } from 'react-hook-form';
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
import { SelectItem } from '@mantine/core';
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';

import { commonApi } from '@libs/api';
import { notify } from '@libs/notify';
import { track } from '@libs/amplitude';
import { IColumn, IErrorObject } from '@impler/shared';
import { API_KEYS, COLUMN_TYPES, MODAL_KEYS, MODAL_TITLES, NOTIFICATION_KEYS } from '@config';

import { useKeyboardEvent } from './useKeyboardEvent';
import { useUpdateBulkColumns } from './useUpdateBulkColumns';
import { ConfirmDelete } from '@components/imports/forms/ConfirmDelete';
import { usePlanMetaData } from 'store/planmeta.store.context';
import { ConfirmDelete } from '@components/imports/forms/ConfirmDelete';

const ColumnForm = dynamic(() => import('@components/imports/forms/ColumnForm').then((mod) => mod.ColumnForm), {
ssr: false,
});
Expand All @@ -27,6 +28,7 @@ export function useSchema({ templateId }: UseSchemaProps) {
const { meta } = usePlanMetaData();
const queryClient = useQueryClient();
const [showAddRow, setShowAddRow] = useState(false);
const validationRef = useRef<boolean | undefined>(undefined);
const { register, control, watch, reset, setFocus, handleSubmit, formState, getValues } = useForm<IColumn>({
defaultValues: {
type: 'String',
Expand Down Expand Up @@ -125,7 +127,11 @@ export function useSchema({ templateId }: UseSchemaProps) {
});
}
}

const onAddColumnSubmit = handleSubmit((data) => {
validationRef.current = false;
if (!data.key) data.key = data.name;
createColumn(data);
});
function onValidationsClick(columnData: Partial<IColumn>) {
if (columnData) {
modals.open({
Expand All @@ -138,6 +144,7 @@ export function useSchema({ templateId }: UseSchemaProps) {
data={columnData}
onSubmit={(data) => {
reset(data);
onAddColumnSubmit();
modals.close(MODAL_KEYS.COLUMN_UPDATE);
}}
/>
Expand Down Expand Up @@ -165,11 +172,10 @@ export function useSchema({ templateId }: UseSchemaProps) {
children: <ConfirmDelete onConfirm={() => onConfirmDelete(columnId)} />,
});
}
function onAddColumnSubmit(data: IColumn) {
if (!data.key) data.key = data.name;
createColumn(data);
function onCancelAddColumn() {
setShowAddRow(false);
validationRef.current = false;
}

function getColumnTypes(): SelectItem[] {
if (!meta) return COLUMN_TYPES;

Expand All @@ -186,6 +192,11 @@ export function useSchema({ templateId }: UseSchemaProps) {
if (showAddRow) setFocus('name');
}, [setFocus, showAddRow]);

useKeyboardEvent('Escape', () => {
if (!validationRef.current) onCancelAddColumn();
else validationRef.current = false;
});

return {
watch,
control,
Expand All @@ -194,14 +205,16 @@ export function useSchema({ templateId }: UseSchemaProps) {
formState,
getValues,
showAddRow,
validationRef,
onMoveColumns,
setShowAddRow,
getColumnTypes,
onAddColumnSubmit,
onEditColumnClick,
onCancelAddColumn,
onValidationsClick,
onDeleteColumnClick,
getColumnTypes,
isColumnCreateLoading,
isLoading: isColumnListLoading,
handleSubmit: handleSubmit(onAddColumnSubmit),
};
}
2 changes: 1 addition & 1 deletion apps/web/pages/imports/[id].tsx
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ export default function ImportDetails({}) {
</Button>
<Group spacing={0}>
<Title order={2}>{templateData?.name}</Title>
<ActionIcon onClick={onUpdateClick} p={0}>
<ActionIcon radius={0} onClick={onUpdateClick} p={0}>
<EditIcon color={colors.blue} size="sm" />
</ActionIcon>
</Group>
Expand Down

0 comments on commit db15191

Please sign in to comment.