Skip to content

Commit

Permalink
feat output improvments (#454)
Browse files Browse the repository at this point in the history
  • Loading branch information
chavda-bhavik authored Dec 28, 2023
2 parents 7d48477 + 248eb9b commit e75bb22
Show file tree
Hide file tree
Showing 14 changed files with 143 additions and 26 deletions.
21 changes: 19 additions & 2 deletions apps/api/src/app/template/template.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import {
CreateTemplate,
DeleteTemplate,
UpdateTemplate,
SyncCustomization,
GetTemplateDetails,
GetUploadsCommand,
CreateTemplateCommand,
Expand Down Expand Up @@ -47,17 +48,18 @@ import { UpdateCustomizationRequestDto } from './dtos/update-customization-reque
@UseGuards(JwtAuthGuard)
export class TemplateController {
constructor(
private getTemplateColumns: GetTemplateColumns,
private getUploads: GetUploads,
private getValidations: GetValidations,
private downloadSample: DownloadSample,
private getCustomization: GetCustomization,
private updateValidations: UpdateValidations,
private updateCustomization: UpdateCustomization,
private syncCustomization: SyncCustomization,
private createTemplateUsecase: CreateTemplate,
private updateTemplateUsecase: UpdateTemplate,
private deleteTemplateUsecase: DeleteTemplate,
private getTemplateColumns: GetTemplateColumns,
private getTemplateDetails: GetTemplateDetails,
private updateCustomization: UpdateCustomization,
private updateTemplateColumns: UpdateTemplateColumns
) {}

Expand Down Expand Up @@ -205,6 +207,7 @@ export class TemplateController {
);
}

// Customization
@Get(':templateId/customizations')
@ApiOperation({
summary: 'Get template customizations',
Expand All @@ -230,6 +233,20 @@ export class TemplateController {
return this.updateCustomization.execute(templateId, UpdateCustomizationCommand.create(body));
}

@Put(':templateId/customizations/sync')
@ApiOperation({
summary: 'Sync template customizations',
})
@ApiOkResponse({
type: CustomizationResponseDto,
})
async syncCustomizationRoute(
@Param('templateId', ValidateMongoId) templateId: string
): Promise<CustomizationResponseDto> {
return this.syncCustomization.execute(templateId);
}

// Validations
@Get(':templateId/validations')
@ApiOperation({
summary: 'Get template validations',
Expand Down
11 changes: 7 additions & 4 deletions apps/api/src/app/template/usecases/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,14 @@ import { CreateTemplate } from './create-template/create-template.usecase';
import { UpdateTemplate } from './update-template/update-template.usecase';
import { DeleteTemplate } from './delete-template/delete-template.usecase';
import { DownloadSample } from './download-sample/download-sample.usecase';
import { GetTemplateDetails } from './get-template-details/get-template-details.usecase';
import { UpdateTemplateColumns } from './update-template-columns/update-template-columns.usecase';
import { UpdateCustomization } from './update-customization/update-customization.usecase';
import { GetValidations } from './get-validations/get-validations.usecase';
import { GetCustomization } from './get-customization/get-customization.usecase';
import { SyncCustomization } from './sync-customization/sync-customization.usecase';
import { UpdateValidations } from './update-validations/update-validations.usecase';
import { GetValidations } from './get-validations/get-validations.usecase';
import { GetTemplateDetails } from './get-template-details/get-template-details.usecase';
import { UpdateCustomization } from './update-customization/update-customization.usecase';
import { SaveSampleFile } from '@shared/usecases/save-sample-file/save-sample-file.usecase';
import { UpdateTemplateColumns } from './update-template-columns/update-template-columns.usecase';

import { GetUploadsCommand } from './get-uploads/get-uploads.command';
import { CreateTemplateCommand } from './create-template/create-template.command';
Expand All @@ -24,6 +25,7 @@ export const USE_CASES = [
DeleteTemplate,
GetTemplateDetails,
GetUploads,
SyncCustomization,
GetTemplateColumns,
UpdateTemplateColumns,
UpdateCustomization,
Expand All @@ -39,6 +41,7 @@ export {
CreateTemplate,
UpdateTemplate,
DeleteTemplate,
SyncCustomization,
GetTemplateDetails,
GetUploads,
GetTemplateColumns,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { Injectable } from '@nestjs/common';

import { CONSTANTS } from '@shared/constants';
import { createRecordFormat, updateCombinedFormat } from '@impler/shared';
import { CustomizationRepository } from '@impler/dal';

@Injectable()
export class SyncCustomization {
constructor(private customizationRepository: CustomizationRepository) {}

async execute(_templateId: string) {
const customization = await this.customizationRepository.findOne({
_templateId,
});
customization.isChunkFormatUpdated = false;
customization.isRecordFormatUpdated = false;
customization.isCombinedFormatUpdated = false;

customization.recordFormat = createRecordFormat(customization.recordVariables);
customization.combinedFormat = updateCombinedFormat(CONSTANTS.COMBINED_FORMAT, customization.recordVariables);

await this.customizationRepository.update({ _templateId }, customization);

return customization;
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { CustomizationRepository } from '@impler/dal';
import { createVariable, getRecordFormat } from '@impler/shared';
import { getRecordFormat } from '@impler/shared';
import { HttpException, Injectable } from '@nestjs/common';

import { UpdateCustomizationCommand } from './update-customization.command';
Expand All @@ -25,7 +25,7 @@ export class UpdateCustomization {
throw new DocumentNotFoundException('Customization', _templateId);
}

this.customizationRepository.findOneAndUpdate(
return this.customizationRepository.findOneAndUpdate(
{
_templateId,
},
Expand All @@ -36,11 +36,5 @@ export class UpdateCustomization {
isChunkFormatUpdated: data.chunkFormat !== customization.chunkFormat,
}
);

return {
...customization,
recordVariables: customization.recordVariables?.map((variable) => createVariable(variable)),
chunkVariables: customization.chunkVariables?.map((variable) => createVariable(variable)),
};
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -43,12 +43,12 @@ export class UpdateTemplateColumns {
customizationUpdate.recordVariables = this.listRecordVariables(data);

if (!customization.isRecordFormatUpdated) {
customizationUpdate.recordFormat = createRecordFormat(customization.recordVariables);
customizationUpdate.recordFormat = createRecordFormat(customizationUpdate.recordVariables);
}
if (!customization.isCombinedFormatUpdated) {
customizationUpdate.combinedFormat = updateCombinedFormat(
CONSTANTS.COMBINED_FORMAT,
customization.recordVariables
customizationUpdate.recordVariables
);
}

Expand Down
17 changes: 17 additions & 0 deletions apps/web/assets/icons/Warning.icon.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { IconType } from '@types';
import { IconSizes } from 'config';

export const WarningIcon = ({ size = 'sm', color }: IconType) => {
return (
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="-2 -2 24 24"
fill="currentColor"
width={IconSizes[size]}
height={IconSizes[size]}
color={color}
>
<path 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-13a1 1 0 0 1 1 1v5a1 1 0 0 1-2 0V6a1 1 0 0 1 1-1zm0 10a1 1 0 1 1 0-2 1 1 0 0 1 0 2z" />
</svg>
);
};
26 changes: 20 additions & 6 deletions apps/web/components/imports/editor/Editor.tsx
Original file line number Diff line number Diff line change
@@ -1,23 +1,27 @@
import { Controller } from 'react-hook-form';
import { Group, Title, Text, useMantineColorScheme, Flex, Alert, Code, Stack } from '@mantine/core';
import { Group, Title, Text, useMantineColorScheme, Flex, Code, Stack } from '@mantine/core';

import { colors } from '@config';
import { Button } from '@ui/button';
import { Editor } from '@ui/editor/Editor';
import { useEditor } from '@hooks/useEditor';

import { Alert } from '@ui/Alert';
import { VarLabel } from './VarLabel';
import { VarItemWrapper } from './VarItemWrapper';
import { PossibleJSONErrors } from '@components/common/PossibleJsonErrors';
import { WarningIcon } from '@assets/icons/Warning.icon';
import { InformationIcon } from '@assets/icons/Information.icon';
import { PossibleJSONErrors } from '@components/common/PossibleJsonErrors';

interface OutputEditorProps {
templateId: string;
}

export function OutputEditor({ templateId }: OutputEditorProps) {
const { colorScheme } = useMantineColorScheme();
const { customization, control, errors, onSaveClick } = useEditor({ templateId });
const { customization, control, errors, onSaveClick, syncCustomization, isSyncCustomizationLoading } = useEditor({
templateId,
});

return (
<Stack spacing="sm">
Expand All @@ -33,18 +37,28 @@ export function OutputEditor({ templateId }: OutputEditorProps) {

<Button onClick={onSaveClick}>Save</Button>
</Group>
<Alert icon={<InformationIcon />} p="xs">
<Alert icon={<InformationIcon size="sm" />} p="xs">
<Code>{`%<var>%`}</Code> will be used to loop over data items.
</Alert>
{customization?.isCombinedFormatUpdated && (
<Alert p="xs" color="red" icon={<WarningIcon size="sm" />}>
<Flex align="center" justify="space-between">
Format is updated manually. The update in schema will not reflact automatically in output.
<Button size="xs" onClick={syncCustomization} loading={isSyncCustomizationLoading}>
Sync Again
</Button>
</Flex>
</Alert>
)}
<Flex gap="xs">
<div style={{ width: '80%' }}>
<Controller
control={control}
name="combinedFormat"
render={({ field }) => (
<Editor
name="recordItem"
id="record-item"
name="combinedFormat"
id="combined-format"
value={field.value}
onChange={field.onChange}
variables={[...(customization?.recordVariables || []), ...(customization?.chunkVariables || [])]}
Expand Down
1 change: 1 addition & 0 deletions apps/web/config/constants.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ export const API_KEYS = {
TEMPLATE_CUSTOMIZATION_GET: 'CUSTOMIZATION_GET',
TEMPLATE_COLUMNS_UPDATE: 'TEMPLATE_COLUMNS_UPDATE',
TEMPLATE_CUSTOMIZATION_UPDATE: 'CUSTOMIZATION_UPDATE',
TEMPLATE_CUSTOMIZATION_SYNC: 'CUSTOMIZATION_SYNC',

COLUMN_CREATE: 'COLUMN_CREATE',
COLUMN_UPDATE: 'COLUMN_UPDATE',
Expand Down
11 changes: 11 additions & 0 deletions apps/web/design-system/Alert/Alert.styles.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { createStyles } from '@mantine/core';

const getWrapperStyles = (): React.CSSProperties => ({
alignItems: 'center',
});

export default createStyles((): Record<string, any> => {
return {
wrapper: getWrapperStyles(),
};
});
11 changes: 11 additions & 0 deletions apps/web/design-system/Alert/Alert.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { Alert as MantineAlert, AlertProps as MantineAlertProps } from '@mantine/core';

import useStyles from './Alert.styles';

type AlertProps = MantineAlertProps;

export function Alert(props: AlertProps) {
const { classes } = useStyles();

return <MantineAlert classNames={classes} {...props} />;
}
1 change: 1 addition & 0 deletions apps/web/design-system/Alert/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './Alert';
18 changes: 18 additions & 0 deletions apps/web/hooks/useEditor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ export function useEditor({ templateId }: UseEditorProps) {
reset,
control,
setError,
setValue,
handleSubmit,
formState: { errors },
} = useForm<CustomizationDataFormat>();
Expand Down Expand Up @@ -63,6 +64,21 @@ export function useEditor({ templateId }: UseEditorProps) {
},
}
);
const { mutate: syncCustomization, isLoading: isSyncCustomizationLoading } = useMutation<
ICustomization,
IErrorObject,
void,
string[]
>(
[API_KEYS.TEMPLATE_CUSTOMIZATION_UPDATE, templateId],
() => commonApi<ICustomization>(API_KEYS.TEMPLATE_CUSTOMIZATION_SYNC as any, { parameters: [templateId] }),
{
onSuccess(data) {
queryClient.setQueryData([API_KEYS.TEMPLATE_CUSTOMIZATION_GET, templateId], data);
setValue('combinedFormat', data.combinedFormat);
},
}
);

const validateFormat = (data: string): boolean => {
try {
Expand Down Expand Up @@ -100,8 +116,10 @@ export function useEditor({ templateId }: UseEditorProps) {
onSaveClick,
handleSubmit,
customization,
syncCustomization,
updateCustomization,
isCustomizationLoading,
isSyncCustomizationLoading,
isUpdateCustomizationLoading,
};
}
4 changes: 4 additions & 0 deletions apps/web/libs/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,10 @@ const routes: Record<string, Route> = {
url: (templateId) => `/v1/template/${templateId}/customizations`,
method: 'PUT',
},
[API_KEYS.TEMPLATE_CUSTOMIZATION_SYNC]: {
url: (templateId) => `/v1/template/${templateId}/customizations/sync`,
method: 'PUT',
},
[API_KEYS.COLUMN_CREATE]: {
url: (templateId) => `/v1/column/${templateId}`,
method: 'POST',
Expand Down
8 changes: 4 additions & 4 deletions apps/web/libs/notify.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,12 @@ const Messages: Record<string, NotifyProps> = {
message: 'Import details has been updated',
},
[NOTIFICATION_KEYS.IMPORT_CREATED]: {
title: 'Import record created',
message: 'Import record has been created successfully',
title: 'Import created',
message: 'Import has been created successfully',
},
[NOTIFICATION_KEYS.IMPORT_DELETED]: {
title: 'Import record deleted',
message: 'Import record has been deleted successfully',
title: 'Import deleted',
message: 'Import has been deleted successfully',
},
[NOTIFICATION_KEYS.DESTINATION_UPDATED]: {
title: 'Destination details updated',
Expand Down

0 comments on commit e75bb22

Please sign in to comment.