Skip to content
47 changes: 47 additions & 0 deletions apps/api/Transcript Summarization.postman_collection.json
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,53 @@
}
},
"response": []
},
{
"name": "FetchAllRecords",
"request": {
"method": "POST",
"header": [
{
"key": "Accept-Encoding",
"value": "gzip, deflate, br"
},
{
"key": "Content-Type",
"value": "application/json"
},
{
"key": "Accept",
"value": "application/json"
},
{
"key": "Connection",
"value": "keep-alive"
},
{
"key": "Origin",
"value": "chrome-extension://flnheeellpciglgpaodhkhmapeljopja"
}
],
"body": {
"mode": "graphql",
"graphql": {
"query": "{summaries(options:{limit:10 offset:0 sortOrder:ASC filters:[{field:\"createdOn\",operator:\"gte\",value:\"2024-05-09\"}{field:\"jobStatus\",operator:\"eq\",value:\"1\"}]}){limit offset summaries{createdBy createdOn id inputFile jobStatus modifiedBy modifiedOn outputText status}total}}",
"variables": ""
}
},
"url": {
"raw": "http://localhost:3000/graphql",
"protocol": "http",
"host": [
"localhost"
],
"port": "3000",
"path": [
"graphql"
]
}
},
"response": []
}
]
}
23 changes: 17 additions & 6 deletions apps/api/src/common/graphql/services/core.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { QueryOptionsDto } from '../dtos/query-options.dto';
export abstract class CoreService<TEntity> {
protected readonly logger = new Logger(CoreService.name);

constructor(protected readonly repository: Repository<TEntity>) { }
constructor(protected readonly repository: Repository<TEntity>) {}

// List of date fields for comparison handling
private dateFields: string[] = ['createdOn', 'modifiedOn']; // Customize based on your entity fields
Expand Down Expand Up @@ -47,10 +47,19 @@ export abstract class CoreService<TEntity> {
options.filters?.forEach((filter, index) => {
const field = filter.field;
const operator = filter.operator;
const value =
this.isDateField(field) && (operator === 'gt' || operator === 'lt')
? new Date(filter.value)
: filter.value;
let value = filter.value;

if (operator === 'in' && typeof value === 'string') {
try {
// Attempt to parse the string as JSON to convert it into an array
value = JSON.parse(value);
} catch (error) {
this.logger.error(`Error parsing value for 'in' operator: ${error.message}`);
}
} else if (this.isDateField(field) && (operator === 'gt' || operator === 'lt')) {
value = new Date(value) as unknown as string;
}

const paramName = `param${index}`;
let condition = `${alias}.${field}`;

Expand All @@ -67,7 +76,6 @@ export abstract class CoreService<TEntity> {
case 'lt':
condition += ` < :${paramName}`;
break;
condition += ` < :${paramName}`;
case 'gte':
condition += ` >= :${paramName}`;
break;
Expand All @@ -77,6 +85,9 @@ export abstract class CoreService<TEntity> {
case 'ne':
condition += ` != :${paramName}`;
break;
case 'in':
condition += ` IN (:...${paramName})`;
break;
}

queryBuilder.andWhere(condition, {
Expand Down
2 changes: 1 addition & 1 deletion apps/api/src/config/typeorm/configuration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,6 @@ export default new DataSource({
entities: [],
autoLoadEntities: true,
migrations: ['src/database/migrations/**'],
migrationsTableName: 'jobs',
migrationsTableName: 'jobDetails',
synchronize: false,
} as DataSourceOptions);
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import { MigrationInterface, QueryRunner, Table, TableForeignKey, } from "typeorm";
import { MigrationInterface, QueryRunner, Table } from "typeorm";

export class Migration1714646233635 implements MigrationInterface {
export class Migration1715278578144 implements MigrationInterface {

name = 'Migration1715278578144';

name = 'Migration1714646233635';
public async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.createTable(
new Table({
Expand All @@ -18,10 +19,11 @@ export class Migration1714646233635 implements MigrationInterface {
{
name: 'job_status',
type: 'tinyint',
default: 1,
},
{
name: 'input_file',
type: 'int',
type: 'text',
},
{
name: 'output_text',
Expand All @@ -42,10 +44,12 @@ export class Migration1714646233635 implements MigrationInterface {
{
name: 'created_by',
type: 'varchar',
default: "'admin'",
},
{
name: 'modified_by',
type: 'varchar',
default: "'admin'",
},
{
name: 'status',
Expand All @@ -55,20 +59,9 @@ export class Migration1714646233635 implements MigrationInterface {
],
}),
);
await queryRunner.createForeignKey(
'jobs',
new TableForeignKey({
columnNames: ['input_file'],
referencedColumnNames: ['file_id'],
referencedTableName: 'files',
onDelete: 'CASCADE',
}),
);

}

public async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.dropForeignKey('jobs', 'input_file');
await queryRunner.query(`DROP TABLE \`jobs\``);
}

Expand Down
2 changes: 1 addition & 1 deletion apps/api/src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ async function bootstrap(): Promise<void> {
const app = await NestFactory.create(AppModule, {
logger: loggerConfig,
});
app.use(graphqlUploadExpress({ maxFileSize: 1000000, maxFiles: 5 }), (err, req, res, next) => {
app.use(graphqlUploadExpress({ maxFileSize: 1000000, maxFiles: 1 }), (err, req, res, next) => {
if (err) {
res.status(500).json({ error: err.message });
} else {
Expand Down
24 changes: 24 additions & 0 deletions apps/api/src/modules/summary/dto/summary-response.dto.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { ObjectType, Field, Int } from '@nestjs/graphql';
import { Summary } from '../entities/summary.entity';

@ObjectType()
export class SummaryResponse {
@Field(() => [Summary])
summaries: Summary[];

@Field(() => Int)
total: number;

@Field(() => Int)
offset: number;

@Field(() => Int)
limit: number;

constructor(items: Summary[], total: number, offset?: number, limit?: number) {
this.summaries = items;
this.total = total;
this.offset = offset ?? 0;
this.limit = limit ?? items.length;
}
}
12 changes: 5 additions & 7 deletions apps/api/src/modules/summary/entities/summary.entity.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import { ObjectType, Field } from '@nestjs/graphql';
import { Entity, Column, PrimaryGeneratedColumn, UpdateDateColumn, CreateDateColumn } from 'typeorm';
import { IsEnum, IsOptional } from 'class-validator';
import { JobStatus, Status } from 'src/common/constants/summary';

@Entity({ name: 'jobs' })
@ObjectType()
export class Summary {
Expand All @@ -20,17 +19,16 @@ export class Summary {
@IsOptional()
inputFile: string;

@Column({ name: 'output_text' })
@Field()
@IsOptional()
outputFile: string;
@Column({ name: 'output_text', nullable: true })
@Field({ nullable: true })
outputText: string;

@CreateDateColumn({ name: 'created_on' })
@Field()
createdOn: Date;

@UpdateDateColumn({ name: 'modified_on' })
@Field()
@UpdateDateColumn({ name: 'modified_on'})
@Field({ nullable: true })
modifiedOn: Date;

@Column({ name: 'created_by', default: 'admin' })
Expand Down
12 changes: 8 additions & 4 deletions apps/api/src/modules/summary/summary.resolver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ import { Resolver, Query, Mutation, Args } from '@nestjs/graphql';
import { SummaryService } from './summary.service';
import { Summary } from './entities/summary.entity';
import { CreateSummaryDTO } from './dto/create-summary.dto';
import { QueryOptionsDto } from 'src/common/graphql/dtos/query-options.dto';
import { SummaryResponse } from './dto/summary-response.dto';

@Resolver(() => Summary)
export class SummaryResolver {
Expand All @@ -14,9 +16,11 @@ export class SummaryResolver {
return this.summaryService.createSummary(createSummaryInput);
}

@Query(() => [Summary], { name: 'summary' })
async findAll(): Promise<Summary[]> {
return this.summaryService.findAllJobs();
@Query(() => SummaryResponse, { name: 'summaries' })
async findAll(
@Args('options', { type: () => QueryOptionsDto, nullable: true, defaultValue: {} })
options: QueryOptionsDto
): Promise<SummaryResponse> {
return this.summaryService.findAllJobs(options);
}

}
28 changes: 23 additions & 5 deletions apps/api/src/modules/summary/summary.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,21 @@ import { Summary } from './entities/summary.entity';
import { CreateSummaryDTO } from './dto/create-summary.dto';
import { createWriteStream } from 'fs';
import { join } from 'path';
import { v4 as uuidv4 } from 'uuid';
import { QueryOptionsDto } from 'src/common/graphql/dtos/query-options.dto';
import { CoreService } from 'src/common/graphql/services/core.service';
import { Status } from 'src/common/constants/summary';
import { SummaryResponse } from './dto/summary-response.dto';
import { v4 as uuidv4 } from 'uuid';

@Injectable()
export class SummaryService {
export class SummaryService extends CoreService<Summary> {
protected readonly logger = new Logger(SummaryService.name);

constructor(
@InjectRepository(Summary)
private readonly summaryRepository: Repository<Summary>,
) {
super(summaryRepository);
}

async createSummary(createSummaryInput: CreateSummaryDTO): Promise<Summary> {
Expand All @@ -24,7 +28,7 @@ export class SummaryService {
const { createReadStream, filename } = await inputFile;

const uniqueIdentifier = uuidv4();
const modifiedFilename = `${filename}_${uniqueIdentifier}`;
const modifiedFilename = `${uniqueIdentifier}_${filename}`;
const fileLocation = join(process.cwd(), `./src/upload/${modifiedFilename}`);

return new Promise((resolve, reject) => {
Expand All @@ -46,8 +50,22 @@ export class SummaryService {
}
}

async findAllJobs(): Promise<Summary[]> {
return this.summaryRepository.find({ where: { status: Status.ACTIVE } });
async findAllJobs(
options: QueryOptionsDto): Promise<SummaryResponse> {
this.logger.log('Getting all jobs with options.');

const baseConditions = [
{ field: 'status', value: Status.ACTIVE },
];
const searchableFields = ['createdBy', 'data', 'result'];

const { items, total } = await super.findAll(
options,
'summary',
searchableFields,
baseConditions,
);
return new SummaryResponse(items, total, options.offset, options.limit);
}

}
Expand Down