Skip to content

Commit

Permalink
Feat/column description and guidpoints (#725)
Browse files Browse the repository at this point in the history
Added support for adding column description and guide points at specific
locations in applications.
  • Loading branch information
chavda-bhavik authored Aug 7, 2024
2 parents 054ded7 + dbf8ca7 commit 8dd1347
Show file tree
Hide file tree
Showing 40 changed files with 286 additions and 301 deletions.
1 change: 0 additions & 1 deletion apps/api/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,6 @@
"dayjs": "^1.11.11",
"dotenv": "^16.0.2",
"envalid": "^7.3.1",
"exceljs": "^4.3.0",
"hat": "^0.0.3",
"jsonwebtoken": "^9.0.0",
"jszip": "^3.10.1",
Expand Down
4 changes: 4 additions & 0 deletions apps/api/src/app/column/commands/add-column.command.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@ export class AddColumnCommand extends BaseCommand {
@IsDefined()
key: string;

@IsString()
@IsOptional()
description?: string;

@IsArray()
@IsOptional()
@Type(() => Array<string>)
Expand Down
4 changes: 4 additions & 0 deletions apps/api/src/app/column/commands/update-column.command.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@ export class UpdateColumnCommand extends BaseCommand {
@IsDefined()
key: string;

@IsString()
@IsOptional()
description?: string;

@IsArray()
@IsOptional()
@Type(() => Array<string>)
Expand Down
7 changes: 7 additions & 0 deletions apps/api/src/app/column/dtos/column-request.dto.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,13 @@ export class ColumnRequestDto {
@IsString()
key: string;

@ApiProperty({
description: 'Description of the column',
})
@IsOptional()
@IsString()
description?: string;

@ApiProperty({
description: 'Alternative possible keys of the column',
type: Array<string>,
Expand Down
5 changes: 5 additions & 0 deletions apps/api/src/app/column/dtos/column-response.dto.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,11 @@ export class ColumnResponseDto {
})
key: string;

@ApiProperty({
description: 'Description of the column',
})
description?: string;

@ApiProperty({
description: 'Alternative possible keys of the column',
type: Array<string>,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ export class CreateProject {
_templateId: template._id,
name: 'Date',
key: 'Date *',
description: 'The date when the transaction took place. Format: DD/MM/YYYY',
isFrozen: true,
type: ColumnTypesEnum.DATE,
isRequired: true,
Expand All @@ -55,6 +56,7 @@ export class CreateProject {
_templateId: template._id,
name: 'Product Name/ID',
key: 'Product Name/ID *',
description: 'The name or ID of the product purchased, e.g., "Apple" or "12345"',
type: ColumnTypesEnum.STRING,
isRequired: true,
isUnique: false,
Expand All @@ -63,6 +65,7 @@ export class CreateProject {
_templateId: template._id,
name: 'Quantity',
key: 'Quantity *',
description: 'The amount of the product purchased. For example, "3" apples or "2" bottles of milk',
type: ColumnTypesEnum.NUMBER,
isRequired: true,
isUnique: false,
Expand All @@ -71,6 +74,7 @@ export class CreateProject {
_templateId: template._id,
name: 'Total Price',
key: 'Total Price',
description: 'The total cost of the products purchased in this transaction. For example, "$10.50"',
type: ColumnTypesEnum.NUMBER,
isRequired: false,
isUnique: false,
Expand All @@ -79,6 +83,7 @@ export class CreateProject {
_templateId: template._id,
name: 'Customer Name/ID',
key: 'Customer Name/ID *',
description: 'The name or ID of the customer making the purchase, e.g., "John Doe" or "7890"',
type: ColumnTypesEnum.STRING,
isRequired: true,
isUnique: false,
Expand All @@ -87,6 +92,7 @@ export class CreateProject {
_templateId: template._id,
name: 'Payment Method',
key: 'Payment Method *',
description: 'The method used for payment. Options include credit card, cash, or check',
type: ColumnTypesEnum.SELECT,
selectValues: ['credit card', 'cash', 'check'],
isRequired: true,
Expand All @@ -96,6 +102,7 @@ export class CreateProject {
_templateId: template._id,
name: 'Transaction ID',
key: 'Transaction ID * (unique)',
description: 'A unique identifier for the transaction. For example, "TX12345678"',
type: ColumnTypesEnum.STRING,
isRequired: true,
isUnique: true,
Expand All @@ -104,6 +111,7 @@ export class CreateProject {
_templateId: template._id,
name: 'Salesperson Name/ID',
key: 'Salesperson Name/ID',
description: 'The name or ID of the salesperson handling the transaction, e.g., "Jane Smith" or "3456"',
type: ColumnTypesEnum.STRING,
isRequired: false,
isUnique: false,
Expand All @@ -112,6 +120,8 @@ export class CreateProject {
_templateId: template._id,
name: 'Notes/Comments',
key: 'Notes/Comments',
description:
'Additional comments or notes about the transaction. For example, "Discount applied" or "Gift wrap requested"',
type: ColumnTypesEnum.STRING,
isRequired: false,
isUnique: false,
Expand Down
24 changes: 1 addition & 23 deletions apps/api/src/app/shared/services/file/file.service.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import * as XLSX from 'xlsx';
import * as ExcelJS from 'exceljs';
import { cwd } from 'node:process';
import * as xlsxPopulate from 'xlsx-populate';
import { CONSTANTS } from '@shared/constants';
Expand Down Expand Up @@ -45,28 +44,7 @@ export class ExcelFileService {

return name;
}
addSelectValidation({
ws,
range,
keyName,
isRequired,
}: {
ws: ExcelJS.Worksheet;
range: string;
keyName: string;
isRequired: boolean;
}) {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
ws.dataValidations.add(range, {
type: 'list',
allowBlank: !isRequired,
formulae: [`${keyName}!$A$2:$A$9999`],
showErrorMessage: true,
errorTitle: 'Invalid Value',
error: 'Please select from the list',
});
}

getExcelColumnNameFromIndex(columnNumber: number) {
// To store result (Excel column name)
const columnName = [];
Expand Down
1 change: 1 addition & 0 deletions apps/api/src/app/shared/types/file.types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { ColumnTypesEnum } from '@impler/shared';

export interface IExcelFileHeading {
key: string;
description?: string;
isRequired?: boolean;
isFrozen?: boolean;
delimiter?: string;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,14 @@ export class SaveSampleFile {
isRequired: columnItem.isRequired,
dateFormats: columnItem.dateFormats,
allowMultiSelect: columnItem.allowMultiSelect,
description: columnItem.description,
}))
.sort((a, b) => (a.isFrozen === b.isFrozen ? 0 : a.isFrozen ? -1 : 1));

const hasMultiSelect = columns.some(
(columnItem) => columnItem.type === ColumnTypesEnum.SELECT && columnItem.allowMultiSelect
);

const fileName = this.fileNameService.getSampleFileName(templateId, hasMultiSelect);
const sampleFileUrl = this.fileNameService.getSampleFileUrl(templateId, hasMultiSelect);
const sampleExcelFile = await this.excelFileService.getExcelFileForHeadings(columnKeys);
Expand Down
1 change: 1 addition & 0 deletions apps/api/src/app/template/template.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,7 @@ export class TemplateController {
isUnique: columnData.isUnique,
isFrozen: columnData.isFrozen,
name: columnData.name,
description: columnData.description,
regex: columnData.regex,
regexDescription: columnData.regexDescription,
selectValues: columnData.selectValues,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ export class DownloadSample {
{
_templateId,
},
'key type selectValues isRequired allowMultiSelect'
'key description type selectValues isRequired allowMultiSelect'
);

let parsedSchema: ISchemaItem[], columnKeys: IExcelFileHeading[];
Expand All @@ -55,6 +55,7 @@ export class DownloadSample {
selectValues: imageSchema?.[columnItem.key] || columnItem.selectValues || [],
isRequired: columnItem.isRequired,
allowMultiSelect: columnItem.allowMultiSelect,
description: columnItem.description,
}));
} else {
// else create structure from existing defualt schema
Expand All @@ -64,6 +65,7 @@ export class DownloadSample {
selectValues: imageSchema?.[columnItem.key] || columnItem.selectValues || [],
isRequired: columnItem.isRequired,
allowMultiSelect: columnItem.allowMultiSelect,
description: columnItem.description,
}));
}
const hasMultiSelect = columnKeys.some(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ export class DuplicateTemplate {
_templateId,
},
// eslint-disable-next-line max-len
'-_id name key alternateKeys isRequired isUnique type regex regexDescription selectValues dateFormats sequence defaultValue allowMultiSelect'
'-_id name key alternateKeys isRequired isUnique type regex regexDescription selectValues dateFormats sequence defaultValue allowMultiSelect description'
);

await this.columnRepository.createMany(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ export class GetTemplateColumns {
return this.columnRepository.find(
{ _templateId },
// eslint-disable-next-line max-len
'_id name key type alternateKeys isRequired isUnique isFrozen selectValues regex dateFormats defaultValue sequence allowMultiSelect delimiter',
'_id name key description type alternateKeys isRequired isUnique isFrozen selectValues regex dateFormats defaultValue sequence allowMultiSelect delimiter',
{
sort: {
isFrozen: -1,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ export class MakeUploadEntry {
_templateId: templateId,
},
// eslint-disable-next-line max-len
'name key isRequired isUnique isFrozen selectValues dateFormats defaultValue type regex sequence allowMultiSelect alternateKeys delimiter',
'name key isRequired isUnique isFrozen selectValues dateFormats defaultValue type regex sequence allowMultiSelect alternateKeys delimiter description',
{
sort: 'sequence',
}
Expand Down Expand Up @@ -103,6 +103,7 @@ export class MakeUploadEntry {
isUnique: schemaItem.isUnique || false,
defaultValue: schemaItem.defaultValue,
allowMultiSelect: schemaItem.allowMultiSelect,
description: schemaItem.description,
alternateKeys: Array.isArray(schemaItem.alternateKeys) ? schemaItem.alternateKeys : [],

sequence: Object.keys(formattedColumns).length,
Expand Down
19 changes: 19 additions & 0 deletions apps/web/assets/icons/GuidePoint.icon.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import React from 'react';
import { IconType } from '@types';
import { IconSizes } from 'config';

export const GuidePointIcon = ({ size = 'sm', color }: IconType) => {
return (
<svg
viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg"
width={IconSizes[size]}
height={IconSizes[size]}
fill={color}
>
<path d="m18 20.75h-12a2.75 2.75 0 0 1 -2.75-2.75v-12a2.75 2.75 0 0 1 2.75-2.75h6a.75.75 0 0 1 0 1.5h-6a1.25 1.25 0 0 0 -1.25 1.25v12a1.25 1.25 0 0 0 1.25 1.25h12a1.25 1.25 0 0 0 1.25-1.25v-6a.75.75 0 0 1 1.5 0v6a2.75 2.75 0 0 1 -2.75 2.75z" />
<path d="m20 8.75a.76.76 0 0 1 -.75-.75v-3.25h-3.25a.75.75 0 0 1 0-1.5h4a.76.76 0 0 1 .75.75v4a.76.76 0 0 1 -.75.75z" />
<path d="m13.5 11.25a.74.74 0 0 1 -.5-.25.75.75 0 0 1 0-1l6.5-6.5a.75.75 0 1 1 1.06 1.06l-6.56 6.44a.74.74 0 0 1 -.5.25z" />
</svg>
);
};
29 changes: 29 additions & 0 deletions apps/web/components/TooltipLink/TooltipLink.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import React from 'react';
import { Tooltip, useMantineColorScheme } from '@mantine/core';
import Link from 'next/link';
import { GuidePointIcon } from '@assets/icons/GuidePoint.icon';
import { colors } from '@config';

interface TooltipLinkProps {
label?: string;
link: string;
iconSize?: 'sm' | 'md' | 'lg';
iconColor?: string;
}

export function TooltipLink({ label = 'Read More', link, iconSize = 'sm' }: TooltipLinkProps) {
const theme = useMantineColorScheme();

return (
<Tooltip label={label} withArrow>
<Link href={link} target="_blank" rel="noopener noreferrer">
<GuidePointIcon
size={iconSize}
color={theme.colorScheme === 'dark' ? colors.BGPrimaryLight : colors.BGPrimaryDark}
/>
</Link>
</Tooltip>
);
}

export default TooltipLink;
4 changes: 3 additions & 1 deletion apps/web/components/home/PlanDetails/PlanDetails.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,10 @@ import { useApp } from '@hooks/useApp';
import { SelectCardModal } from '@components/settings';
import { usePlanDetails } from '@hooks/usePlanDetails';
import { PlansModal } from '@components/UpgradePlan/PlansModal';
import { CONSTANTS, MODAL_KEYS, ROUTES, colors } from '@config';
import { CONSTANTS, MODAL_KEYS, ROUTES, colors, DOCUMENTATION_REFERENCE_LINKS } from '@config';
import { numberFormatter } from '@impler/shared/dist/utils/helpers';
import { ConfirmationModal } from '@components/ConfirmationModal';
import TooltipLink from '@components/TooltipLink/TooltipLink';

export function PlanDetails() {
const router = useRouter();
Expand Down Expand Up @@ -173,6 +174,7 @@ export function PlanDetails() {
</Text>
</Flex>
</Flex>
<TooltipLink link={DOCUMENTATION_REFERENCE_LINKS.subscriptionInformation} iconSize="md" />
</Flex>
);
}
5 changes: 4 additions & 1 deletion apps/web/components/imports/destination/Destination.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { Stack, TextInput as Input, Group } from '@mantine/core';
import { Button } from '@ui/button';
import { NumberInput } from '@ui/number-input';
import { DoaminInput } from '@ui/domain-input';
import { REGULAR_EXPRESSIONS } from '@config';
import { DOCUMENTATION_REFERENCE_LINKS, REGULAR_EXPRESSIONS } from '@config';
import { NativeSelect } from '@ui/native-select';
import { useDestination } from '@hooks/useDestination';
import { DestinationItem } from './DestinationItem';
Expand Down Expand Up @@ -54,12 +54,14 @@ export function Destination({ template }: DestinationProps) {
subtitle="User imported data will be sent to frontend"
active={destination === DestinationsEnum.FRONTEND}
onClick={() => swithDestination(DestinationsEnum.FRONTEND)}
tooltipLink={DOCUMENTATION_REFERENCE_LINKS.frontendEndCallback}
/>
<DestinationItem
title="Webhook"
subtitle="Provide webhook to receive data"
active={destination === DestinationsEnum.WEBHOOK}
onClick={() => swithDestination(DestinationsEnum.WEBHOOK)}
tooltipLink={DOCUMENTATION_REFERENCE_LINKS.webhook}
>
<form onSubmit={onSubmit}>
<Stack spacing="xs">
Expand Down Expand Up @@ -102,6 +104,7 @@ export function Destination({ template }: DestinationProps) {
subtitle="Send Imported data to bubble.io"
active={destination === DestinationsEnum.BUBBLEIO}
onClick={() => swithDestination(DestinationsEnum.BUBBLEIO)}
tooltipLink={DOCUMENTATION_REFERENCE_LINKS.bubbleIo}
>
<form onSubmit={onSubmit}>
<Stack spacing="xs">
Expand Down
Original file line number Diff line number Diff line change
@@ -1,27 +1,32 @@
import { PropsWithChildren } from 'react';
import { Title, useMantineColorScheme, Flex, Stack, Switch, Collapse } from '@mantine/core';
import { Title, useMantineColorScheme, Flex, Stack, Switch, Collapse, Group } from '@mantine/core';

import useStyles from './DestinationItem.styles';
import { colors } from '@config';
import TooltipLink from '@components/TooltipLink/TooltipLink';

interface DestinationItemProps extends PropsWithChildren {
title: string;
subtitle: string;
onClick?: () => void;
active?: boolean;
tooltipLink?: string;
}

export const DestinationItem = ({ title, subtitle, onClick, children, active }: DestinationItemProps) => {
export const DestinationItem = ({ title, subtitle, onClick, children, active, tooltipLink }: DestinationItemProps) => {
const { colorScheme } = useMantineColorScheme();
const { classes } = useStyles({ colorScheme });

return (
<Stack className={classes.container} p="lg" spacing={children ? 'sm' : 0}>
<Flex justify="space-between" align="center">
<Stack spacing={0}>
<Title color={colorScheme === 'dark' ? colors.white : colors.black} order={4}>
{title}
</Title>
<Stack spacing={2}>
<Group spacing="xs" align="center" noWrap>
<Title color={colorScheme === 'dark' ? colors.white : colors.black} order={4}>
{title}
</Title>
{tooltipLink && <TooltipLink link={tooltipLink} iconSize="md" />}
</Group>
<Title order={5} fw="normal" color={colors.TXTSecondaryDark}>
{subtitle}
</Title>
Expand Down
Loading

0 comments on commit 8dd1347

Please sign in to comment.