Skip to content
Merged

1.1.0 #244

Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
54 commits
Select commit Hold shift + click to select a range
ab0a930
Merge pull request #230 from iqb-berlin/release-1.0.0
svwolter Aug 29, 2025
06dedcc
Bump @inquirer/editor in the npm_and_yarn group across 1 directory
dependabot[bot] Aug 29, 2025
f07166e
Merge pull request #227 from iqb-berlin/dependabot/npm_and_yarn/npm_a…
jurei733 Sep 16, 2025
63fbb28
Bump the npm_and_yarn group across 1 directory with 3 updates
dependabot[bot] Sep 16, 2025
ac0bc0f
Merge pull request #232 from iqb-berlin/dependabot/npm_and_yarn/npm_a…
jurei733 Sep 16, 2025
a8959c0
Fix coding job variables assignment
jurei733 Aug 13, 2025
25e7f12
Implement frontend sys-admin guard
jurei733 Sep 16, 2025
1e2924d
Edit the "track expression" that it uniquely identifies items in a co…
jurei733 Sep 16, 2025
1f026b4
Replace English text in the booklet info component with German transl…
jurei733 Sep 16, 2025
478e8b7
Use database aggregation to avoid loading all records into memory in …
jurei733 Sep 16, 2025
ee177c7
Fix workspace_id validation by updating the @WorkspaceId() decorator…
jurei733 Sep 16, 2025
45f89b3
Fix the x-axis label spacing issue in coding statistics replay freque…
jurei733 Sep 16, 2025
5432924
Add toggle in workspace admin settings to control whether coding stat…
jurei733 Sep 17, 2025
f4fa4a7
Implement batch updates for test persons coding by replacing individu…
jurei733 Sep 17, 2025
f9fabd5
Merge remote-tracking branch 'origin/main' into develop
jurei733 Sep 17, 2025
297f309
Fix coding job dialog selection
jurei733 Sep 22, 2025
d4c4126
Display coding jobs assigned to coder
jurei733 Sep 23, 2025
af6c78f
Translate unit info dialog into german
jurei733 Sep 24, 2025
364ffd5
Clean up any type
jurei733 Sep 24, 2025
b5b526e
Add german intl service for mat paginator to components
jurei733 Sep 24, 2025
00b5e4f
Display a message for users without access to a workspace.
jurei733 Sep 24, 2025
0df7a4d
Display coding data in bigger view
jurei733 Sep 24, 2025
886bdd4
Undo bulk update with CASE statements
jurei733 Sep 24, 2025
adb704c
Bump tar-fs in the npm_and_yarn group across 1 directory
dependabot[bot] Sep 26, 2025
d0338f8
Merge pull request #234 from iqb-berlin/dependabot/npm_and_yarn/npm_a…
jurei733 Sep 30, 2025
bc9fe0d
Merge remote-tracking branch 'origin/develop' into develop
jurei733 Sep 30, 2025
78958f8
Prettier coding scheme view
jurei733 Sep 30, 2025
f011529
Align container in ws-settings-component
jurei733 Oct 1, 2025
360f2a0
Revert "Align container in ws-settings-component"
jurei733 Oct 1, 2025
2d19a6d
Add sql-lite export in workspace settings and sys settings
jurei733 Oct 1, 2025
3c34537
Merge pull request #236 from iqb-berlin/sqllite-export
jurei733 Oct 2, 2025
7d800d3
Prevent premature status display in test center import
jurei733 Oct 6, 2025
3568874
Show per-category file counts during test center import.
jurei733 Oct 6, 2025
9795371
Update package json lock
jurei733 Oct 8, 2025
60f49d6
Fix deletion logic to allow multiple file deletions
jurei733 Oct 8, 2025
30ba71c
Fix package-lock
jurei733 Oct 8, 2025
bb75ea8
Fix duplicated test results import
jurei733 Sep 30, 2025
87a0ceb
Merge pull request #239 from iqb-berlin/bugfix/duplicated-results-imp…
jurei733 Oct 8, 2025
028c81f
Update the CSV parser to accept empty values in rows.
jurei733 Oct 8, 2025
16253f0
Add the booklet name to the journal entry for booklet deletion.
jurei733 Oct 8, 2025
ad25ade
Modify the journal service to use userId instead of "system" when cre…
jurei733 Oct 8, 2025
070cc13
Update the response table with eight new columns for coding procedure.
jurei733 Oct 9, 2025
fd9a847
Update the response table with new columns for coding procedure.
jurei733 Oct 9, 2025
b0cc002
Update coding using an external file with data for externally manuall…
jurei733 Oct 9, 2025
0d59578
Merge branch 'develop' into feature/external-coding-import
jurei733 Oct 10, 2025
609e8ff
Merge pull request #241 from iqb-berlin/feature/external-coding-import
jurei733 Oct 10, 2025
9475345
Adc coder-training component
jurei733 Oct 10, 2025
f598277
Merge pull request #242 from iqb-berlin/feature/coder-training
jurei733 Oct 13, 2025
e91c8eb
Rename response db coding columns
jurei733 Oct 13, 2025
9a4c73a
Replace `any[]` with a specific CoderTrainingResponse interface
jurei733 Oct 13, 2025
9ce171e
Migrate response table columns from codedstatus to status_v1, code to…
jurei733 Oct 13, 2025
2516957
Modify parseLoadCompleteLog method to remove backslashes from keys an…
jurei733 Oct 13, 2025
f8b9dff
Update @iqb/responses
jurei733 Oct 13, 2025
c6d1440
Set version to 1.1.0
jurei733 Oct 14, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions api-dto/coding/external-coding-import-result.dto.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
export interface ExternalCodingImportResultDto {
message: string;
processedRows: number;
updatedRows: number;
errors: string[];
affectedRows: Array<{
unitAlias: string;
variableId: string;
personCode?: string;
personLogin?: string;
personGroup?: string;
bookletName?: string;
originalCodedStatus: string;
originalCode: number | null;
originalScore: number | null;
updatedCodedStatus: string | null;
updatedCode: number | null;
updatedScore: number | null;
}>;
}
20 changes: 20 additions & 0 deletions api-dto/coding/external-coding-import.dto.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { IsString, IsOptional } from 'class-validator';
import { ApiProperty } from '@nestjs/swagger';

