From 12262559f32cd5c969755efe7075ef52397282b0 Mon Sep 17 00:00:00 2001 From: Diego Guerrero Date: Sun, 9 Jun 2024 11:25:39 +0200 Subject: [PATCH] Adds warning in browsers without File System Access API In case any user logs in to the VSCode4Teaching web application in a browser that does not support the File System Access API (such as, for example, Firefox currently), a warning will be displayed recommending to change browser, as most of the functionality of this application will be inoperative. --- .../src/app/app.component.html | 1 + vscode4teaching-webapp/src/app/app.module.ts | 2 ++ ...rted-file-system-access-api.component.html | 10 ++++++ ...rted-file-system-access-api.component.scss | 0 ...d-file-system-access-api.component.spec.ts | 21 ++++++++++++ ...ported-file-system-access-api.component.ts | 33 +++++++++++++++++++ .../common/dashboard/dashboard.component.html | 2 +- .../common/dashboard/dashboard.component.ts | 5 ++- .../auto-sync-server.component.ts | 3 +- .../course/student-course.component.html | 4 +-- .../course/student-course.component.ts | 3 +- .../students-progress.component.html | 9 +++-- .../students-progress.component.ts | 4 +++ .../file-system-read-directory.service.ts | 7 +--- vscode4teaching-webapp/src/styles.scss | 10 ++++++ 15 files changed, 100 insertions(+), 14 deletions(-) create mode 100644 vscode4teaching-webapp/src/app/components/helpers/not-supported-file-system-access-api/not-supported-file-system-access-api.component.html create mode 100644 vscode4teaching-webapp/src/app/components/helpers/not-supported-file-system-access-api/not-supported-file-system-access-api.component.scss create mode 100644 vscode4teaching-webapp/src/app/components/helpers/not-supported-file-system-access-api/not-supported-file-system-access-api.component.spec.ts create mode 100644 vscode4teaching-webapp/src/app/components/helpers/not-supported-file-system-access-api/not-supported-file-system-access-api.component.ts diff --git a/vscode4teaching-webapp/src/app/app.component.html b/vscode4teaching-webapp/src/app/app.component.html index 3f5e2eff..7d8bfe95 100644 --- a/vscode4teaching-webapp/src/app/app.component.html +++ b/vscode4teaching-webapp/src/app/app.component.html @@ -7,6 +7,7 @@
+
diff --git a/vscode4teaching-webapp/src/app/app.module.ts b/vscode4teaching-webapp/src/app/app.module.ts index dea8952c..c272c7dd 100644 --- a/vscode4teaching-webapp/src/app/app.module.ts +++ b/vscode4teaching-webapp/src/app/app.module.ts @@ -32,6 +32,7 @@ import { HttpRequestInterceptor } from "./services/rest-api/interceptor/http-req import { UrlService } from "./services/url/url.service"; import { WebSocketHandler } from "./services/ws/web-socket-handler"; import { WebSocketHandlerFactory } from "./services/ws/web-socket-handler-factory.service"; +import { NotSupportedFileSystemAccessApiComponent } from './components/helpers/not-supported-file-system-access-api/not-supported-file-system-access-api.component'; @NgModule({ declarations: [ @@ -42,6 +43,7 @@ import { WebSocketHandlerFactory } from "./services/ws/web-socket-handler-factor // helpers ProgressBarComponent, + NotSupportedFileSystemAccessApiComponent, DelaySinceComponent, // public diff --git a/vscode4teaching-webapp/src/app/components/helpers/not-supported-file-system-access-api/not-supported-file-system-access-api.component.html b/vscode4teaching-webapp/src/app/components/helpers/not-supported-file-system-access-api/not-supported-file-system-access-api.component.html new file mode 100644 index 00000000..5537ede8 --- /dev/null +++ b/vscode4teaching-webapp/src/app/components/helpers/not-supported-file-system-access-api/not-supported-file-system-access-api.component.html @@ -0,0 +1,10 @@ +
+
+
+
+  Attention! This web browser does not support interaction with your computer files and folders, so you will not be able to use features like exercise download or automatic file synchronization. +
If you want to use these features, please use a compatible browser like most recent versions of Google Chrome or Microsoft Edge. Check out compatibility in this link. +
+
+
+
diff --git a/vscode4teaching-webapp/src/app/components/helpers/not-supported-file-system-access-api/not-supported-file-system-access-api.component.scss b/vscode4teaching-webapp/src/app/components/helpers/not-supported-file-system-access-api/not-supported-file-system-access-api.component.scss new file mode 100644 index 00000000..e69de29b diff --git a/vscode4teaching-webapp/src/app/components/helpers/not-supported-file-system-access-api/not-supported-file-system-access-api.component.spec.ts b/vscode4teaching-webapp/src/app/components/helpers/not-supported-file-system-access-api/not-supported-file-system-access-api.component.spec.ts new file mode 100644 index 00000000..689f5c9e --- /dev/null +++ b/vscode4teaching-webapp/src/app/components/helpers/not-supported-file-system-access-api/not-supported-file-system-access-api.component.spec.ts @@ -0,0 +1,21 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { NotSupportedFileSystemAccessApiComponent } from './not-supported-file-system-access-api.component'; + +describe('NotSupportedFileSystemAccessApiComponent', () => { + let component: NotSupportedFileSystemAccessApiComponent; + let fixture: ComponentFixture; + + beforeEach(() => { + TestBed.configureTestingModule({ + declarations: [NotSupportedFileSystemAccessApiComponent] + }); + fixture = TestBed.createComponent(NotSupportedFileSystemAccessApiComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/vscode4teaching-webapp/src/app/components/helpers/not-supported-file-system-access-api/not-supported-file-system-access-api.component.ts b/vscode4teaching-webapp/src/app/components/helpers/not-supported-file-system-access-api/not-supported-file-system-access-api.component.ts new file mode 100644 index 00000000..6a95a169 --- /dev/null +++ b/vscode4teaching-webapp/src/app/components/helpers/not-supported-file-system-access-api/not-supported-file-system-access-api.component.ts @@ -0,0 +1,33 @@ +import { Component, OnDestroy, OnInit } from '@angular/core'; +import { Event, NavigationStart, Router } from "@angular/router"; +import { supported as fileSystemAccessApiSupported } from "browser-fs-access"; +import { Subscription } from "rxjs"; +import { CurrentUserService } from "../../../services/auth/current-user/current-user.service"; + +@Component({ + selector: 'app-not-supported-file-system-access-api', + templateUrl: './not-supported-file-system-access-api.component.html', + styleUrls: ['./not-supported-file-system-access-api.component.scss'] +}) +export class NotSupportedFileSystemAccessApiComponent implements OnInit, OnDestroy { + public showFsaAPINotSupportedMessage: boolean; + public routerSubscription?: Subscription; + + constructor(private curUser: CurrentUserService, private router: Router) { + this.showFsaAPINotSupportedMessage = false; + } + + async ngOnInit(): Promise { + this.routerSubscription = this.router.events.subscribe({ + next: async (event: Event) => { + if (event instanceof NavigationStart) { + this.showFsaAPINotSupportedMessage = !fileSystemAccessApiSupported && (await this.curUser.currentUser) !== undefined + } + } + }); + } + + ngOnDestroy(): void { + this.routerSubscription?.unsubscribe(); + } +} diff --git a/vscode4teaching-webapp/src/app/components/private/common/dashboard/dashboard.component.html b/vscode4teaching-webapp/src/app/components/private/common/dashboard/dashboard.component.html index 18d7823b..8fe61c27 100644 --- a/vscode4teaching-webapp/src/app/components/private/common/dashboard/dashboard.component.html +++ b/vscode4teaching-webapp/src/app/components/private/common/dashboard/dashboard.component.html @@ -21,7 +21,7 @@

My Courses

{{ course.name }}
- + Exercises diff --git a/vscode4teaching-webapp/src/app/components/private/common/dashboard/dashboard.component.ts b/vscode4teaching-webapp/src/app/components/private/common/dashboard/dashboard.component.ts index 82c450e2..d0f119d4 100644 --- a/vscode4teaching-webapp/src/app/components/private/common/dashboard/dashboard.component.ts +++ b/vscode4teaching-webapp/src/app/components/private/common/dashboard/dashboard.component.ts @@ -3,7 +3,7 @@ import { CourseService } from "../../../../services/rest-api/model-entities/cour import { CurrentUserService } from "../../../../services/auth/current-user/current-user.service"; import { Course } from "../../../../model/course.model"; import { User } from "../../../../model/user.model"; -import { Router } from "@angular/router"; +import { supported as fileSystemAccessApiSupported } from "browser-fs-access"; import { AsideService } from "../../../../services/aside/aside.service"; @Component({ @@ -17,10 +17,13 @@ export class DashboardComponent implements OnInit { coursesLoaded: boolean; + fsaApiSupported: boolean; + constructor(private asideService: AsideService, private courseService: CourseService, private curUserService: CurrentUserService) { this.coursesLoaded = false; + this.fsaApiSupported = fileSystemAccessApiSupported; } async ngOnInit(): Promise { diff --git a/vscode4teaching-webapp/src/app/components/private/student/course/exercise-status/in-progress-exercise/auto-sync-server/auto-sync-server.component.ts b/vscode4teaching-webapp/src/app/components/private/student/course/exercise-status/in-progress-exercise/auto-sync-server/auto-sync-server.component.ts index 809f53d6..91991de9 100644 --- a/vscode4teaching-webapp/src/app/components/private/student/course/exercise-status/in-progress-exercise/auto-sync-server/auto-sync-server.component.ts +++ b/vscode4teaching-webapp/src/app/components/private/student/course/exercise-status/in-progress-exercise/auto-sync-server/auto-sync-server.component.ts @@ -1,4 +1,5 @@ import { Component, ElementRef, Input, OnDestroy, OnInit, ViewChild } from '@angular/core'; +import { supported as fileSystemAccessApiSupported } from "browser-fs-access"; import { ExerciseUserInfo } from "../../../../../../../model/exercise-user-info.model"; import { DirectoryNode, TreeDiffResult } from "../../../../../../../model/file-system/file-system.model"; import { SyncJobPriorityQueue } from "../../../../../../../model/file-system/syncjob-priority-queue"; @@ -81,7 +82,7 @@ export class AutoSyncServerComponent implements OnInit, OnDestroy { // The current directory structure is obtained in the same way as in step 2. // If a FileSystemDirectoryHandle already exists (in case the File System Access API can be used), it is not necessary to ask user for the directory again. let currentDirectoryStructure: DirectoryNode | undefined; - if (this.fileSystemReadDirectoryService.fileSystemAccessAPISupported() && this.exerciseDirectoryHandle) { + if (fileSystemAccessApiSupported && this.exerciseDirectoryHandle) { currentDirectoryStructure = await this.fileSystemReadDirectoryService.supportedFileSystemAPI(this.exerciseDirectoryHandle); } diff --git a/vscode4teaching-webapp/src/app/components/private/student/course/student-course.component.html b/vscode4teaching-webapp/src/app/components/private/student/course/student-course.component.html index 2c790cb4..1ea16948 100644 --- a/vscode4teaching-webapp/src/app/components/private/student/course/student-course.component.html +++ b/vscode4teaching-webapp/src/app/components/private/student/course/student-course.component.html @@ -12,7 +12,7 @@
-
+

{{ this.course.name }}

@@ -23,7 +23,7 @@

{{ this.course.name }}

- +
diff --git a/vscode4teaching-webapp/src/app/components/private/student/course/student-course.component.ts b/vscode4teaching-webapp/src/app/components/private/student/course/student-course.component.ts index 410a8f54..5037be15 100644 --- a/vscode4teaching-webapp/src/app/components/private/student/course/student-course.component.ts +++ b/vscode4teaching-webapp/src/app/components/private/student/course/student-course.component.ts @@ -5,6 +5,7 @@ import { ExerciseUserInfo } from "../../../../model/exercise-user-info.model"; import { Exercise } from "../../../../model/exercise.model"; import { CourseService } from "../../../../services/rest-api/model-entities/course/course.service"; import { ExerciseUserInfoService } from "../../../../services/rest-api/model-entities/exercise-user-info/exercise-user-info.service"; +import { supported as fileSystemAccessApiSupported } from "browser-fs-access"; @Component({ selector: 'app-student-course', @@ -32,7 +33,7 @@ export class StudentCourseComponent implements OnInit { this.courseDirectory = undefined; - this.error = false; + this.error = !fileSystemAccessApiSupported; } diff --git a/vscode4teaching-webapp/src/app/components/private/teacher/course/teacher-exercise/students-progress/students-progress.component.html b/vscode4teaching-webapp/src/app/components/private/teacher/course/teacher-exercise/students-progress/students-progress.component.html index 5603f305..d9a6ef8f 100644 --- a/vscode4teaching-webapp/src/app/components/private/teacher/course/teacher-exercise/students-progress/students-progress.component.html +++ b/vscode4teaching-webapp/src/app/components/private/teacher/course/teacher-exercise/students-progress/students-progress.component.html @@ -13,11 +13,16 @@

Students' progress

Currently, preview mode is enabled. You can only see the progress of the students. -
To enable the full mode, choose a directory at your local computer where the students' submissions will be synchronized on demand. + +
To enable the full mode, choose a directory at your local computer where the students' submissions will be synchronized on demand. +
+ +
Full mode is not supported in this browser. To enable it, use a browser that supports interacting with the local file system. +
-
diff --git a/vscode4teaching-webapp/src/app/components/private/teacher/course/teacher-exercise/students-progress/students-progress.component.ts b/vscode4teaching-webapp/src/app/components/private/teacher/course/teacher-exercise/students-progress/students-progress.component.ts index 2c9aaa4e..88e061e5 100644 --- a/vscode4teaching-webapp/src/app/components/private/teacher/course/teacher-exercise/students-progress/students-progress.component.ts +++ b/vscode4teaching-webapp/src/app/components/private/teacher/course/teacher-exercise/students-progress/students-progress.component.ts @@ -1,5 +1,6 @@ import { HttpEvent } from "@angular/common/http"; import { Component, Input } from '@angular/core'; +import { supported as fileSystemAccessApiSupported } from "browser-fs-access"; import { Observable } from "rxjs"; import { ExerciseUserInfo } from "../../../../../../model/exercise-user-info.model"; import { Exercise } from "../../../../../../model/exercise.model"; @@ -19,6 +20,8 @@ export class StudentsProgressComponent { // Preview mode (true) means that the user has not selected a local directory to save the files and the dashboard only shows real-time information on the progress of students // Full mode (false) means that the user has selected a local directory to save the files and the dashboard allows them to download the files on demand public isPreview: boolean; + // File System Access API is supported by the browser + public fsaApiSupported: boolean; // Files last update timestamp (only for full mode) public filesLastUpdateTimestamp: Date | undefined; // Only one download can be active at a time (either students files, template files or solution files) @@ -35,6 +38,7 @@ export class StudentsProgressComponent { private fileExchangeService: FileExchangeService ) { this.isPreview = true; + this.fsaApiSupported = fileSystemAccessApiSupported; this.isActiveDownload = false; this.downloadProgressBar = { visible: false, process: undefined, percentage: 0 }; this.studentIdentitiesShown = true; diff --git a/vscode4teaching-webapp/src/app/services/file-system/read-directory/file-system-read-directory.service.ts b/vscode4teaching-webapp/src/app/services/file-system/read-directory/file-system-read-directory.service.ts index 5599ae25..2cbf8985 100644 --- a/vscode4teaching-webapp/src/app/services/file-system/read-directory/file-system-read-directory.service.ts +++ b/vscode4teaching-webapp/src/app/services/file-system/read-directory/file-system-read-directory.service.ts @@ -1,6 +1,5 @@ import { Injectable } from '@angular/core'; -import { supported } from "browser-fs-access"; -import { DirectoryNode, FileNode, Node, TreeDiffResult } from "../../../model/file-system/file-system.model"; + import { DirectoryNode, FileNode, Node, TreeDiffResult } from "../../../model/file-system/file-system.model"; /** * File System service @@ -16,10 +15,6 @@ export class FileSystemReadDirectoryService { constructor() { } - public fileSystemAccessAPISupported(): boolean { - return supported && window.hasOwnProperty("showDirectoryPicker"); - } - /** * Returns a DirectoryNode-based tree representing the file-and-directory structure included in directory represented by rootDirectoryHandle, * recursively including contents of nested directories and introducing information about files. diff --git a/vscode4teaching-webapp/src/styles.scss b/vscode4teaching-webapp/src/styles.scss index ff23eb0b..e4936fe0 100644 --- a/vscode4teaching-webapp/src/styles.scss +++ b/vscode4teaching-webapp/src/styles.scss @@ -13,6 +13,16 @@ button.btn-xs { } } +a.link-v4t { + color: #F44A3E; + text-decoration-color: #F44A3E; + + &:hover { + color: #F33326; + text-decoration-color: #F33326; + } +} + a.btn-v4t, button.btn-v4t {