diff --git a/src/assets/wise5/classroomMonitor/dataExport/export-events/export-events.component.spec.ts b/src/assets/wise5/classroomMonitor/dataExport/export-events/export-events.component.spec.ts index 3313c3404e3..0264a1f3a77 100644 --- a/src/assets/wise5/classroomMonitor/dataExport/export-events/export-events.component.spec.ts +++ b/src/assets/wise5/classroomMonitor/dataExport/export-events/export-events.component.spec.ts @@ -11,7 +11,13 @@ import { FormsModule } from '@angular/forms'; let configService: ConfigService; let teacherProjectService: TeacherProjectService; - +const group0 = { + id: 'group0', + type: 'group', + title: 'Master', + startId: '', + ids: [] +}; describe('ExportEventsComponent', () => { let component: ExportEventsComponent; let fixture: ComponentFixture; @@ -31,13 +37,17 @@ describe('ExportEventsComponent', () => { teacherProjectService = TestBed.inject(TeacherProjectService); spyOn(teacherProjectService, 'getNodeOrderOfProject').and.returnValue({ idToOrder: {}, - nodes: [] + nodes: [group0] }); teacherProjectService.project = { metadata: { title: 'Test Project' - } + }, + startGroupId: 'group0', + startNodeId: 'group0', + nodes: [group0] }; + teacherProjectService.idToNode['group0'] = group0; configService = TestBed.inject(ConfigService); spyOn(configService, 'getPermissions').and.returnValue({ canGradeStudentWork: true, diff --git a/src/assets/wise5/classroomMonitor/dataExport/export-one-workgroup-per-row/export-one-workgroup-per-row.component.spec.ts b/src/assets/wise5/classroomMonitor/dataExport/export-one-workgroup-per-row/export-one-workgroup-per-row.component.spec.ts index cfa57bdbbcf..da8d288965c 100644 --- a/src/assets/wise5/classroomMonitor/dataExport/export-one-workgroup-per-row/export-one-workgroup-per-row.component.spec.ts +++ b/src/assets/wise5/classroomMonitor/dataExport/export-one-workgroup-per-row/export-one-workgroup-per-row.component.spec.ts @@ -13,21 +13,33 @@ import { provideHttpClient, withInterceptorsFromDi } from '@angular/common/http' let configService: ConfigService; let teacherProjectService: TeacherProjectService; - +const group0 = { + id: 'group0', + type: 'group', + title: 'Master', + startId: '', + ids: [] +}; describe('ExportOneWorkgroupPerRowComponent', () => { let component: ExportOneWorkgroupPerRowComponent; let fixture: ComponentFixture; beforeEach(() => { TestBed.configureTestingModule({ - declarations: [ExportOneWorkgroupPerRowComponent], - imports: [ClassroomMonitorTestingModule, + declarations: [ExportOneWorkgroupPerRowComponent], + imports: [ + ClassroomMonitorTestingModule, DataExportModule, MatCheckboxModule, MatIconModule, - RouterTestingModule], - providers: [DataExportService, provideHttpClient(withInterceptorsFromDi()), provideHttpClientTesting()] -}); + RouterTestingModule + ], + providers: [ + DataExportService, + provideHttpClient(withInterceptorsFromDi()), + provideHttpClientTesting() + ] + }); fixture = TestBed.createComponent(ExportOneWorkgroupPerRowComponent); component = fixture.componentInstance; configService = TestBed.inject(ConfigService); @@ -39,15 +51,18 @@ describe('ExportOneWorkgroupPerRowComponent', () => { teacherProjectService = TestBed.inject(TeacherProjectService); spyOn(teacherProjectService, 'getNodeOrderOfProject').and.returnValue({ idToOrder: {}, - nodes: [] + nodes: [group0] }); teacherProjectService.project = { - nodes: [], inactiveNodes: [], metadata: { title: 'Test Project' - } + }, + startGroupId: 'group0', + startNodeId: 'group0', + nodes: [group0] }; + teacherProjectService.idToNode['group0'] = group0; fixture.detectChanges(); }); diff --git a/src/assets/wise5/classroomMonitor/dataExport/export-raw-data/export-raw-data.component.spec.ts b/src/assets/wise5/classroomMonitor/dataExport/export-raw-data/export-raw-data.component.spec.ts index 92559495130..850e6a62b2f 100644 --- a/src/assets/wise5/classroomMonitor/dataExport/export-raw-data/export-raw-data.component.spec.ts +++ b/src/assets/wise5/classroomMonitor/dataExport/export-raw-data/export-raw-data.component.spec.ts @@ -13,7 +13,13 @@ import { ConfigService } from '../../../services/configService'; let configService: ConfigService; let teacherProjectService: TeacherProjectService; - +const group0 = { + id: 'group0', + type: 'group', + title: 'Master', + startId: '', + ids: [] +}; describe('ExportRawDataComponent', () => { let component: ExportRawDataComponent; let fixture: ComponentFixture; @@ -39,13 +45,17 @@ describe('ExportRawDataComponent', () => { teacherProjectService = TestBed.inject(TeacherProjectService); spyOn(teacherProjectService, 'getNodeOrderOfProject').and.returnValue({ idToOrder: {}, - nodes: [] + nodes: [group0] }); teacherProjectService.project = { metadata: { title: 'Test Project' - } + }, + startGroupId: 'group0', + startNodeId: 'group0', + nodes: [group0] }; + teacherProjectService.idToNode['group0'] = group0; configService = TestBed.inject(ConfigService); spyOn(configService, 'getPermissions').and.returnValue({ canGradeStudentWork: true, diff --git a/src/assets/wise5/classroomMonitor/dataExport/export-student-work/export-student-work.component.spec.ts b/src/assets/wise5/classroomMonitor/dataExport/export-student-work/export-student-work.component.spec.ts index 8aeb1404093..c079ee29637 100644 --- a/src/assets/wise5/classroomMonitor/dataExport/export-student-work/export-student-work.component.spec.ts +++ b/src/assets/wise5/classroomMonitor/dataExport/export-student-work/export-student-work.component.spec.ts @@ -9,7 +9,13 @@ import { ConfigService } from '../../../services/configService'; let configService: ConfigService; let teacherProjectService: TeacherProjectService; - +const group0 = { + id: 'group0', + type: 'group', + title: 'Master', + startId: '', + ids: [] +}; describe('ExportStudentWorkComponent', () => { let component: ExportStudentWorkComponent; let fixture: ComponentFixture; @@ -32,15 +38,18 @@ describe('ExportStudentWorkComponent', () => { teacherProjectService = TestBed.inject(TeacherProjectService); spyOn(teacherProjectService, 'getNodeOrderOfProject').and.returnValue({ idToOrder: {}, - nodes: [] + nodes: [group0] }); teacherProjectService.project = { - nodes: [], inactiveNodes: [], metadata: { title: 'Test Project' - } + }, + startGroupId: 'group0', + startNodeId: 'group0', + nodes: [group0] }; + teacherProjectService.idToNode['group0'] = group0; fixture.detectChanges(); }); diff --git a/src/assets/wise5/services/projectService.ts b/src/assets/wise5/services/projectService.ts index 456694d657e..9e232d399b5 100644 --- a/src/assets/wise5/services/projectService.ts +++ b/src/assets/wise5/services/projectService.ts @@ -854,230 +854,224 @@ export class ProjectService { getAllPaths(pathSoFar: string[], nodeId: string = '', includeGroups: boolean = false): any[][] { const allPaths = []; if (this.isApplicationNode(nodeId)) { - const path = []; - const transitions = this.getTransitionsByFromNodeId(nodeId); - if (includeGroups) { - const parentGroup = this.getParentGroup(nodeId); - if (parentGroup != null) { - const parentGroupId = parentGroup.id; - if (parentGroupId != null && pathSoFar.indexOf(parentGroupId) == -1) { - pathSoFar.push(parentGroup.id); - } + this.getStepPaths(pathSoFar, nodeId, includeGroups, allPaths); + } else { + this.getLessonPaths(pathSoFar, nodeId, includeGroups, allPaths); + } + return allPaths; + } + + private getStepPaths( + pathSoFar: string[], + nodeId: string, + includeGroups: boolean, + allPaths: any[] + ): void { + const path = []; + const transitions = this.getTransitionsByFromNodeId(nodeId); + if (includeGroups) { + const parentGroup = this.getParentGroup(nodeId); + if (parentGroup != null) { + const parentGroupId = parentGroup.id; + if (parentGroupId != null && pathSoFar.indexOf(parentGroupId) == -1) { + pathSoFar.push(parentGroup.id); } } + } + + /* + * add the node id to the path so far so we can later check + * which nodes are already in the path to prevent looping + * back in the path + */ + pathSoFar.push(nodeId); + if (transitions.length === 0) { /* - * add the node id to the path so far so we can later check - * which nodes are already in the path to prevent looping - * back in the path + * there are no transitions from the node id so we will + * look for a transition in the parent group */ - pathSoFar.push(nodeId); - - if (transitions.length === 0) { - /* - * there are no transitions from the node id so we will - * look for a transition in the parent group - */ - - let addedCurrentNodeId = false; - const parentGroupId = this.getParentGroupId(nodeId); - const parentGroupTransitions = this.getTransitionsByFromNodeId(parentGroupId); - for (const parentGroupTransition of parentGroupTransitions) { - if (parentGroupTransition != null) { - const toNodeId = parentGroupTransition.to; - if (pathSoFar.indexOf(toNodeId) == -1) { - /* - * recursively get the paths by getting all - * the paths for the to node - */ - const allPathsFromToNode = this.getAllPaths(pathSoFar, toNodeId, includeGroups); + let addedCurrentNodeId = false; + const parentGroupId = this.getParentGroupId(nodeId); + const parentGroupTransitions = this.getTransitionsByFromNodeId(parentGroupId); + for (const parentGroupTransition of parentGroupTransitions) { + if (parentGroupTransition != null) { + const toNodeId = parentGroupTransition.to; + if (pathSoFar.indexOf(toNodeId) == -1) { + /* + * recursively get the paths by getting all + * the paths for the to node + */ + const allPathsFromToNode = this.getAllPaths(pathSoFar, toNodeId, includeGroups); - for (let tempPath of allPathsFromToNode) { - tempPath.unshift(nodeId); - allPaths.push(tempPath); - addedCurrentNodeId = true; - } + for (let tempPath of allPathsFromToNode) { + tempPath.unshift(nodeId); + allPaths.push(tempPath); + addedCurrentNodeId = true; } } } + } - if (!addedCurrentNodeId) { - /* - * if the parent group doesn't have any transitions we will - * need to add the current node id to the path - */ - path.push(nodeId); - allPaths.push(path); - } - } else { - // there are transitions from this node id - - for (let transition of transitions) { - if (transition != null) { - const toNodeId = transition.to; - if (toNodeId != null && pathSoFar.indexOf(toNodeId) == -1) { - // we have not found the to node in the path yet so we can traverse it - - /* - * recursively get the paths by getting all - * the paths from the to node - */ - const allPathsFromToNode = this.getAllPaths(pathSoFar, toNodeId, includeGroups); - - if (allPathsFromToNode != null) { - for (let tempPath of allPathsFromToNode) { - if (includeGroups) { - // we need to add the group id to the path - - if (tempPath.length > 0) { - const firstNodeId = tempPath[0]; - const firstParentGroupId = this.getParentGroupId(firstNodeId); - const parentGroupId = this.getParentGroupId(nodeId); - if (parentGroupId != firstParentGroupId) { - /* - * the parent ids are different which means this is a boundary - * between two groups. for example if the project looked like - * group1>node1>node2>group2>node3>node4 - * and the current node was node2 then the first node in the - * path would be node3 which means we would need to place - * group2 on the path before node3 - */ - tempPath.unshift(firstParentGroupId); - } + if (!addedCurrentNodeId) { + /* + * if the parent group doesn't have any transitions we will + * need to add the current node id to the path + */ + path.push(nodeId); + allPaths.push(path); + } + } else { + // there are transitions from this node id + for (let transition of transitions) { + if (transition != null) { + const toNodeId = transition.to; + if (toNodeId != null && pathSoFar.indexOf(toNodeId) == -1) { + // we have not found the to node in the path yet so we can traverse it + /* + * recursively get the paths by getting all + * the paths from the to node + */ + const allPathsFromToNode = this.getAllPaths(pathSoFar, toNodeId, includeGroups); + + if (allPathsFromToNode != null) { + for (let tempPath of allPathsFromToNode) { + if (includeGroups) { + // we need to add the group id to the path + if (tempPath.length > 0) { + const firstNodeId = tempPath[0]; + const firstParentGroupId = this.getParentGroupId(firstNodeId); + const parentGroupId = this.getParentGroupId(nodeId); + if (parentGroupId != firstParentGroupId) { + /* + * the parent ids are different which means this is a boundary + * between two groups. for example if the project looked like + * group1>node1>node2>group2>node3>node4 + * and the current node was node2 then the first node in the + * path would be node3 which means we would need to place + * group2 on the path before node3 + */ + tempPath.unshift(firstParentGroupId); } } - - tempPath.unshift(nodeId); - allPaths.push(tempPath); } + + tempPath.unshift(nodeId); + allPaths.push(tempPath); } - } else { - /* - * the node is already in the path so far which means - * the transition is looping back to a previous node. - * we do not want to take this transition because - * it will lead to an infinite loop. we will just - * add the current node id to the path and not take - * the transition which essentially ends the path. - */ - path.push(nodeId); - allPaths.push(path); } + } else { + /* + * the node is already in the path so far which means + * the transition is looping back to a previous node. + * we do not want to take this transition because + * it will lead to an infinite loop. we will just + * add the current node id to the path and not take + * the transition which essentially ends the path. + */ + path.push(nodeId); + allPaths.push(path); } } } + } - if (pathSoFar.length > 0) { - const lastNodeId = pathSoFar[pathSoFar.length - 1]; - if (this.isGroupNode(lastNodeId)) { - /* - * the last node id is a group id so we will remove it - * since we are moving back up the path as we traverse - * the nodes depth first - */ - pathSoFar.pop(); - } + if (pathSoFar.length > 0) { + const lastNodeId = pathSoFar[pathSoFar.length - 1]; + if (this.isGroupNode(lastNodeId)) { + /* + * the last node id is a group id so we will remove it + * since we are moving back up the path as we traverse + * the nodes depth first + */ + pathSoFar.pop(); } + } - /* - * remove the latest node id (this will be a step node id) - * since we are moving back up the path as we traverse the - * nodes depth first - */ - pathSoFar.pop(); - - if (includeGroups) { - if (pathSoFar.length == 1) { - /* - * we are including groups and we have traversed - * back up to the start node id for the project. - * the only node id left in pathSoFar is now the - * parent group of the start node id. we will - * now add this parent group of the start node id - * to all of the paths - */ - - for (let path of allPaths) { - if (path != null) { - /* - * prepend the parent group of the start node id - * to the path - */ - path.unshift(pathSoFar[0]); - } - } + /* + * remove the latest node id (this will be a step node id) + * since we are moving back up the path as we traverse the + * nodes depth first + */ + pathSoFar.pop(); - /* - * remove the parent group of the start node id from - * pathSoFar which leaves us with an empty pathSoFar - * which means we are completely done with - * calculating all the paths - */ - pathSoFar.pop(); - } - } - } else { - /* - * add the node id to the path so far so we can later check - * which nodes are already in the path to prevent looping - * back in the path - */ - pathSoFar.push(nodeId); - - const groupNode = this.getNodeById(nodeId); - if (groupNode != null) { - const startId = groupNode.startId; - if (startId == null || startId == '') { - // there is no start id so we will take the transition from the group - // TODO? there is no start id so we will loop through all the child nodes - - const transitions = this.getTransitionsByFromNodeId(groupNode.id); - if (transitions.length > 0) { - for (let transition of transitions) { - if (transition != null) { - const toNodeId = transition.to; - - const allPathsFromToNode = this.getAllPaths(pathSoFar, toNodeId, includeGroups); - - if (allPathsFromToNode != null) { - for (let tempPath of allPathsFromToNode) { - tempPath.unshift(nodeId); - allPaths.push(tempPath); - } - } - } - } - } else { + if (includeGroups) { + if (pathSoFar.length == 1) { + /* + * we are including groups and we have traversed + * back up to the start node id for the project. + * the only node id left in pathSoFar is now the + * parent group of the start node id. we will + * now add this parent group of the start node id + * to all of the paths + */ + for (let path of allPaths) { + if (path != null) { /* - * this activity does not have any transitions so - * we have reached the end of this path + * prepend the parent group of the start node id + * to the path */ - - const tempPath = []; - tempPath.unshift(nodeId); - allPaths.push(tempPath); + path.unshift(pathSoFar[0]); } - } else { - // there is a start id so we will traverse it + } - const allPathsFromToNode = this.getAllPaths(pathSoFar, startId, includeGroups); + /* + * remove the parent group of the start node id from + * pathSoFar which leaves us with an empty pathSoFar + * which means we are completely done with + * calculating all the paths + */ + pathSoFar.pop(); + } + } + } - if (allPathsFromToNode != null) { - for (let tempPath of allPathsFromToNode) { - tempPath.unshift(nodeId); - allPaths.push(tempPath); - } + private getLessonPaths( + pathSoFar: string[], + groupId: string, + includeGroups: boolean, + allPaths: any[] + ): void { + /* + * add the node id to the path so far so we can later check + * which nodes are already in the path to prevent looping + * back in the path + */ + pathSoFar.push(groupId); + + const groupNode = this.getNodeById(groupId); + const startId = groupNode.startId; + if (startId == null || startId == '') { + // there is no start id (e.g., this is an empty lesson) + // so we will take the transition from the group + // TODO? there is no start id so we will loop through all the child nodes + const transitions = this.getTransitionsByFromNodeId(groupNode.id); + if (transitions.length > 0) { + for (const transition of transitions) { + const allPathsFromToNode = this.getAllPaths(pathSoFar, transition.to, includeGroups); + for (const tempPath of allPathsFromToNode) { + tempPath.unshift(groupId); + allPaths.push(tempPath); } } + } else { + // this activity does not have any transitions so we have reached the end of this path + allPaths.push([groupId]); + } + } else { + // there is a start id so we will traverse it + const allPathsFromToNode = this.getAllPaths(pathSoFar, startId, includeGroups); + for (const tempPath of allPathsFromToNode) { + tempPath.unshift(groupId); + allPaths.push(tempPath); } - - /* - * remove the latest node id since we are moving back - * up the path as we traverse the nodes depth first - */ - pathSoFar.pop(); } - return allPaths; + + /* + * remove the latest node id since we are moving back + * up the path as we traverse the nodes depth first + */ + pathSoFar.pop(); } getStepNodeIds(): string[] {