export class ExternalCodingImportDto {
@ApiProperty({
description: 'Base64 encoded file data (CSV or Excel)',
type: 'string'
})
@IsString()
file: string;

@ApiProperty({
description: 'Optional filename',
type: 'string',
required: false
})
@IsOptional()
@IsString()
fileName?: string;
}
10 changes: 8 additions & 2 deletions apps/backend/src/app/admin/admin.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@ import FileUpload from '../database/entities/file_upload.entity';
import { ReplayStatisticsController } from './replay-statistics/replay-statistics.controller';
import { VariableBundleModule } from './variable-bundle/variable-bundle.module';
import { VariableBundleController } from './variable-bundle/variable-bundle.controller';
import { CodingJobsController } from './coding-jobs/coding-jobs.controller';
import { DatabaseAdminController } from './database/database-admin.controller';
import { DatabaseExportService } from './database/database-export.service';

@Module({
imports: [
Expand Down Expand Up @@ -58,11 +61,14 @@ import { VariableBundleController } from './variable-bundle/variable-bundle.cont
UnitInfoController,
MissingsProfilesController,
ReplayStatisticsController,
VariableBundleController
VariableBundleController,
CodingJobsController,
DatabaseAdminController
],
providers: [
BookletInfoService,
UnitInfoService
UnitInfoService,
DatabaseExportService
]
})
export class AdminModule {}
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import {
ToTextFactory, CodeAsText, CodingScheme, VariableCodingData, CodeData
ToTextFactory, CodeAsText
} from '@iqb/responses';
import { VariableCodingData, CodeData, CodingScheme } from '@iqbspecs/coding-scheme/coding-scheme.interface';

