diff --git a/angular.json b/angular.json index f2ecb001f1..c7e114b0dd 100644 --- a/angular.json +++ b/angular.json @@ -32,6 +32,7 @@ "src/manifest.webmanifest" ], "styles": [ + "@angular/material/prebuilt-themes/azure-blue.css", "src/theme.scss", "src/styles.scss", "./node_modules/bootstrap/dist/css/bootstrap.css", @@ -139,6 +140,7 @@ "tsConfig": "src/tsconfig.spec.json", "karmaConfig": "src/karma.conf.js", "styles": [ + "@angular/material/prebuilt-themes/azure-blue.css", "./node_modules/bootstrap/dist/css/bootstrap.css", "./node_modules/ngx-bootstrap/datepicker/bs-datepicker.css" ], diff --git a/package.json b/package.json index cc4a67fd36..b7b58ce083 100644 --- a/package.json +++ b/package.json @@ -165,4 +165,4 @@ "@nx/nx-linux-x64-gnu": "^18.0", "@nx/nx-win32-x64-msvc": "^18.0" } -} +} \ No newline at end of file diff --git a/src/app/admin/modals/grant-extension-form/grant-extension-dialog.component.ts b/src/app/admin/modals/grant-extension-form/grant-extension-dialog.component.ts new file mode 100644 index 0000000000..9e8ff15782 --- /dev/null +++ b/src/app/admin/modals/grant-extension-form/grant-extension-dialog.component.ts @@ -0,0 +1,27 @@ +import { Component } from '@angular/core'; +import { MatDialogRef } from '@angular/material/dialog'; +import { GrantExtensionFormComponent } from './grant-extension-form.component'; +import { MatDialogModule } from '@angular/material/dialog'; +import { CommonModule } from '@angular/common'; + +@Component({ + selector: 'f-grant-extension-dialog', + standalone: true, + imports: [MatDialogModule, CommonModule, GrantExtensionFormComponent], + template: ` +

Grant Extension

+ + + + + + + ` +}) +export class GrantExtensionDialogComponent { + constructor(private dialogRef: MatDialogRef) {} + + close(): void { + this.dialogRef.close(); + } +} diff --git a/src/app/admin/modals/grant-extension-form/grant-extension-form.component.html b/src/app/admin/modals/grant-extension-form/grant-extension-form.component.html new file mode 100644 index 0000000000..4c8ea67f29 --- /dev/null +++ b/src/app/admin/modals/grant-extension-form/grant-extension-form.component.html @@ -0,0 +1,65 @@ +

Grant Extension

