Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
1 change: 0 additions & 1 deletion src/app/doubtfire-angularjs.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,6 @@ import 'build/src/app/units/states/edit/directives/unit-details-editor/unit-deta
import 'build/src/app/units/states/edit/directives/unit-ilo-editor/unit-ilo-editor.js';
import 'build/src/app/units/states/edit/directives/directives.js';
import 'build/src/app/units/states/edit/edit.js';
import 'build/src/app/units/states/index/index.js';
import 'build/src/app/units/states/students-list/students-list.js';
import 'build/src/app/units/states/analytics/analytics.js';
import 'build/src/app/common/filters/filters.js';
Expand Down
50 changes: 0 additions & 50 deletions src/app/units/states/index/index.coffee

This file was deleted.

7 changes: 0 additions & 7 deletions src/app/units/states/index/index.tpl.html

This file was deleted.

1 change: 0 additions & 1 deletion src/app/units/states/states.coffee
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
angular.module('doubtfire.units.states', [
# 'doubtfire.units.states.all'
'doubtfire.units.states.index'
'doubtfire.units.states.edit'
'doubtfire.units.states.tasks'
'doubtfire.units.states.groups'
Expand Down
2 changes: 1 addition & 1 deletion src/app/units/task-viewer/task-viewer-state.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ export class TaskViewerStateComponent {
export const TaskViewerState: NgHybridStateDeclaration = {
name: 'units2/tasks',
url: '/tasks/:taskDefId',
parent: 'unit-root-state',
parent: 'units/index',
data: {
pageTitle: 'Unit Tasks',
roleWhitelist: ['Tutor', 'Convenor', 'Admin', 'Auditor'],
Expand Down
9 changes: 8 additions & 1 deletion src/app/units/unit-root-state.component.html
Original file line number Diff line number Diff line change
@@ -1 +1,8 @@
<div ui-view="unitView"></div>
<div *ngIf="!(unit$ | async) || !(unitRole$ | async)" class="large-notice-block">
<i class="fa fa-2x fa-spinner fa-pulse"></i>
<p>Loading unit details...</p>
</div>

<div *ngIf="(unit$ | async) && (unitRole$ | async)">
<ui-view></ui-view>
</div>
143 changes: 92 additions & 51 deletions src/app/units/unit-root-state.component.ts
Original file line number Diff line number Diff line change
@@ -1,90 +1,131 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
import {CdkDragEnd, CdkDragMove, CdkDragStart} from '@angular/cdk/drag-drop';
import {Component, Input, OnInit} from '@angular/core';
import {
BehaviorSubject,
Observable,
Subject,
auditTime,
first,
merge,
of,
tap,
withLatestFrom,
} from 'rxjs';
import {Unit, UnitService, UserService} from 'src/app/api/models/doubtfire-model';
import { AppInjector } from '../app-injector';
import { NgHybridStateDeclaration } from '@uirouter/angular-hybrid';
import { GlobalStateService, ViewType } from '../projects/states/index/global-state.service';
import { StateService } from '@uirouter/core';
import { AlertService } from '../common/services/alert.service';
import {Component, Input, OnInit, OnDestroy} from '@angular/core';
import {Observable, Subscription} from 'rxjs';
import {Unit, UnitRole} from 'src/app/api/models/doubtfire-model';
import {AppInjector} from '../app-injector';
import {NgHybridStateDeclaration} from '@uirouter/angular-hybrid';
import {Ng2ViewDeclaration} from '@uirouter/angular';
import {GlobalStateService, ViewType} from '../projects/states/index/global-state.service';
import {StateService} from '@uirouter/core';
import {AlertService} from '../common/services/alert.service';
import {UnitService} from '../api/services/unit.service';
import {UserService} from '../api/services/user.service';
import {first} from 'rxjs/operators';

@Component({
selector: 'f-unit-root-state',
templateUrl: './unit-root-state.component.html',
styleUrl: './unit-root-state.component.css',
})
export class UnitRootStateComponent {
export class UnitRootStateComponent implements OnInit, OnDestroy {
@Input() public unit$: Observable<Unit>;
@Input() public unitRole$: Observable<UnitRole>;

public unit: Unit;
public unitRole: UnitRole;

private subscriptions: Subscription[] = [];

ngOnInit(): void {
// Subscribe to observables and store values for Angular template
if (this.unit$) {
const unitSub = this.unit$.subscribe((unit) => {
this.unit = unit;
});
this.subscriptions.push(unitSub);
}

if (this.unitRole$) {
const roleSub = this.unitRole$.subscribe((unitRole) => {
this.unitRole = unitRole;
});
this.subscriptions.push(roleSub);
}
}

ngOnDestroy(): void {
// Clean up subscriptions
this.subscriptions.forEach(sub => sub.unsubscribe());
}
}

export const UnitRootState: NgHybridStateDeclaration = {
name: 'unit-root-state',
url: '/units2/:unitId',
name: 'units/index',
url: '/units/:unitId',
abstract: true,
data: {
pageTitle: 'Unit Root State',
pageTitle: '_Home_',
roleWhitelist: ['Tutor', 'Convenor', 'Admin', 'Auditor'],
},
views: {
main: {
component: UnitRootStateComponent,
},
controller: function($scope, unit$, unitRole$) {
// Set observables on $scope for template binding to Angular component
$scope.unit$ = unit$;
$scope.unitRole$ = unitRole$;

// Subscribe and set values on $scope for AngularJS child states
unit$.subscribe((unit) => {
$scope.unit = unit;
});
unitRole$.subscribe((unitRole) => {
$scope.unitRole = unitRole;
});
},
template: '<f-unit-root-state [unit$]="unit$" [unitRole$]="unitRole$"></f-unit-root-state>',
} as unknown as Ng2ViewDeclaration,
},

resolve: {
unit$: function ($stateParams) {
const unitService = AppInjector.get(UnitService);
const stateService = AppInjector.get(StateService);
const alertService = AppInjector.get(AlertService);

const unitId = parseInt($stateParams.unitId);
if (!unitId) {
stateService.go('home');
return;
}

return unitService.get(unitId).pipe(
first()
);
},
unitRole$: function ($stateParams, unit$) {
const globalState = AppInjector.get(GlobalStateService);
const userService = AppInjector.get(UserService);
const stateService = AppInjector.get(StateService);
const alertService = AppInjector.get(AlertService);

return new Observable<Unit>((observer) => {
return new Observable<UnitRole>((observer) => {
globalState.onLoad(() => {
const unitId: number = parseInt($stateParams.unitId);
let unitRole = globalState.loadedUnitRoles.currentValues.find(
(unitRole) => unitRole.unit.id === unitId,
const unitId = parseInt($stateParams.unitId);

let role = globalState.loadedUnitRoles.currentValues.find(
(ur) => ur.unit.id === unitId
);

if (
!unitRole &&
(userService.currentUser.role == 'Admin' || userService.currentUser.role == 'Auditor')
) {
unitRole = userService.adminOrAuditorRoleFor(
if (!role && (userService.currentUser.role === 'Admin' || userService.currentUser.role === 'Auditor')) {
role = userService.adminOrAuditorRoleFor(
userService.currentUser.role,
unitId,
userService.currentUser,
userService.currentUser
);
}

// Go home if no unit role was found
if (!unitRole) {
console.log('No unit role found for unit', unitId);
return stateService.go('home');
if (!role) {
alertService.error('You do not have access to this unit', 6000);
stateService.go('home');
observer.complete();
return;
}

unitService.get(unitId).subscribe({
next: (unit: Unit) => {
observer.next(unit);
globalState.setView(ViewType.UNIT, unitRole);
observer.complete();
},
error: (err) => {
AppInjector.get(AlertService).error('Error loading unit: ' + err, 8000);
setTimeout(() => stateService.go('home'), 5000);
}
});
globalState.setView(ViewType.UNIT, role);
observer.next(role);
observer.complete();
});
}).pipe(first());
},
},
};
};