import {
BookVariable,
CodeBookContentSetting,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { VariableInfo } from '@iqb/responses';
import { VariableInfo } from '@iqbspecs/variable-info/variable-info.interface';

/**
* Item metadata for codebook
Expand Down
84 changes: 84 additions & 0 deletions apps/backend/src/app/admin/coding-job/coding-job.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -342,4 +342,88 @@ export class CodingJobController {
throw new BadRequestException(`Failed to assign coders: ${error.message}`);
}
}

@Get('/coder/:coderId')
@UseGuards(JwtAuthGuard)
@ApiBearerAuth()
@ApiOperation({
summary: 'Get coding jobs by coder',
description: 'Gets all coding jobs assigned to a specific coder'
})
@ApiParam({
name: 'coderId',
type: Number,
required: true,
description: 'The ID of the coder'
})
@ApiOkResponse({
description: 'The coding jobs assigned to the coder.',
schema: {
type: 'object',
properties: {
data: {
type: 'array',
items: { $ref: '#/components/schemas/CodingJobDto' }
}
}
}
})
async getCodingJobsByCoder(
@Param('coderId', ParseIntPipe) coderId: number
): Promise<{ data: CodingJobDto[] }> {
try {
const codingJobs = await this.codingJobService.getCodingJobsByCoder(coderId);
return {
data: codingJobs.map(job => CodingJobDto.fromEntity(job))
};
} catch (error) {
throw new BadRequestException(`Failed to get coding jobs for coder: ${error.message}`);
}
}

@Get(':jobId/coders')
@UseGuards(JwtAuthGuard)
@ApiBearerAuth()
@ApiOperation({
summary: 'Get coders by job ID',
description: 'Gets all coders assigned to a specific coding job'
})
@ApiParam({
name: 'jobId',
type: Number,
required: true,
description: 'The ID of the coding job'
})
@ApiOkResponse({
description: 'The coders assigned to the coding job.',
schema: {
type: 'object',
properties: {
data: {
type: 'array',
items: {
type: 'object',
properties: {
userId: { type: 'number' }
}
}
},
total: { type: 'number' }
}
}
})
async getCodersByJobId(
@Param('jobId', ParseIntPipe) jobId: number
): Promise<{ data: { userId: number }[], total: number }> {
try {
const coderIds = await this.codingJobService.getCodersByJobId(jobId);
const data = coderIds.map(userId => ({ userId }));
return {
data,
total: data.length
};
} catch (error) {
throw new BadRequestException(`Failed to get coders for job: ${error.message}`);
}
}
}
32 changes: 20 additions & 12 deletions apps/backend/src/app/admin/coding-job/dto/coding-job.dto.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,20 +60,28 @@ export class CodingJobDto {
assigned_coders?: number[];

@ApiProperty({
description: 'Variable IDs assigned to the coding job',
type: [String],
example: ['var1', 'var2', 'var3'],
description: 'Variables assigned to the coding job with unit and variable IDs',
type: [Object],
example: [{ unitName: 'Unit1', variableId: 'var1' }, { unitName: 'Unit2', variableId: 'var2' }],
required: false
})
assigned_variables?: string[];
assigned_variables?: { unitName: string; variableId: string }[];

@ApiProperty({
description: 'Variable bundle names assigned to the coding job',
type: [String],
example: ['Bundle A', 'Bundle B'],
description: 'Variable bundles assigned to the coding job with their variables',
type: [Object],
example: [
{
name: 'Bundle A',
variables: [
{ unitName: 'Unit1', variableId: 'var1' },
{ unitName: 'Unit2', variableId: 'var2' }
]
}
],
required: false
})
assigned_variable_bundles?: string[];
assigned_variable_bundles?: { name: string; variables: { unitName: string; variableId: string }[] }[];

@ApiProperty({
description: 'Variables assigned to the coding job',
Expand All @@ -93,15 +101,15 @@ export class CodingJobDto {
* Create a CodingJobDto from a CodingJob entity
* @param entity The CodingJob entity
* @param assignedCoders Optional array of assigned coder IDs
* @param assignedVariables Optional array of assigned variable IDs
* @param assignedVariableBundles Optional array of assigned variable bundle names
* @param assignedVariables Optional array of assigned variable objects with unit and variable IDs
* @param assignedVariableBundles Optional array of assigned variable bundle objects with name and variables
* @returns A CodingJobDto
*/
static fromEntity(
entity: CodingJob,
assignedCoders?: number[],
assignedVariables?: string[],
assignedVariableBundles?: string[]
assignedVariables?: { unitName: string; variableId: string }[],
assignedVariableBundles?: { name: string; variables: { unitName: string; variableId: string }[] }[]
): CodingJobDto {
const dto = new CodingJobDto();
dto.id = entity.id;
Expand Down
Loading