+ + + + + Student + + Select a student + + {{ student.name }} + + + + Please select a student. + + + + +
+ + + + + +
+ + + + + + Reason + + + Please provide a reason for the extension. + + + + + + Additional Notes (optional) + + +
+ + + + + diff --git a/src/app/admin/modals/grant-extension-form/grant-extension-form.component.scss b/src/app/admin/modals/grant-extension-form/grant-extension-form.component.scss new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/app/admin/modals/grant-extension-form/grant-extension-form.component.spec.ts b/src/app/admin/modals/grant-extension-form/grant-extension-form.component.spec.ts new file mode 100644 index 0000000000..6d3c33c448 --- /dev/null +++ b/src/app/admin/modals/grant-extension-form/grant-extension-form.component.spec.ts @@ -0,0 +1,22 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { GrantExtensionFormComponent } from './grant-extension-form.component'; + +describe('GrantExtensionFormComponent', () => { + let component: GrantExtensionFormComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + imports: [GrantExtensionFormComponent] + }) + .compileComponents(); + + fixture = TestBed.createComponent(GrantExtensionFormComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/admin/modals/grant-extension-form/grant-extension-form.component.ts b/src/app/admin/modals/grant-extension-form/grant-extension-form.component.ts new file mode 100644 index 0000000000..b5d522908b --- /dev/null +++ b/src/app/admin/modals/grant-extension-form/grant-extension-form.component.ts @@ -0,0 +1,85 @@ +import { Component, OnInit, Inject } from '@angular/core'; +import { FormGroup, FormBuilder, Validators, ReactiveFormsModule } from '@angular/forms'; +import { CommonModule } from '@angular/common'; +import { MatFormFieldModule } from '@angular/material/form-field'; +import { MatSelectModule } from '@angular/material/select'; +import { MatInputModule } from '@angular/material/input'; +import { MatSliderModule } from '@angular/material/slider'; +import { MatButtonModule } from '@angular/material/button'; +import { MatDialogModule, MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog'; + +@Component({ + selector: 'f-grant-extension-form', + standalone: true, + imports: [ + ReactiveFormsModule, + CommonModule, + MatFormFieldModule, + MatSelectModule, + MatInputModule, + MatSliderModule, + MatButtonModule, + MatDialogModule + ], + templateUrl: './grant-extension-form.component.html', + styleUrls: ['./grant-extension-form.component.scss'] +}) +export class GrantExtensionFormComponent implements OnInit { + grantExtensionForm!: FormGroup; + isSubmitting = false; + + students = [ + { id: 1, name: 'Joe M' }, + { id: 2, name: 'Sahiru W' }, + { id: 3, name: 'Samindi M' } + ]; + + constructor( + private fb: FormBuilder, + private dialogRef: MatDialogRef, + @Inject(MAT_DIALOG_DATA) public data: { unitId: number; taskDefinitionId: number } + ) {} + + ngOnInit(): void { + this.grantExtensionForm = this.fb.group({ + student: ['', Validators.required], + extension: [1, [Validators.required, Validators.min(1)]], + reason: ['', Validators.required], + notes: [''], + }); + console.log('Received dialog data:', this.data); + } + + onSubmit(): void { + if (this.grantExtensionForm.invalid) { + this.grantExtensionForm.markAllAsTouched(); + return; + } + + this.isSubmitting = true; + + setTimeout(() => { + console.log('Form submitted:', { + ...this.grantExtensionForm.value, + unitId: this.data.unitId, + taskDefinitionId: this.data.taskDefinitionId + }); + + this.grantExtensionForm.reset({ + student: '', + extension: 1, + reason: '', + notes: '' + }); + + this.isSubmitting = false; + this.dialogRef.close(); + }, 1000); + console.log('Submitting with data:', this.data); + + + } + close(): void { + this.dialogRef.close(); + } +} diff --git a/src/app/doubtfire-angular.module.ts b/src/app/doubtfire-angular.module.ts index c714ff0e5a..d1538d5b27 100644 --- a/src/app/doubtfire-angular.module.ts +++ b/src/app/doubtfire-angular.module.ts @@ -267,6 +267,7 @@ const MY_DATE_FORMAT = { }, }; import { UnitStudentEnrolmentModalComponent } from './units/modals/unit-student-enrolment-modal/unit-student-enrolment-modal.component'; +import { provideAnimationsAsync } from '@angular/platform-browser/animations/async'; @NgModule({ // Components we declare @@ -468,6 +469,7 @@ import { UnitStudentEnrolmentModalComponent } from './units/modals/unit-student- provideLottieOptions({ player: () => player, }), + provideAnimationsAsync(), ], imports: [ FlexLayoutModule, diff --git a/src/app/doubtfire.states.ts b/src/app/doubtfire.states.ts index 7baa910f57..94334b33a0 100644 --- a/src/app/doubtfire.states.ts +++ b/src/app/doubtfire.states.ts @@ -271,6 +271,21 @@ const ProjectDashboardState: NgHybridStateDeclaration = { }, }; +const ProjectDashboardStateV1: NgHybridStateDeclaration = { + name: 'dashboard', + parent: 'projects', + url: '/dashboard', + views: { + projectView: { + component: ProjectDashboardComponent, // <-- Your new Angular Component + }, + }, + data: { + pageTitle: 'Unit Dashboard', + }, +}; + + const ViewAllUnits: NgHybridStateDeclaration = { name: 'view-all-units', url: '/view-all-units', @@ -428,6 +443,7 @@ export const doubtfireStates = [ UnauthoriedState, ProjectRootState, ProjectDashboardState, + ProjectDashboardStateV1, UnitRootState, TaskViewerState, ScormPlayerNormalState, diff --git a/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-status-card/task-status-card.component.html b/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-status-card/task-status-card.component.html index e210890833..1c78a97c34 100644 --- a/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-status-card/task-status-card.component.html +++ b/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-status-card/task-status-card.component.html @@ -1,44 +1,40 @@ @if (triggers?.length > 0) { - - - - - -

{{ task?.statusLabel() }}

-
-
- @for (trigger of triggers; track trigger) { - - -
{{ trigger.label }}
-
- } -
-
- } @if (triggers?.length < 0) { - - - -
{{ task?.statusLabel() }}
-
-
+ + + + + +

{{ task?.statusLabel() }}

+
+
+ @for (trigger of triggers; track trigger) { + + + +
{{ trigger.label }}
+
+
+ } +
+
}

{{ task?.statusHelp().reason }} {{ task?.statusHelp().action }}

- @if ( task?.unit.currentUserIsStaff || task?.canApplyForExtension() || (task?.inSubmittedState() && - task?.requiresFileUpload()) ) { @if (task?.canApplyForExtension()) { - - } @if (task?.inSubmittedState() && task?.requiresFileUpload()) { - + } + @if (task?.inSubmittedState() && task?.requiresFileUpload()) { + + } + + + - }
diff --git a/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-status-card/task-status-card.component.ts b/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-status-card/task-status-card.component.ts index d33646b066..976b4d2335 100644 --- a/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-status-card/task-status-card.component.ts +++ b/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-status-card/task-status-card.component.ts @@ -5,6 +5,9 @@ import { Task } from 'src/app/api/models/task'; import { TaskStatusEnum } from 'src/app/api/models/task-status'; import { TaskService } from 'src/app/api/services/task.service'; import { ExtensionModalService } from 'src/app/common/modals/extension-modal/extension-modal.service'; +import { MatDialog } from '@angular/material/dialog'; +import { GrantExtensionFormComponent } from 'src/app/admin/modals/grant-extension-form/grant-extension-form.component'; + @Component({ selector: 'f-task-status-card', @@ -19,6 +22,7 @@ export class TaskStatusCardComponent implements OnChanges, AfterViewInit { private extensions: ExtensionModalService, private taskService: TaskService, private router: UIRouter, + private dialog: MatDialog, ) {} @Input() task: Task; @@ -66,4 +70,19 @@ export class TaskStatusCardComponent implements OnChanges, AfterViewInit { this.task.refresh(); }); } + + openGrantExtensionDialog(): void { + this.dialog.open(GrantExtensionFormComponent, { + width: '100%', + maxWidth: '600px', + disableClose: true, + data: { + unitId: this.task.unit.id, + taskDefinitionId: this.task.definition.id + } + }); + + console.log('TASK:', this.task); + } + } diff --git a/src/app/projects/states/dashboard/project-dashboard/project-dashboard.component.ts b/src/app/projects/states/dashboard/project-dashboard/project-dashboard.component.ts index ac792b582e..b9230045f9 100644 --- a/src/app/projects/states/dashboard/project-dashboard/project-dashboard.component.ts +++ b/src/app/projects/states/dashboard/project-dashboard/project-dashboard.component.ts @@ -15,7 +15,7 @@ import {ProjectService} from 'src/app/api/services/project.service'; import {GlobalStateService} from '../../index/global-state.service'; import {UserService} from 'src/app/api/services/user.service'; import {Project, TaskDefinition} from 'src/app/api/models/doubtfire-model'; - +import { MatDialog } from '@angular/material/dialog'; @Component({ selector: 'f-project-dashboard', templateUrl: './project-dashboard.component.html', @@ -43,6 +43,7 @@ export class ProjectDashboardComponent implements OnInit { private currentUser: UserService, private projectService: ProjectService, private globalStateService: GlobalStateService, + private dialog: MatDialog, ) {} startedDragging(event: CdkDragStart, div: HTMLDivElement) { diff --git a/src/styles.scss b/src/styles.scss index 0df654e6ba..54ee9aadf2 100644 --- a/src/styles.scss +++ b/src/styles.scss @@ -64,3 +64,6 @@ $main-view-max-height: calc((var(--vh, 1vh) * (100)) - 85px); } } + +html, body { height: 100%; } +body { margin: 0; font-family: Roboto, "Helvetica Neue", sans-serif; }