From 0eb6869da77498a8c5fc9b24d320edba665327bb Mon Sep 17 00:00:00 2001 From: chavda-bhavik Date: Wed, 12 Jun 2024 14:33:52 +0530 Subject: [PATCH 1/5] feat: Updated APIs to consider isFrozen field --- .../api/src/app/column/commands/add-column.command.ts | 8 ++++++-- .../src/app/column/commands/update-column.command.ts | 8 ++++++-- apps/api/src/app/column/dtos/column-request.dto.ts | 11 +++++++++-- apps/api/src/app/column/dtos/column-response.dto.ts | 9 +++++++-- .../usecases/create-project/create-project.usecase.ts | 1 + apps/api/src/app/template/template.controller.ts | 1 + .../usecases/get-columns/get-columns.usecase.ts | 7 ++++++- apps/api/src/app/upload/upload.controller.ts | 4 ++-- .../usecases/get-columns/get-columns.usecase.ts | 4 +++- .../make-upload-entry/make-upload-entry.usecase.ts | 3 ++- libs/dal/src/repositories/column/column.entity.ts | 6 ++++-- libs/dal/src/repositories/column/column.schema.ts | 1 + libs/shared/src/entities/Column/Column.interface.ts | 1 + libs/shared/src/types/column/column.types.ts | 1 + 14 files changed, 50 insertions(+), 15 deletions(-) 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 0fbe7dce0..60389d6d8 100644 --- a/apps/api/src/app/column/commands/add-column.command.ts +++ b/apps/api/src/app/column/commands/add-column.command.ts @@ -20,11 +20,15 @@ export class AddColumnCommand extends BaseCommand { @IsBoolean() @IsOptional() - isRequired = false; + isRequired? = false; @IsBoolean() @IsOptional() - isUnique = false; + isUnique? = false; + + @IsBoolean() + @IsOptional() + isFrozen? = false; @IsDefined() type: ColumnTypesEnum; 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 58b5c7146..1414b8412 100644 --- a/apps/api/src/app/column/commands/update-column.command.ts +++ b/apps/api/src/app/column/commands/update-column.command.ts @@ -20,11 +20,15 @@ export class UpdateColumnCommand extends BaseCommand { @IsBoolean() @IsOptional() - isRequired = false; + isRequired? = false; @IsBoolean() @IsOptional() - isUnique = false; + isUnique? = false; + + @IsBoolean() + @IsOptional() + isFrozen? = false; @IsDefined() type: ColumnTypesEnum; 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 83b560536..a55d66236 100644 --- a/apps/api/src/app/column/dtos/column-request.dto.ts +++ b/apps/api/src/app/column/dtos/column-request.dto.ts @@ -43,14 +43,21 @@ export class ColumnRequestDto { }) @IsBoolean() @IsOptional() - isRequired = false; + isRequired? = false; @ApiPropertyOptional({ description: 'While true, it Indicates column value should be unique in data', }) @IsBoolean() @IsOptional() - isUnique = false; + isUnique? = false; + + @ApiPropertyOptional({ + description: 'While true, it Indicates column value should be frozen in data', + }) + @IsBoolean() + @IsOptional() + isFrozen? = false; @ApiProperty({ description: 'Specifies the type of column', 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 790ce0047..73abaee99 100644 --- a/apps/api/src/app/column/dtos/column-response.dto.ts +++ b/apps/api/src/app/column/dtos/column-response.dto.ts @@ -22,12 +22,17 @@ export class ColumnResponseDto { @ApiPropertyOptional({ description: 'While true, it Indicates column value should exists in data', }) - isRequired = false; + isRequired? = false; @ApiPropertyOptional({ description: 'While true, it Indicates column value should be unique in data', }) - isUnique = false; + isUnique? = false; + + @ApiPropertyOptional({ + description: 'While true, it Indicates column value should be frozen in data', + }) + isFrozen? = false; @ApiProperty({ description: 'Specifies the type of column', 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 cd410362a..1541d7547 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 *', + isFrozen: true, type: ColumnTypesEnum.DATE, isRequired: true, dateFormats: ['DD/MM/YYYY'], diff --git a/apps/api/src/app/template/template.controller.ts b/apps/api/src/app/template/template.controller.ts index c47d25d69..0976acc88 100644 --- a/apps/api/src/app/template/template.controller.ts +++ b/apps/api/src/app/template/template.controller.ts @@ -187,6 +187,7 @@ export class TemplateController { alternateKeys: columnData.alternateKeys, isRequired: columnData.isRequired, isUnique: columnData.isUnique, + isFrozen: columnData.isFrozen, name: columnData.name, regex: columnData.regex, regexDescription: columnData.regexDescription, 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 8e14992e6..1b325eb11 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 @@ -8,7 +8,12 @@ export class GetTemplateColumns { async execute(_templateId: string) { return this.columnRepository.find( { _templateId }, - '_id name key type alternateKeys isRequired isUnique selectValues regex dateFormats defaultValue sequence allowMultiSelect' + '_id name key type alternateKeys isRequired isUnique isFrozen selectValues regex dateFormats defaultValue sequence allowMultiSelect', + { + sort: { + isFrozen: -1, + }, + } ); } } diff --git a/apps/api/src/app/upload/upload.controller.ts b/apps/api/src/app/upload/upload.controller.ts index 52e62c809..428b3b822 100644 --- a/apps/api/src/app/upload/upload.controller.ts +++ b/apps/api/src/app/upload/upload.controller.ts @@ -1,7 +1,7 @@ // eslint-disable-next-line @typescript-eslint/no-unused-vars, no-unused-vars import _whatever from 'multer'; import { Response } from 'express'; -import { ColumnEntity, FileEntity } from '@impler/dal'; +import { FileEntity } from '@impler/dal'; import { FileInterceptor } from '@nestjs/platform-express'; import { ACCESS_KEY_NAME, Defaults, UploadStatusEnum } from '@impler/shared'; import { @@ -120,7 +120,7 @@ export class UploadController { @ApiOperation({ summary: 'Get upload columns', }) - async getColumns(@Param('uploadId', ValidateMongoId) uploadId: string): Promise { + async getColumns(@Param('uploadId', ValidateMongoId) uploadId: string) { return this.getUploadColumns.execute(uploadId); } diff --git a/apps/api/src/app/upload/usecases/get-columns/get-columns.usecase.ts b/apps/api/src/app/upload/usecases/get-columns/get-columns.usecase.ts index 40eed23c6..951f89ebe 100644 --- a/apps/api/src/app/upload/usecases/get-columns/get-columns.usecase.ts +++ b/apps/api/src/app/upload/usecases/get-columns/get-columns.usecase.ts @@ -1,5 +1,6 @@ import { Injectable } from '@nestjs/common'; import { UploadRepository } from '@impler/dal'; +import { ISchemaColumn } from '@impler/shared'; @Injectable() export class GetUploadColumns { @@ -7,7 +8,8 @@ export class GetUploadColumns { async execute(_uploadId: string) { const upload = await this.uploadRepository.findById(_uploadId, 'customSchema'); + const columns = JSON.parse(upload.customSchema) as ISchemaColumn[]; - return JSON.parse(upload.customSchema); + return columns.sort((a, b) => (a.isFrozen === b.isFrozen ? 0 : a.isFrozen ? -1 : 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 380e64f26..fc597a83f 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 @@ -70,7 +70,7 @@ export class MakeUploadEntry { { _templateId: templateId, }, - 'name key isRequired isUnique selectValues dateFormats defaultValue type regex sequence allowMultiSelect', + 'name key isRequired isUnique isFrozen selectValues dateFormats defaultValue type regex sequence allowMultiSelect', { sort: 'sequence', } @@ -86,6 +86,7 @@ export class MakeUploadEntry { formattedColumns[schemaItem.key] = { name: schemaItem.name || 'Untitled Column', isRequired: schemaItem.isRequired || false, + isFrozen: schemaItem.isFrozen, key: schemaItem.key, type: schemaItem.type || ColumnTypesEnum.STRING, regex: schemaItem.regex, diff --git a/libs/dal/src/repositories/column/column.entity.ts b/libs/dal/src/repositories/column/column.entity.ts index d8630f95f..66f549f06 100644 --- a/libs/dal/src/repositories/column/column.entity.ts +++ b/libs/dal/src/repositories/column/column.entity.ts @@ -7,9 +7,11 @@ export class ColumnEntity { alternateKeys?: string[]; - isRequired: boolean; + isRequired?: boolean; - isUnique: boolean; + isUnique?: boolean; + + isFrozen?: boolean; type: string; diff --git a/libs/dal/src/repositories/column/column.schema.ts b/libs/dal/src/repositories/column/column.schema.ts index f978aa41c..3a51ae359 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, + isFrozen: Boolean, regex: String, allowMultiSelect: Boolean, regexDescription: String, diff --git a/libs/shared/src/entities/Column/Column.interface.ts b/libs/shared/src/entities/Column/Column.interface.ts index 86d20b5ea..894fb7063 100644 --- a/libs/shared/src/entities/Column/Column.interface.ts +++ b/libs/shared/src/entities/Column/Column.interface.ts @@ -6,6 +6,7 @@ export interface IColumn { alternateKeys?: string[]; isRequired?: boolean; isUnique?: boolean; + isFrozen?: boolean; regex?: string; allowMultiSelect?: boolean; defaultValue?: string | number; diff --git a/libs/shared/src/types/column/column.types.ts b/libs/shared/src/types/column/column.types.ts index 33007ff1d..9b7644b7e 100644 --- a/libs/shared/src/types/column/column.types.ts +++ b/libs/shared/src/types/column/column.types.ts @@ -15,6 +15,7 @@ export interface ISchemaItem { alternateKeys?: string[]; isRequired?: boolean; isUnique?: boolean; + isFrozen?: boolean; selectValues?: string[]; dateFormats?: string[]; type?: ColumnTypesEnum; From 51a3162d2f698e2901caec7fc4e0dbb01bf69290 Mon Sep 17 00:00:00 2001 From: chavda-bhavik Date: Wed, 12 Jun 2024 14:35:02 +0530 Subject: [PATCH 2/5] feat: Generated sample file with frozen columns --- .../app/shared/services/file/file.service.ts | 4 ++++ apps/api/src/app/shared/types/file.types.ts | 1 + .../save-sample-file.usecase.ts | 20 +++++++++++-------- 3 files changed, 17 insertions(+), 8 deletions(-) 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 2148f4768..5be4e0455 100644 --- a/apps/api/src/app/shared/services/file/file.service.ts +++ b/apps/api/src/app/shared/services/file/file.service.ts @@ -109,6 +109,10 @@ export class ExcelFileService { worksheet.column(columnName).style('numberFormat', '@'); }); + const frozenColumns = headings.filter((heading) => heading.isFrozen).length; + if (frozenColumns) worksheet.freezePanes(frozenColumns, 1); // freeze panes (freeze first n column and first row) + else worksheet.freezePanes(0, 1); // freeze 0 column and first row + headings.forEach((heading, index) => { if (heading.type === ColumnTypesEnum.SELECT) { const keyName = this.addSelectSheet(workbook, heading); diff --git a/apps/api/src/app/shared/types/file.types.ts b/apps/api/src/app/shared/types/file.types.ts index bff8efb50..4e7d48fae 100644 --- a/apps/api/src/app/shared/types/file.types.ts +++ b/apps/api/src/app/shared/types/file.types.ts @@ -3,6 +3,7 @@ import { ColumnTypesEnum } from '@impler/shared'; export interface IExcelFileHeading { key: string; isRequired?: boolean; + isFrozen?: boolean; type: ColumnTypesEnum; selectValues?: string[]; dateFormats?: 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 c20dfe8d7..7c073b033 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 @@ -15,14 +15,18 @@ export class SaveSampleFile { ) {} async execute(columns: ColumnEntity[], templateId: string) { - const columnKeys: IExcelFileHeading[] = columns.map((columnItem) => ({ - key: columnItem.key, - type: columnItem.type as ColumnTypesEnum, - selectValues: columnItem.selectValues, - isRequired: columnItem.isRequired, - dateFormats: columnItem.dateFormats, - allowMultiSelect: columnItem.allowMultiSelect, - })); + const columnKeys: IExcelFileHeading[] = columns + .map((columnItem) => ({ + key: columnItem.key, + type: columnItem.type as ColumnTypesEnum, + selectValues: columnItem.selectValues, + isFrozen: columnItem.isFrozen, + isRequired: columnItem.isRequired, + dateFormats: columnItem.dateFormats, + allowMultiSelect: columnItem.allowMultiSelect, + })) + .sort((a, b) => (a.isFrozen === b.isFrozen ? 0 : a.isFrozen ? -1 : 1)); + const hasMultiSelect = columns.some( (columnItem) => columnItem.type === ColumnTypesEnum.SELECT && columnItem.allowMultiSelect ); From 5e0fb12a373c0290f08473f6073357d3a172c18f Mon Sep 17 00:00:00 2001 From: chavda-bhavik Date: Wed, 12 Jun 2024 14:36:10 +0530 Subject: [PATCH 3/5] feat: Added frozen field to column form --- .../components/imports/forms/ColumnForm.tsx | 1 + .../imports/schema/ColumnsTable.tsx | 19 ++++++++++++++----- apps/web/hooks/useColumnsEditor.tsx | 4 ++-- .../Common/Table/HandsonTable.styles.min.css | 8 +++++++- .../src/components/Common/Table/Table.tsx | 4 ++++ .../widget/Phases/Phase3/Phase3.tsx | 3 +++ apps/widget/src/hooks/Phase3/usePhase3.tsx | 6 +++++- 7 files changed, 36 insertions(+), 9 deletions(-) diff --git a/apps/web/components/imports/forms/ColumnForm.tsx b/apps/web/components/imports/forms/ColumnForm.tsx index 8eec96ef3..d76b494f8 100644 --- a/apps/web/components/imports/forms/ColumnForm.tsx +++ b/apps/web/components/imports/forms/ColumnForm.tsx @@ -166,6 +166,7 @@ export function ColumnForm({ onSubmit, data, isLoading }: ColumnFormProps) { ) : ( )} +