diff --git a/apps/api/package.json b/apps/api/package.json index f23b5d76a..0eb9abcee 100644 --- a/apps/api/package.json +++ b/apps/api/package.json @@ -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", diff --git a/apps/api/src/app/column/commands/add-column.command.ts b/apps/api/src/app/column/commands/add-column.command.ts index 71a1b84c1..6cc3e75b2 100644 --- a/apps/api/src/app/column/commands/add-column.command.ts +++ b/apps/api/src/app/column/commands/add-column.command.ts @@ -13,6 +13,10 @@ export class AddColumnCommand extends BaseCommand { @IsDefined() key: string; + @IsString() + @IsOptional() + description?: string; + @IsArray() @IsOptional() @Type(() => Array) diff --git a/apps/api/src/app/column/commands/update-column.command.ts b/apps/api/src/app/column/commands/update-column.command.ts index bf669bf1c..9b7ef2f5d 100644 --- a/apps/api/src/app/column/commands/update-column.command.ts +++ b/apps/api/src/app/column/commands/update-column.command.ts @@ -13,6 +13,10 @@ export class UpdateColumnCommand extends BaseCommand { @IsDefined() key: string; + @IsString() + @IsOptional() + description?: string; + @IsArray() @IsOptional() @Type(() => Array) diff --git a/apps/api/src/app/column/dtos/column-request.dto.ts b/apps/api/src/app/column/dtos/column-request.dto.ts index c462e0d8e..858ad6336 100644 --- a/apps/api/src/app/column/dtos/column-request.dto.ts +++ b/apps/api/src/app/column/dtos/column-request.dto.ts @@ -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, diff --git a/apps/api/src/app/column/dtos/column-response.dto.ts b/apps/api/src/app/column/dtos/column-response.dto.ts index 2c8bd0612..6400e59f7 100644 --- a/apps/api/src/app/column/dtos/column-response.dto.ts +++ b/apps/api/src/app/column/dtos/column-response.dto.ts @@ -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, diff --git a/apps/api/src/app/project/usecases/create-project/create-project.usecase.ts b/apps/api/src/app/project/usecases/create-project/create-project.usecase.ts index 1541d7547..e59e41a1c 100644 --- a/apps/api/src/app/project/usecases/create-project/create-project.usecase.ts +++ b/apps/api/src/app/project/usecases/create-project/create-project.usecase.ts @@ -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, @@ -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, @@ -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, @@ -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, @@ -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, @@ -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, @@ -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, @@ -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, @@ -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, diff --git a/apps/api/src/app/shared/services/file/file.service.ts b/apps/api/src/app/shared/services/file/file.service.ts index 60fe805b3..e584fd2b1 100644 --- a/apps/api/src/app/shared/services/file/file.service.ts +++ b/apps/api/src/app/shared/services/file/file.service.ts @@ -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'; @@ -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 = []; diff --git a/apps/api/src/app/shared/types/file.types.ts b/apps/api/src/app/shared/types/file.types.ts index 710448720..59f780186 100644 --- a/apps/api/src/app/shared/types/file.types.ts +++ b/apps/api/src/app/shared/types/file.types.ts @@ -2,6 +2,7 @@ import { ColumnTypesEnum } from '@impler/shared'; export interface IExcelFileHeading { key: string; + description?: string; isRequired?: boolean; isFrozen?: boolean; delimiter?: string; diff --git a/apps/api/src/app/shared/usecases/save-sample-file/save-sample-file.usecase.ts b/apps/api/src/app/shared/usecases/save-sample-file/save-sample-file.usecase.ts index 920d5bf7a..16f7d6fad 100644 --- a/apps/api/src/app/shared/usecases/save-sample-file/save-sample-file.usecase.ts +++ b/apps/api/src/app/shared/usecases/save-sample-file/save-sample-file.usecase.ts @@ -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); diff --git a/apps/api/src/app/template/template.controller.ts b/apps/api/src/app/template/template.controller.ts index ea083eae1..9496d330d 100644 --- a/apps/api/src/app/template/template.controller.ts +++ b/apps/api/src/app/template/template.controller.ts @@ -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, diff --git a/apps/api/src/app/template/usecases/download-sample/download-sample.usecase.ts b/apps/api/src/app/template/usecases/download-sample/download-sample.usecase.ts index 617a66e82..9c3d5984b 100644 --- a/apps/api/src/app/template/usecases/download-sample/download-sample.usecase.ts +++ b/apps/api/src/app/template/usecases/download-sample/download-sample.usecase.ts @@ -37,7 +37,7 @@ export class DownloadSample { { _templateId, }, - 'key type selectValues isRequired allowMultiSelect' + 'key description type selectValues isRequired allowMultiSelect' ); let parsedSchema: ISchemaItem[], columnKeys: IExcelFileHeading[]; @@ -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 @@ -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( diff --git a/apps/api/src/app/template/usecases/duplicate-template/duplicate-template.usecase.ts b/apps/api/src/app/template/usecases/duplicate-template/duplicate-template.usecase.ts index 2b7159270..9c66a625f 100644 --- a/apps/api/src/app/template/usecases/duplicate-template/duplicate-template.usecase.ts +++ b/apps/api/src/app/template/usecases/duplicate-template/duplicate-template.usecase.ts @@ -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( diff --git a/apps/api/src/app/template/usecases/get-columns/get-columns.usecase.ts b/apps/api/src/app/template/usecases/get-columns/get-columns.usecase.ts index 567f1ee85..9ccb53f17 100644 --- a/apps/api/src/app/template/usecases/get-columns/get-columns.usecase.ts +++ b/apps/api/src/app/template/usecases/get-columns/get-columns.usecase.ts @@ -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, diff --git a/apps/api/src/app/upload/usecases/make-upload-entry/make-upload-entry.usecase.ts b/apps/api/src/app/upload/usecases/make-upload-entry/make-upload-entry.usecase.ts index 83e71e561..d2ee732ad 100644 --- a/apps/api/src/app/upload/usecases/make-upload-entry/make-upload-entry.usecase.ts +++ b/apps/api/src/app/upload/usecases/make-upload-entry/make-upload-entry.usecase.ts @@ -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', } @@ -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, diff --git a/apps/web/assets/icons/GuidePoint.icon.tsx b/apps/web/assets/icons/GuidePoint.icon.tsx new file mode 100644 index 000000000..b4005336d --- /dev/null +++ b/apps/web/assets/icons/GuidePoint.icon.tsx @@ -0,0 +1,19 @@ +import React from 'react'; +import { IconType } from '@types'; +import { IconSizes } from 'config'; + +export const GuidePointIcon = ({ size = 'sm', color }: IconType) => { + return ( + + + + + + ); +}; diff --git a/apps/web/components/TooltipLink/TooltipLink.tsx b/apps/web/components/TooltipLink/TooltipLink.tsx new file mode 100644 index 000000000..c6e342e51 --- /dev/null +++ b/apps/web/components/TooltipLink/TooltipLink.tsx @@ -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 ( + + + + + + ); +} + +export default TooltipLink; diff --git a/apps/web/components/home/PlanDetails/PlanDetails.tsx b/apps/web/components/home/PlanDetails/PlanDetails.tsx index a47d7036f..2f3c89edd 100644 --- a/apps/web/components/home/PlanDetails/PlanDetails.tsx +++ b/apps/web/components/home/PlanDetails/PlanDetails.tsx @@ -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(); @@ -173,6 +174,7 @@ export function PlanDetails() { + ); } diff --git a/apps/web/components/imports/destination/Destination.tsx b/apps/web/components/imports/destination/Destination.tsx index 0184dda8e..450685029 100644 --- a/apps/web/components/imports/destination/Destination.tsx +++ b/apps/web/components/imports/destination/Destination.tsx @@ -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'; @@ -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} /> swithDestination(DestinationsEnum.WEBHOOK)} + tooltipLink={DOCUMENTATION_REFERENCE_LINKS.webhook} >
@@ -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} > diff --git a/apps/web/components/imports/destination/DestinationItem/DestinationItem.tsx b/apps/web/components/imports/destination/DestinationItem/DestinationItem.tsx index 106f90f33..0b8a1a830 100644 --- a/apps/web/components/imports/destination/DestinationItem/DestinationItem.tsx +++ b/apps/web/components/imports/destination/DestinationItem/DestinationItem.tsx @@ -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 ( - - - {title} - + + + + {title} + + {tooltipLink && } + {subtitle} diff --git a/apps/web/components/imports/editor/Editor.tsx b/apps/web/components/imports/editor/Editor.tsx index e15b45a9b..b9d38fb7c 100644 --- a/apps/web/components/imports/editor/Editor.tsx +++ b/apps/web/components/imports/editor/Editor.tsx @@ -1,7 +1,7 @@ import { Controller } from 'react-hook-form'; import { Group, Title, Text, useMantineColorScheme, Flex, Code, Stack, LoadingOverlay } from '@mantine/core'; -import { colors } from '@config'; +import { colors, DOCUMENTATION_REFERENCE_LINKS } from '@config'; import { Button } from '@ui/button'; import { Editor } from '@ui/editor/Editor'; import { useEditor } from '@hooks/useEditor'; @@ -13,6 +13,7 @@ import { VarItemWrapper } from './VarItemWrapper'; import { WarningIcon } from '@assets/icons/Warning.icon'; import { InformationIcon } from '@assets/icons/Information.icon'; import { PossibleJSONErrors } from '@components/common/PossibleJsonErrors'; +import TooltipLink from '@components/TooltipLink/TooltipLink'; interface OutputEditorProps { templateId: string; @@ -59,9 +60,12 @@ export function OutputEditor({ templateId, switchToDestination }: OutputEditorPr
- - {titles[destination.destination].title} - + + + {titles[destination.destination].title} + + + {titles[destination.destination].subtitle} diff --git a/apps/web/components/imports/forms/ColumnForm.tsx b/apps/web/components/imports/forms/ColumnForm.tsx index e873628fd..b9fcd7725 100644 --- a/apps/web/components/imports/forms/ColumnForm.tsx +++ b/apps/web/components/imports/forms/ColumnForm.tsx @@ -1,4 +1,3 @@ -import Link from 'next/link'; import { modals } from '@mantine/modals'; import { Controller, useForm } from 'react-hook-form'; import { @@ -12,16 +11,18 @@ import { CloseButton, Select, useMantineColorScheme, + Flex, } from '@mantine/core'; import { ColumnTypesEnum, DEFAULT_VALUES, IColumn } from '@impler/shared'; -import { colors, COLUMN_TYPES, DELIMITERS, MODAL_KEYS, MODAL_TITLES } from '@config'; +import { colors, COLUMN_TYPES, DELIMITERS, MODAL_KEYS, MODAL_TITLES, DOCUMENTATION_REFERENCE_LINKS } from '@config'; import { Button } from '@ui/button'; import { Textarea } from '@ui/textarea'; import { Checkbox } from '@ui/checkbox'; import { MultiSelect } from '@ui/multi-select'; import { CustomSelect } from '@ui/custom-select'; +import TooltipLink from '@components/TooltipLink/TooltipLink'; interface ColumnFormProps { data?: Partial; @@ -78,6 +79,12 @@ export function ColumnForm({ onSubmit, data, isLoading }: ColumnFormProps) { placeholder="Column Key" error={errors.key?.message} /> + (
`; + TH.innerHTML = ` +
+ + + + +
`; + } else { + if (columnDescriptions && columnDescriptions[i]) { + // Create the SVG icon element + const infoIcon = document.createElementNS('http://www.w3.org/2000/svg', 'svg'); + infoIcon.setAttribute('xmlns', 'http://www.w3.org/2000/svg'); + infoIcon.setAttribute('viewBox', '-2 -2 24 24'); + infoIcon.setAttribute('width', '20'); + infoIcon.setAttribute('fill', 'currentColor'); + infoIcon.setAttribute( + 'style', + 'vertical-align: middle;float: right;cursor: pointer;color:#fffff; margin-right:4px;' + ); + const infoIconPath = document.createElementNS('http://www.w3.org/2000/svg', 'path'); + infoIconPath.setAttribute( + 'd', + 'M10 20C4.477 20 0 15.523 0 10S4.477 0 10 0s10 4.477 10 10-4.477 10-10 10zm0-2a8 8 0 1 0 0-16 8 8 0 0 0 0 16zm0-10a1 1 0 0 1 1 1v5a1 1 0 0 1-2 0V9a1 1 0 0 1 1-1zm0-1a1 1 0 1 1 0-2 1 1 0 0 1 0 2z' + ); + infoIcon.appendChild(infoIconPath); + TH.appendChild(infoIcon); + + addTippyToElement(infoIcon as unknown as HTMLElement, columnDescriptions[i]); + } } }} renderAllColumns diff --git a/apps/widget/src/components/widget/Phases/Phase3/Phase3.tsx b/apps/widget/src/components/widget/Phases/Phase3/Phase3.tsx index 23082ac90..5246f6a80 100644 --- a/apps/widget/src/components/widget/Phases/Phase3/Phase3.tsx +++ b/apps/widget/src/components/widget/Phases/Phase3/Phase3.tsx @@ -61,6 +61,7 @@ export function Phase3(props: IPhase3Props) { height: 200, width: 500, }); + const columnDescriptions = columnDefs.map((column) => column.description || ''); useEffect(() => { // setting wrapper height @@ -172,6 +173,7 @@ export function Phase3(props: IPhase3Props) { headings={headings} columnDefs={columnDefs} allChecked={allChecked} + columnDescriptions={columnDescriptions} />
diff --git a/apps/widget/src/hooks/Phase3/usePhase3.tsx b/apps/widget/src/hooks/Phase3/usePhase3.tsx index 3d80f2b6a..60e5ca411 100644 --- a/apps/widget/src/hooks/Phase3/usePhase3.tsx +++ b/apps/widget/src/hooks/Phase3/usePhase3.tsx @@ -77,12 +77,15 @@ export function usePhase3({ onNext }: IUsePhase3Props) { data.forEach((column: ISchemaColumn) => { if (column.isFrozen) updatedFrozenColumns++; newHeadings.push(column.name); + const columnItem: HotItemSchema = { className: 'htCenter', data: `record.${column.key}`, allowEmpty: !column.isRequired, allowDuplicate: !column.isUnique, + description: column.description, }; + switch (column.type) { case ColumnTypesEnum.STRING: case ColumnTypesEnum.EMAIL: diff --git a/apps/widget/src/types/utility.types.ts b/apps/widget/src/types/utility.types.ts index 4d76e37c0..305d2b9b9 100644 --- a/apps/widget/src/types/utility.types.ts +++ b/apps/widget/src/types/utility.types.ts @@ -17,6 +17,7 @@ export type HotItemSchema = { allowEmpty?: boolean; allowInvalid?: boolean; disableVisualSelection?: boolean; + description?: string; renderer?: | 'custom' | 'check' diff --git a/apps/widget/src/util/helpers/common.helpers.ts b/apps/widget/src/util/helpers/common.helpers.ts index c6a306693..0f26e4307 100644 --- a/apps/widget/src/util/helpers/common.helpers.ts +++ b/apps/widget/src/util/helpers/common.helpers.ts @@ -1,5 +1,8 @@ -import axios from 'axios'; import * as Sentry from '@sentry/react'; +import axios from 'axios'; +import tippy from 'tippy.js'; +import 'tippy.js/dist/tippy.css'; +import 'tippy.js/animations/shift-away.css'; import { variables } from '@config'; import { downloadFile } from '@impler/shared'; @@ -77,3 +80,19 @@ export const validateRssUrl = { }; export const getObjectId = (math = Math, date = Date, hr = 16, sec = (sp: number) => math.floor(sp).toString(hr)) => sec(date.now() / 1000) + ' '.repeat(hr).replace(/./g, () => sec(math.random() * hr)); + +export const getColumnDescription = (columnIndex: number, descriptions: string[]): string | null => { + return descriptions[columnIndex] || null; +}; + +export const addTippyToElement = (element: SVGSVGElement | HTMLElement, content: string) => { + if (!element || !content) return; + + tippy(element, { + content, + arrow: true, + duration: 300, + theme: 'custom', + animation: 'shift-away', + }); +}; diff --git a/libs/dal/src/repositories/column/column.entity.ts b/libs/dal/src/repositories/column/column.entity.ts index 4fb92c9b6..1a000c441 100644 --- a/libs/dal/src/repositories/column/column.entity.ts +++ b/libs/dal/src/repositories/column/column.entity.ts @@ -5,6 +5,8 @@ export class ColumnEntity { key: string; + description?: string; + alternateKeys?: string[]; isRequired?: boolean; diff --git a/libs/dal/src/repositories/column/column.schema.ts b/libs/dal/src/repositories/column/column.schema.ts index db0eeb2cf..473b02787 100644 --- a/libs/dal/src/repositories/column/column.schema.ts +++ b/libs/dal/src/repositories/column/column.schema.ts @@ -9,6 +9,7 @@ const columnSchema = new Schema( alternateKeys: [String], isRequired: Boolean, isUnique: Boolean, + description: String, isFrozen: Boolean, regex: String, allowMultiSelect: Boolean, diff --git a/libs/shared/src/entities/Column/Column.interface.ts b/libs/shared/src/entities/Column/Column.interface.ts index 785e64fb8..fa6d7be72 100644 --- a/libs/shared/src/entities/Column/Column.interface.ts +++ b/libs/shared/src/entities/Column/Column.interface.ts @@ -2,6 +2,7 @@ export interface IColumn { _id: string; name: string; key: string; + description?: string; type: string; alternateKeys?: string[]; isRequired?: boolean; diff --git a/libs/shared/src/types/column/column.types.ts b/libs/shared/src/types/column/column.types.ts index 1283a9dad..8438f02d9 100644 --- a/libs/shared/src/types/column/column.types.ts +++ b/libs/shared/src/types/column/column.types.ts @@ -18,6 +18,7 @@ export enum ColumnDelimiterEnum { export interface ISchemaItem { key: string; name: string; + description?: string; alternateKeys?: string[]; isRequired?: boolean; isUnique?: boolean; diff --git a/packages/react/src/types/index.ts b/packages/react/src/types/index.ts index 3150aa765..5bc206be1 100644 --- a/packages/react/src/types/index.ts +++ b/packages/react/src/types/index.ts @@ -18,6 +18,7 @@ export interface ButtonProps { export interface ISchemaItem { key: string; name: string; + description: string; alternateKeys?: string[]; isRequired?: boolean; isUnique?: boolean; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 7f736c1d5..1eb53e44d 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -183,9 +183,6 @@ importers: envalid: specifier: ^7.3.1 version: 7.3.1 - exceljs: - specifier: ^4.3.0 - version: 4.4.0 hat: specifier: ^0.0.3 version: 0.0.3 @@ -576,6 +573,9 @@ importers: rimraf: specifier: ^3.0.2 version: 3.0.2 + tippy.js: + specifier: ^6.3.7 + version: 6.3.7 web-vitals: specifier: ^3.0.4 version: 3.5.2 @@ -4087,29 +4087,6 @@ packages: resolution: {integrity: sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - /@fast-csv/format@4.3.5: - resolution: {integrity: sha512-8iRn6QF3I8Ak78lNAa+Gdl5MJJBM5vRHivFtMRUWINdevNo00K7OXxS2PshawLKTejVwieIlPmK5YlLu6w4u8A==} - dependencies: - '@types/node': 14.18.63 - lodash.escaperegexp: 4.1.2 - lodash.isboolean: 3.0.3 - lodash.isequal: 4.5.0 - lodash.isfunction: 3.0.9 - lodash.isnil: 4.0.0 - dev: false - - /@fast-csv/parse@4.3.6: - resolution: {integrity: sha512-uRsLYksqpbDmWaSmzvJcuApSEe38+6NQZBUsuAyMZKqHxH0g1wcJgsKUvN3WC8tewaqFjBMMGrkHmC+T7k8LvA==} - dependencies: - '@types/node': 14.18.63 - lodash.escaperegexp: 4.1.2 - lodash.groupby: 4.6.0 - lodash.isfunction: 3.0.9 - lodash.isnil: 4.0.0 - lodash.isundefined: 3.0.1 - lodash.uniq: 4.5.0 - dev: false - /@floating-ui/core@1.6.4: resolution: {integrity: sha512-a4IowK4QkXl4SCWTGUR0INAfEOX3wtsYw3rKK5InQEHMGObkR8Xk44qYQD9P4r6HHw0iIfK6GUKECmY8sTkqRA==} dependencies: @@ -9137,10 +9114,6 @@ packages: dependencies: '@types/node': 18.19.39 - /@types/node@14.18.63: - resolution: {integrity: sha512-fAtCfv4jJg+ExtXhvCkCqUKZ+4ok/JQk01qDKhL5BDDoS3AxKXhV5/MAVUZyQnSEd2GT92fkgZl0pz0Q0AzcIQ==} - dev: false - /@types/node@16.18.101: resolution: {integrity: sha512-AAsx9Rgz2IzG8KJ6tXd6ndNkVcu+GYB6U/SnFAaokSPNx2N7dcIIfnighYUNumvj6YS2q39Dejz5tT0NCV7CWA==} @@ -10127,51 +10100,6 @@ packages: /aproba@2.0.0: resolution: {integrity: sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==} - /archiver-utils@2.1.0: - resolution: {integrity: sha512-bEL/yUb/fNNiNTuUz979Z0Yg5L+LzLxGJz8x79lYmR54fmTIb6ob/hNQgkQnIUDWIFjZVQwl9Xs356I6BAMHfw==} - engines: {node: '>= 6'} - dependencies: - glob: 7.2.3 - graceful-fs: 4.2.11 - lazystream: 1.0.1 - lodash.defaults: 4.2.0 - lodash.difference: 4.5.0 - lodash.flatten: 4.4.0 - lodash.isplainobject: 4.0.6 - lodash.union: 4.6.0 - normalize-path: 3.0.0 - readable-stream: 2.3.8 - dev: false - - /archiver-utils@3.0.4: - resolution: {integrity: sha512-KVgf4XQVrTjhyWmx6cte4RxonPLR9onExufI1jhvw/MQ4BB6IsZD5gT8Lq+u/+pRkWna/6JoHpiQioaqFP5Rzw==} - engines: {node: '>= 10'} - dependencies: - glob: 7.2.3 - graceful-fs: 4.2.11 - lazystream: 1.0.1 - lodash.defaults: 4.2.0 - lodash.difference: 4.5.0 - lodash.flatten: 4.4.0 - lodash.isplainobject: 4.0.6 - lodash.union: 4.6.0 - normalize-path: 3.0.0 - readable-stream: 3.6.2 - dev: false - - /archiver@5.3.2: - resolution: {integrity: sha512-+25nxyyznAXF7Nef3y0EbBeqmGZgeN/BxHX29Rs39djAfaFalmQ89SE6CWyDCHzGL0yt/ycBtNOmGTW0FyGWNw==} - engines: {node: '>= 10'} - dependencies: - archiver-utils: 2.1.0 - async: 3.2.5 - buffer-crc32: 0.2.13 - readable-stream: 3.6.2 - readdir-glob: 1.1.3 - tar-stream: 2.2.0 - zip-stream: 4.1.1 - dev: false - /are-we-there-yet@2.0.0: resolution: {integrity: sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==} engines: {node: '>=10'} @@ -10836,6 +10764,8 @@ packages: /big-integer@1.6.52: resolution: {integrity: sha512-QxD8cf2eVqJOOz63z6JIN9BzvVs/dlySa5HGSBH5xtR8dPteIRQnBxxKqkNTiT6jbDTF6jAfrd4oMcND9RGbQg==} engines: {node: '>=0.6'} + requiresBuild: true + optional: true /big.js@5.2.2: resolution: {integrity: sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==} @@ -10864,13 +10794,6 @@ packages: resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==} engines: {node: '>=8'} - /binary@0.3.0: - resolution: {integrity: sha512-D4H1y5KYwpJgK8wk1Cue5LLPgmwHKYSChkbspQg5JtVuR5ulGckxfR62H3AE9UDkdMC8yyXlqYihuz3Aqg2XZg==} - dependencies: - buffers: 0.1.1 - chainsaw: 0.1.0 - dev: false - /bindings@1.5.0: resolution: {integrity: sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==} requiresBuild: true @@ -10885,10 +10808,6 @@ packages: inherits: 2.0.4 readable-stream: 3.6.2 - /bluebird@3.4.7: - resolution: {integrity: sha512-iD3898SR7sWVRHbiQv+sHUtHnMvC1o3nW5rAcqnq3uOn07DSAppZYUkIGslDz6gXC7HfunPe7YVBgoEJASPcHA==} - dev: false - /bluebird@3.7.2: resolution: {integrity: sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==} @@ -11090,10 +11009,6 @@ packages: engines: {node: '>=16.20.1'} dev: false - /buffer-crc32@0.2.13: - resolution: {integrity: sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==} - dev: false - /buffer-equal-constant-time@1.0.1: resolution: {integrity: sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==} dev: false @@ -11105,11 +11020,6 @@ packages: /buffer-from@1.1.2: resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} - /buffer-indexof-polyfill@1.0.2: - resolution: {integrity: sha512-I7wzHwA3t1/lwXQh+A5PbNvJxgfo5r3xulgpYDB5zckTu/Z9oUK9biouBKQUjEqzaz3HnAT6TYoovmE+GqSf7A==} - engines: {node: '>=0.10'} - dev: false - /buffer-more-ints@1.0.0: resolution: {integrity: sha512-EMetuGFz5SLsT0QTnXzINh4Ksr+oo4i+UGTXEshiGCQWnsgSs7ZhJ8fzlwQ+OzEMs0MpDAMr1hxnblp5a4vcHg==} dev: false @@ -11137,11 +11047,6 @@ packages: base64-js: 1.5.1 ieee754: 1.2.1 - /buffers@0.1.1: - resolution: {integrity: sha512-9q/rDEGSb/Qsvv2qvzIzdluL5k7AaJOTrw23z9reQthrbF7is4CtlT0DXyO1oei2DCp4uojjzQ7igaSHp1kAEQ==} - engines: {node: '>=0.2.0'} - dev: false - /builtin-modules@3.3.0: resolution: {integrity: sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==} engines: {node: '>=6'} @@ -11369,12 +11274,6 @@ packages: type-detect: 4.0.8 dev: true - /chainsaw@0.1.0: - resolution: {integrity: sha512-75kWfWt6MEKNC8xYXIdRpDehRYY/tNSgwKaJq+dbbDcxORuVrrQ+SEHoWsniVn9XPYfP4gmdWIeDk/4YNp1rNQ==} - dependencies: - traverse: 0.3.9 - dev: false - /chalk@2.4.2: resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==} engines: {node: '>=4'} @@ -11828,16 +11727,6 @@ packages: /component-emitter@1.3.1: resolution: {integrity: sha512-T0+barUSQRTUQASh8bx02dl+DhF54GtIDY13Y3m9oWTklKbb3Wv974meRpeZ3lp1JpLVECWWNHC4vaG2XHXouQ==} - /compress-commons@4.1.2: - resolution: {integrity: sha512-D3uMHtGc/fcO1Gt1/L7i1e33VOvD4A9hfQLP+6ewd+BvG/gQ84Yh4oftEhAdjSMgBgwGL+jsppT7JYNpo6MHHg==} - engines: {node: '>= 10'} - dependencies: - buffer-crc32: 0.2.13 - crc32-stream: 4.0.3 - normalize-path: 3.0.0 - readable-stream: 3.6.2 - dev: false - /compressible@2.0.18: resolution: {integrity: sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==} engines: {node: '>= 0.6'} @@ -12205,14 +12094,6 @@ packages: hasBin: true dev: false - /crc32-stream@4.0.3: - resolution: {integrity: sha512-NT7w2JVU7DFroFdYkeq8cywxrgjPHWkdX1wjpRQXPX5Asews3tA+Ght6lddQO5Mkumffp3X7GEqku3epj2toIw==} - engines: {node: '>= 10'} - dependencies: - crc-32: 1.2.2 - readable-stream: 3.6.2 - dev: false - /create-ecdh@4.0.4: resolution: {integrity: sha512-mf+TCx8wWc9VpuxfP2ht0iSISLZnt0JgWlrOKZiNqyUZWnjIaCIVNQArMHnCZKfEYRg6IM7A+NeJoN8gf/Ws0A==} dependencies: @@ -14042,21 +13923,6 @@ packages: md5.js: 1.3.5 safe-buffer: 5.2.1 - /exceljs@4.4.0: - resolution: {integrity: sha512-XctvKaEMaj1Ii9oDOqbW/6e1gXknSY4g/aLCDicOXqBE4M0nRWkUu0PTp++UPNzoFY12BNHMfs/VadKIS6llvg==} - engines: {node: '>=8.3.0'} - dependencies: - archiver: 5.3.2 - dayjs: 1.11.11 - fast-csv: 4.3.6 - jszip: 3.10.1 - readable-stream: 3.6.2 - saxes: 5.0.1 - tmp: 0.2.3 - unzipper: 0.10.14 - uuid: 8.3.2 - dev: false - /exec-sh@0.3.6: resolution: {integrity: sha512-nQn+hI3yp+oD0huYhKwvYI32+JFeq+XkNcD1GAo3Y/MjxsfVGmrrzrnzjWiNY6f+pUCP440fThsFh5gZrRAU/w==} dev: false @@ -14288,14 +14154,6 @@ packages: transitivePeerDependencies: - supports-color - /fast-csv@4.3.6: - resolution: {integrity: sha512-2RNSpuwwsJGP0frGsOmTb9oUF+VkFSM4SyLTDgwf2ciHWTarN0lQTC+F2f/t5J9QjW+c65VFIAAu85GsvMIusw==} - engines: {node: '>=10.0.0'} - dependencies: - '@fast-csv/format': 4.3.5 - '@fast-csv/parse': 4.3.6 - dev: false - /fast-deep-equal@3.1.3: resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} @@ -14807,17 +14665,6 @@ packages: requiresBuild: true optional: true - /fstream@1.0.12: - resolution: {integrity: sha512-WvJ193OHa0GHPEL+AycEJgxvBEwyfRkN1vhjca23OaPVMCaLCXTd5qAu82AjTcgP1UJmytkOKb63Ypde7raDIg==} - engines: {node: '>=0.6'} - deprecated: This package is no longer supported. - dependencies: - graceful-fs: 4.2.11 - inherits: 2.0.4 - mkdirp: 0.5.6 - rimraf: 2.7.1 - dev: false - /function-bind@1.1.2: resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} @@ -17413,13 +17260,6 @@ packages: dotenv: 8.6.0 dotenv-expand: 5.1.0 - /lazystream@1.0.1: - resolution: {integrity: sha512-b94GiNHQNy6JNTrt5w6zNyffMrNkXZb3KTkCZJb2V1xaEGCk093vkZ2jk3tpaeP33/OiXC+WvK9AxUebnf5nbw==} - engines: {node: '>= 0.6.3'} - dependencies: - readable-stream: 2.3.8 - dev: false - /lerna@8.1.6: resolution: {integrity: sha512-O3zSX/dmchMVy9m37DD1BCx7X68nS5lZFECjqG7Siiv3+KgqKXHnF4JQPJUDD/vG2qBQv5StpXCyqGxR0XJVAQ==} engines: {node: '>=18.0.0'} @@ -17614,10 +17454,6 @@ packages: - supports-color dev: true - /listenercount@1.0.1: - resolution: {integrity: sha512-3mk/Zag0+IJxeDrxSgaDPy4zZ3w05PRZeJNnlWhzFz5OkX49J4krc+A8X2d2M69vGMBEX0uyl8M+W+8gH+kBqQ==} - dev: false - /listr2@6.6.1: resolution: {integrity: sha512-+rAXGHh0fkEWdXBmX+L6mmfmXmXvDGEKzkjxO+8mP3+nI/r/CWznVBvsibXdxda9Zz0OW2e2ikphN3OwCT/jSg==} engines: {node: '>=16.0.0'} @@ -17736,30 +17572,10 @@ packages: /lodash.debounce@4.0.8: resolution: {integrity: sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==} - /lodash.defaults@4.2.0: - resolution: {integrity: sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ==} - dev: false - - /lodash.difference@4.5.0: - resolution: {integrity: sha512-dS2j+W26TQ7taQBGN8Lbbq04ssV3emRw4NY58WErlTO29pIqS0HmoT5aJ9+TUQ1N3G+JOZSji4eugsWwGp9yPA==} - dev: false - - /lodash.escaperegexp@4.1.2: - resolution: {integrity: sha512-TM9YBvyC84ZxE3rgfefxUWiQKLilstD6k7PTGt6wfbtXF8ixIJLOL3VYyV/z+ZiPLsVxAsKAFVwWlWeb2Y8Yyw==} - dev: false - - /lodash.flatten@4.4.0: - resolution: {integrity: sha512-C5N2Z3DgnnKr0LOpv/hKCgKdb7ZZwafIrsesve6lmzvZIRZRGaZ/l6Q8+2W7NaT+ZwO3fFlSCzCzrDCFdJfZ4g==} - dev: false - /lodash.get@4.4.2: resolution: {integrity: sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==} dev: false - /lodash.groupby@4.6.0: - resolution: {integrity: sha512-5dcWxm23+VAoz+awKmBaiBvzox8+RqMgFhi7UvX9DHZr2HdxHXM/Wrf8cfKpsW37RNrvtPn6hSwNqurSILbmJw==} - dev: false - /lodash.includes@4.3.0: resolution: {integrity: sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==} dev: false @@ -17774,6 +17590,7 @@ packages: /lodash.isfunction@3.0.9: resolution: {integrity: sha512-AirXNj15uRIMMPihnkInB4i3NHeb4iBtNg9WRWuK2o31S+ePwwNmDPaTL3o7dTJ+VXNZim7rFs4rxN4YU1oUJw==} + dev: true /lodash.isinteger@4.0.4: resolution: {integrity: sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==} @@ -17783,10 +17600,6 @@ packages: resolution: {integrity: sha512-fPMfXjGQEV9Xsq/8MTSgUf255gawYRbjwMyDbcvDhXgV7enSZA0hynz6vMPnpAb5iONEzBHBPsT+0zes5Z301g==} dev: true - /lodash.isnil@4.0.0: - resolution: {integrity: sha512-up2Mzq3545mwVnMhTDMdfoG1OurpA/s5t88JmQX809eH3C8491iu2sfKhTfhQtKY78oPNhiaHJUpT/dUDAAtng==} - dev: false - /lodash.isnumber@3.0.3: resolution: {integrity: sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==} dev: false @@ -17798,10 +17611,6 @@ packages: resolution: {integrity: sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==} dev: false - /lodash.isundefined@3.0.1: - resolution: {integrity: sha512-MXB1is3s899/cD8jheYYE2V9qTHwKvt+npCwpD+1Sxm3Q3cECXCiYHjeHWXNwr6Q0SOBPrYUDxendrO6goVTEA==} - dev: false - /lodash.kebabcase@4.1.1: resolution: {integrity: sha512-N8XRTIMMqqDgSy4VLKPnJ/+hpGZN+PHQiJnSenYqPaVV/NCqEogTnAdZLQiGKhxX+JCs8waWq2t1XHWKOmlY8g==} dev: true @@ -17833,10 +17642,6 @@ packages: resolution: {integrity: sha512-+WKqsK294HMSc2jEbNgpHpd0JfIBhp7rEV4aqXWqFr6AlXov+SlcgB1Fv01y2kGe3Gc8nMW7VA0SrGuSkRfIEg==} dev: true - /lodash.union@4.6.0: - resolution: {integrity: sha512-c4pB2CdGrGdjMKYLA+XiRDO7Y0PRQbm/Gzg8qMj+QH+pFVAoTp5sBpO0odL3FjoPCGjK96p6qsP+yQoiLoOBcw==} - dev: false - /lodash.uniq@4.5.0: resolution: {integrity: sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ==} @@ -21733,12 +21538,6 @@ packages: string_decoder: 1.3.0 util-deprecate: 1.0.2 - /readdir-glob@1.1.3: - resolution: {integrity: sha512-v05I2k7xN8zXvPD9N+z/uhXPaj0sUFCe2rcWZIpBsqxfP7xXFQ0tipAd/wjj1YxWyWtUS5IDJpOG82JKt2EAVA==} - dependencies: - minimatch: 5.1.6 - dev: false - /readdirp@2.2.1: resolution: {integrity: sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==} engines: {node: '>=0.10'} @@ -23810,6 +23609,12 @@ packages: dev: false optional: true + /tippy.js@6.3.7: + resolution: {integrity: sha512-E1d3oP2emgJ9dRQZdf3Kkn0qJgI6ZLpyS5z6ZkY1DF3kaQaBsGZsndEpHwx+eC+tYM41HaSNvNtLx8tU57FzTQ==} + dependencies: + '@popperjs/core': 2.11.8 + dev: false + /tmp@0.0.33: resolution: {integrity: sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==} engines: {node: '>=0.6.0'} @@ -23820,6 +23625,7 @@ packages: /tmp@0.2.3: resolution: {integrity: sha512-nZD7m9iCPC5g0pYmcaxogYKggSfLsdxl8of3Q/oIbqCqLLIO9IAF0GWjX1z9NZRHPiXv8Wex4yDCaZsgEw0Y8w==} engines: {node: '>=14.14'} + dev: true /tmpl@1.0.5: resolution: {integrity: sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==} @@ -23902,10 +23708,6 @@ packages: punycode: 2.3.1 dev: false - /traverse@0.3.9: - resolution: {integrity: sha512-iawgk0hLP3SxGKDfnDJf8wTz4p2qImnyihM5Hh/sGvQ3K37dPi/w8sRhdNIxYA1TwFwc5mDhIJq+O0RsvXBKdQ==} - dev: false - /tree-kill@1.2.2: resolution: {integrity: sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==} hasBin: true @@ -24452,21 +24254,6 @@ packages: os-homedir: 1.0.2 optional: true - /unzipper@0.10.14: - resolution: {integrity: sha512-ti4wZj+0bQTiX2KmKWuwj7lhV+2n//uXEotUmGuQqrbVZSEGFMbI68+c6JCQ8aAmUWYvtHEz2A8K6wXvueR/6g==} - dependencies: - big-integer: 1.6.52 - binary: 0.3.0 - bluebird: 3.4.7 - buffer-indexof-polyfill: 1.0.2 - duplexer2: 0.1.4 - fstream: 1.0.12 - graceful-fs: 4.2.11 - listenercount: 1.0.1 - readable-stream: 2.3.8 - setimmediate: 1.0.5 - dev: false - /upath@1.2.0: resolution: {integrity: sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==} engines: {node: '>=4'} @@ -25712,15 +25499,6 @@ packages: resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} engines: {node: '>=10'} - /zip-stream@4.1.1: - resolution: {integrity: sha512-9qv4rlDiopXg4E69k+vMHjNN63YFMe9sZMrdlvKnCjlCRWeCBswPPMPUfx+ipsAWq1LXHe70RcbaHdJJpS6hyQ==} - engines: {node: '>= 10'} - dependencies: - archiver-utils: 3.0.4 - compress-commons: 4.1.2 - readable-stream: 3.6.2 - dev: false - /zwitch@1.0.5: resolution: {integrity: sha512-V50KMwwzqJV0NpZIZFwfOD5/lyny3WlSzRiXgA0G7VUnRlqttta1L6UQIHzd6EuBY/cHGfwTIck7w1yH6Q5zUw==}