diff --git a/frontend/src/app/template/template-builder/components/task-types-list/task-types-list.component.ts b/frontend/src/app/template/template-builder/components/task-types-list/task-types-list.component.ts index 2899851c2..501c55116 100644 --- a/frontend/src/app/template/template-builder/components/task-types-list/task-types-list.component.ts +++ b/frontend/src/app/template/template-builder/components/task-types-list/task-types-list.component.ts @@ -4,7 +4,7 @@ import { TemplateBuilderService } from "../../template-builder.service"; import { MatDialog } from "@angular/material/dialog"; import { ApiTaskType, TemplateService } from "../../../../../../openapi"; import { Observable } from "rxjs"; -import { filter, map, shareReplay } from "rxjs/operators"; +import { filter, map, shareReplay, tap } from "rxjs/operators"; import { CompetitionBuilderTaskTypeDialogComponent } from "../../../../competition/competition-builder/competition-builder-task-type-dialog/competition-builder-task-type-dialog.component"; @@ -74,7 +74,7 @@ export class TaskTypesListComponent extends AbstractTemplateBuilderComponent imp } else { return []; } - })); + }), tap((t) => this.table?.renderRows())); } diff --git a/frontend/src/app/template/template-builder/components/template-import-tree/template-import-tree.component.ts b/frontend/src/app/template/template-builder/components/template-import-tree/template-import-tree.component.ts index 7fcd9cf96..43de238b0 100644 --- a/frontend/src/app/template/template-builder/components/template-import-tree/template-import-tree.component.ts +++ b/frontend/src/app/template/template-builder/components/template-import-tree/template-import-tree.component.ts @@ -76,12 +76,12 @@ export class TemplateImportTreeComponent implements OnInit{ ) this.treeControl = new FlatTreeControl>(this.getLevel, this.isExpandable); this.dataSource = new MatTreeFlatDataSource, TemplateTreeFlatNode>(this.treeControl, this.treeFlattener); - } ngOnInit(): void { this.dataSource.data = TemplateImportTreeComponent.buildTrees(this.templates, this.branches); this.templates.forEach(it => this.templatesMap.set(it.id, it)); + console.log(this.templatesMap) } getLevel = (node: TemplateTreeFlatNode) => node.level; @@ -183,44 +183,80 @@ export class TemplateImportTreeComponent implements OnInit{ } public getImportTemplate(){ - const template = { + const types: ApiTaskType[] = []; + const taskGroups: ApiTaskGroup[] = []; + const tasks: ApiTaskTemplate[] = []; + const teams: ApiTeam[] = this.getAllSelectedTeams().map(it => it[0]); + const teamGroups: ApiTeamGroup[] = this.getAllSelectedTeamGroups().map(it => it[0]); + const judges: ApiUser[] = this.getAllSelectedJudges().map(it => it[0]); + /** Sanitation */ + /* Tasks require task groups which in turn require types*/ + this.getAllSelectedTaskTemplates().forEach(it => { + it[0].id = undefined + tasks.push(it[0]); + const group = this.templatesMap.get(it[1]).taskGroups.find((g:ApiTaskGroup) => g.name === it[0].taskGroup) + if(!taskGroups.includes(group)){ + taskGroups.push(group); + } + const type = this.templatesMap.get(it[1]).taskTypes.find((t:ApiTaskType) => t.name === group.type) + if(!types.includes(type)){ + types.push(type) + } + }) + + /* TaskGroup requires TaskType */ + this.getAllSelectedTaskGroups().forEach(it => { + if(!taskGroups.includes(it[0])){ + taskGroups.push(it[0]) + const type = this.templatesMap.get(it[1]).taskTypes.find((t: ApiTaskType) => t.name === it[0].type) + if(!types.includes(type)){ + types.push(type) + } + } + }) + + this.getAllSelectedTaskTypes().forEach(it => { + if(!types.includes(it[0])){ + types.push(it[0]) + } + }) + + + return { name: "", description: "---Automatically generated template whose elements get imported. If this is seen, there was a programmer's error somewhere---", - taskTypes: this.getAllSelectedTaskTypes(), - taskGroups: this.getAllSelectedTaskGroups(), - tasks: this.getAllSelectedTaskTemplates(), - teams: this.getAllSelectedTeams(), - teamGroups: this.getAllSelectedTeamGroups(), - judges: this.getAllSelectedJudges(), + taskTypes: types, + taskGroups: taskGroups, + tasks: tasks, + teams: teams, + teamGroups: teamGroups, + judges: judges, id:"---IMPORT_TEMPLATE_NO_ID---" } as ApiEvaluationTemplate - - /* Sanitisation: For each task, the group and type is required */ - return template; } public getAllSelectedTaskTypes(){ - return this.getSelectedItemsForBranch(TemplateImportTreeBranch.TASK_TYPES) as ApiTaskType[] + return this.getSelectedItemsForBranch(TemplateImportTreeBranch.TASK_TYPES) as [ApiTaskType, string][] } public getAllSelectedTaskGroups(){ - return this.getSelectedItemsForBranch(TemplateImportTreeBranch.TASK_GROUPS) as ApiTaskGroup[]; + return this.getSelectedItemsForBranch(TemplateImportTreeBranch.TASK_GROUPS) as [ApiTaskGroup,string][]; } public getAllSelectedTaskTemplates(){ - return this.getSelectedItemsForBranch(TemplateImportTreeBranch.TASK_TEMPLATES) as ApiTaskTemplate[] + return this.getSelectedItemsForBranch(TemplateImportTreeBranch.TASK_TEMPLATES) as [ApiTaskTemplate, string][] } public getAllSelectedTeams(){ - return this.getSelectedItemsForBranch(TemplateImportTreeBranch.TEAMS) as ApiTeam[] + return this.getSelectedItemsForBranch(TemplateImportTreeBranch.TEAMS) as [ApiTeam, string][] } public getAllSelectedTeamGroups(){ - return this.getSelectedItemsForBranch(TemplateImportTreeBranch.TEAM_GROUPS) as ApiTeamGroup[] + return this.getSelectedItemsForBranch(TemplateImportTreeBranch.TEAM_GROUPS) as [ApiTeamGroup,string][] } public getAllSelectedJudges(){ - return this.getSelectedItemsForBranch(TemplateImportTreeBranch.JUDGES) as ApiUser[] + return this.getSelectedItemsForBranch(TemplateImportTreeBranch.JUDGES) as [ApiUser,string][] } /** @@ -236,30 +272,30 @@ export class TemplateImportTreeComponent implements OnInit{ case TemplateImportTreeBranch.ALL: throw new Error("Cannot type set for TemplateImportTreeBanches ALL and NONE. This is a programmer's error") case TemplateImportTreeBranch.TASK_TYPES: - return items.map(it => it.item) + return items.map<[ApiTaskType, string]>(it => [it.item, it.origin]) case TemplateImportTreeBranch.TASK_GROUPS: - return items.map(it => it.item) + return items.map<[ApiTaskGroup, string]>(it => [it.item, it.origin]) case TemplateImportTreeBranch.TASK_TEMPLATES: - return items.map(it => { + return items.map<[ApiTaskTemplate, string]>(it => { /* Warning: collectionId remains and therefore must exist */ const newItem = it.item as ApiTaskTemplate; - newItem.id = undefined; - return newItem + // newItem.id = undefined; // We need the id for sanitation purposes (to resolve for the parent evaluation template */ + return [newItem, it.origin] }) case TemplateImportTreeBranch.TEAMS: - return items.map(it => { + return items.map<[ApiTeam, string]>(it => { const newItem = it.item as ApiTeam newItem.id = undefined; - return newItem + return [newItem, it.origin] }) case TemplateImportTreeBranch.TEAM_GROUPS: - return items.map(it => { + return items.map<[ApiTeamGroup, string]>(it => { const newItem = it.item as ApiTeamGroup newItem.id = undefined - return newItem + return [newItem, it.origin] }) case TemplateImportTreeBranch.JUDGES: - return items.map(it => it.item) + return items.map<[ApiUser, string]>(it => [it.item,it.origin]) } } @@ -274,24 +310,25 @@ export class TemplateImportTreeComponent implements OnInit{ root.item = template; root.label = template.name; root.children = [] as TemplateTreeNode[]; - if(this.checkForBranch(branches, TemplateImportTreeBranch.TASK_TYPES)){ + if(this.checkForBranch(branches, TemplateImportTreeBranch.TASK_TYPES) && template.taskTypes.length > 0){ root.children.push(this.buildTaskTypesBranch(template)); } - if(this.checkForBranch(branches, TemplateImportTreeBranch.TASK_GROUPS)){ + if(this.checkForBranch(branches, TemplateImportTreeBranch.TASK_GROUPS) && template.taskGroups.length > 0){ root.children.push(this.buildTaskGroupsBranch(template)); } - if(this.checkForBranch(branches, TemplateImportTreeBranch.TASK_TEMPLATES)){ + if(this.checkForBranch(branches, TemplateImportTreeBranch.TASK_TEMPLATES) && template.tasks.length > 0){ root.children.push(this.buildTaskTemplatesBranch(template)); } - if(this.checkForBranch(branches, TemplateImportTreeBranch.TEAMS)){ + if(this.checkForBranch(branches, TemplateImportTreeBranch.TEAMS) && template.teams.length > 0){ root.children.push(this.buildTeamsBranch(template)); } - if(this.checkForBranch(branches, TemplateImportTreeBranch.TEAM_GROUPS)){ + if(this.checkForBranch(branches, TemplateImportTreeBranch.TEAM_GROUPS) && template.teamGroups.length > 0){ root.children.push(this.buildTeamGroupsBranch(template)); } - if(this.checkForBranch(branches, TemplateImportTreeBranch.TEAM_GROUPS)){ + // TODO load apiusers for judges on the fly in future version + /*if(this.checkForBranch(branches, TemplateImportTreeBranch.JUDGES) && template.judges.length > 0){ root.children.push(this.buildJudgesBranch(template)); - } + } */ return root; } @@ -300,42 +337,45 @@ export class TemplateImportTreeComponent implements OnInit{ } public static buildTaskTypesBranch(template: ApiEvaluationTemplate): TemplateTreeNode { - return this.buildBranch(template, "taskTypes", "Task Types", TemplateImportTreeBranch.TASK_TYPES); + return this.buildBranch(template, "taskTypes", "Task Types", "name",TemplateImportTreeBranch.TASK_TYPES); } public static buildTaskGroupsBranch(template: ApiEvaluationTemplate): TemplateTreeNode { - return this.buildBranch(template, "taskGroups", "Task Groups", TemplateImportTreeBranch.TASK_GROUPS); + return this.buildBranch(template, "taskGroups", "Task Groups", "name",TemplateImportTreeBranch.TASK_GROUPS); } public static buildTaskTemplatesBranch(template: ApiEvaluationTemplate): TemplateTreeNode { - return this.buildBranch(template, "tasks", "Task Templates", TemplateImportTreeBranch.TASK_TEMPLATES); + return this.buildBranch(template, "tasks", "Task Templates","name", TemplateImportTreeBranch.TASK_TEMPLATES); } public static buildTeamsBranch(template: ApiEvaluationTemplate): TemplateTreeNode { - return this.buildBranch(template, "teams", "Teams", TemplateImportTreeBranch.TEAMS); + return this.buildBranch(template, "teams", "Teams","name", TemplateImportTreeBranch.TEAMS); } public static buildTeamGroupsBranch(template: ApiEvaluationTemplate): TemplateTreeNode { - return this.buildBranch(template, "teamGroups", "Team Groups", TemplateImportTreeBranch.TEAM_GROUPS); + return this.buildBranch(template, "teamGroups", "Team Groups", "name", TemplateImportTreeBranch.TEAM_GROUPS); } public static buildJudgesBranch(template: ApiEvaluationTemplate): TemplateTreeNode { - return this.buildBranch(template, "judges", "Judges", TemplateImportTreeBranch.JUDGES); + return this.buildBranch(template, "judges", "Judges", "username", TemplateImportTreeBranch.JUDGES); } - public static buildBranch(template: ApiEvaluationTemplate, key: string, rootLabel: string, branch: TemplateImportTreeBranch): TemplateTreeNode { + public static buildBranch(template: ApiEvaluationTemplate, key: string, rootLabel: string, labelKey: string, branch: TemplateImportTreeBranch): TemplateTreeNode { const root = new TemplateTreeNode(); root.label = rootLabel; root.item = template[key]; root.children = template[key].map(it => { + //console.log("THE CHILD ITEM", it) const item = new TemplateTreeNode(); - item.label = it["name"]; + item.label = it[labelKey]; item.item = it; item.children = null; item.branch = branch; item.origin = template.id + //console.log("THE CHILD", item) return item; }); + //console.log("THE Branch: ", root) return root; } diff --git a/frontend/src/app/template/template-builder/template-builder.component.ts b/frontend/src/app/template/template-builder/template-builder.component.ts index fce4e5fd3..c79739052 100644 --- a/frontend/src/app/template/template-builder/template-builder.component.ts +++ b/frontend/src/app/template/template-builder/template-builder.component.ts @@ -111,6 +111,7 @@ export class TemplateBuilderComponent extends AbstractTemplateBuilderComponent i public onImport(templateToImportFrom: ApiEvaluationTemplate){ console.log("Importing...", templateToImportFrom) + this.builderService.importFrom(templateToImportFrom); } public save(){ diff --git a/frontend/src/app/template/template-builder/template-builder.service.ts b/frontend/src/app/template/template-builder/template-builder.service.ts index 1befb5dae..acd0e153f 100644 --- a/frontend/src/app/template/template-builder/template-builder.service.ts +++ b/frontend/src/app/template/template-builder/template-builder.service.ts @@ -262,4 +262,44 @@ export class TemplateBuilderService { return result; } + importFrom(from: ApiEvaluationTemplate) { + + /* types */ + from.taskTypes.forEach(it => { + if(!this.getTemplate().taskTypes.includes(it)){ + this.getTemplate().taskTypes.push(it) + } + }) + /* task groups */ + from.taskGroups.forEach(it => { + if(!this.getTemplate().taskGroups.includes(it)){ + this.getTemplate().taskGroups.push(it) + } + }) + /* tasks */ + from.tasks.forEach(it => { + if(!this.getTemplate().tasks.includes(it)){ + this.getTemplate().tasks.push(it) + } + }) + /* teams */ + from.teams.forEach(it => { + if(!this.getTemplate().teams.includes(it)){ + this.getTemplate().teams.push(it) + } + }) + /* team groups */ + from.teamGroups.forEach(it => { + if(!this.getTemplate().teamGroups.includes(it)){ + this.getTemplate().teamGroups.push(it) + } + }) + /* judges */ + from.judges.forEach(it => { + if(!this.getTemplate().judges.includes(it)){ + this.getTemplate().judges.push(it) + } + }) + this.update(this.getTemplate()); + } }