Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

GUACAMOLE-1085: Migrate frontend to angular #896

Draft
wants to merge 65 commits into
base: main
Choose a base branch
from

Conversation

leonard2901
Copy link
Contributor

@leonard2901 leonard2901 commented Jun 30, 2023

This PR includes the current progress for the migration of the AngularJS frontend to Angular.
There is still a lot of work left to do, but I think now would be a good time to get some feedback on the code.

Overview

The new frontend consists of one Angular app and two Angular libraries:

  • guacamole-frontend

    • contains the main application
  • guacamole-frontend-lib

    • contains components that could be useful when building a custom Guacamole-Angular application
  • guacamole-frontend-ext-lib

    • contains services and classes for extensions that provide a clear interface for registering additional routes and field types

The application and both libraries are included in the maven build.

TODOs:

  • any changes and new features after revision 4664764 (2023-06-02)
  • migrate import module
  • migrate index/services/iconService.js
  • migrate manage/directives/connectionPermissionEditor.js
  • migrate manage/controllers/manageSharingProfileController.js
  • caching of API responses
  • refactor the managed client so that reusable code can be moved to the guacamole-frontend-lib
  • some documentation in the code is missing
  • TODOs in the code
  • code style might not be correct all the time
  • some styles are not applied properly since Angular's components introduce additional DOM elements
  • the functionality to serve complex extensions from the Java code
  • guacamole-common-js should be copied to the frontend in the build process. At the moment I just included a copy at projects/guacamole-frontend-lib/src/assets/. Are there any plans to release an official NPM package for guacamole-common-js?
  • type declarations for guacamole-common-js (projects/guacamole-frontend-lib/src/lib/types/Guacamole.ts). They will be replaced by the package @types/guacamole-common-js once it is updated.
  • automatic generation of the LICENSE and NOTICE files in the maven build.
    The angular build creates a 3rdpartylicenses.txt file, but I don't really know what to do with it.
    Any comments on this will be appreciated.
  • Do not assume that the application is always deployed at /guacamole/

Extensions

The biggest challenge in the migration was to build an extension system in Angular that was as flexible as the one in AngularJS.

  • Adding and modifying translation strings was mostly handled by the REST API and should work like before.
  • Inject additional HTML and CSS should work just like in AngularJS.
    • See apply-patches.service.ts and style-loader.service.ts
      in projects/guacamole-frontend/src/app/index/services/
  • More complex extensions can now be implemented as a separate Angular application
    • Extensions are loaded as a remote module via webpack module federation and the module federation plugin for Angular. Routes and form field can be added by implementing a bootstrap function. Adding custom Angular components to arbitrary locations will also be possible.
    • See doc/guacamole-frontend-extension-example for an example.
    • Note: the module federation configuration file (at the moment hard coded as projects/guacamole-frontend/src/moduleFederation/mf.manifest.json ) should be generated by the Java server in the future

Implementation notes

  • AngularJS services that mostly serve as data containers are replaced by simple classes with instance or static
    methods. Some of the more complex services are replaced by Angular services.
  • Named functions are mostly replaced by arrow functions.
  • Functions that return a promise with data from REST API are mostly replaced by functions that return an RxJS observable.
  • AngularJS's directives are replaced by Angular...
    • components if they are configured with restrict: 'E',
    • directives if they are configured with restrict: 'A'.
  • All styles are defined globally so that they can be overritten by extension styles
  • The authentication service method to perform HTTP request with the current token (AuthenticationService.request())
    is replaced by a HTTP interceptor
    (auth/interceptor/authentication.interceptor.ts).
  • The error handling of the HTTP requests (rest/services/requestService.js) is replaced by a HTTP interceptor
    (rest/interceptor/error-handling.interceptor.ts).
  • The configuration of the $http service (httpDefaults.js) is replaced by an HTTP
    interceptor (index/config/default-headers.interceptor.ts).
  • To disable certain interceptors for specific requests, the HttpContextTokens in the InterceptorService can be used.
  • angular-translate is replaced by transloco (https://ngneat.github.io/transloco/).
  • I refactored the GuacFileBrowser to simply use an *ngFor loop. In my tests I didn't notice any performance issues.
  • I added Cypress for E2E Tests in the cypress folder. The tests are not integrated in the build process, and I did not
    include a proper configuration file because of the various possible testing setups.
  • I removed workarounds for IE since Angular itself does no longer support IE. Should these workarounds still be
    kept?
    • TunnelService~uploadToStream
    • TunnelService~downloadStream
    • UserCredentials.getLink
    • UserCredentialService~getLink
  • To replace the $parse function of AngularJS I used the NPM package angular-expressions
    which is a copy of the AngularJS code as standalone module.
  • There are some more questions directly in the code marked as a TODO.

Running the code

For my setup the easiest way to run the code was to build the frontend with maven and use the war file in a docker-compose setup. Since the module federation config is hard coded for now there will be some errors when the example extension (doc/guacamole-frontend-extension-example) is not running (ng serve) at localhost:4202. If the extension is running, the content will be available at /extension-example.

It is also possible to run the frontend using ng serve and benefit from live reloading with a way to work around the same origin policy (modify HTTP headers/proxy/disable web security). Therefore, the libraries need to be built manually: ng build guacamole-frontend-lib and ng build guacamole-frontend-ext-lib. Additionally, the following code might be necessary to redirect the requests to the REST API:

// projects/guacamole-frontend/src/app/auth/interceptor/authentication.interceptor.ts
if(!request.url.startsWith('assets'))
    request = request.clone({url: `http://localhost:8080/guacamole/${request.url}`});
// projects/guacamole-frontend/src/app/client/services/managed-client.service.ts getInstance()
  tunnel = new Guacamole.ChainedTunnel(
      new Guacamole.WebSocketTunnel('ws://localhost:8080/guacamole/websocket-tunnel'),
      new Guacamole.HTTPTunnel('http://localhost:8080/guacamole/tunnel')

When using ng serve, the REST API from this branch should still be used.

To run the Cypress test I used the following configuration to disable web security for Chrome:

// guacamole/src/main/guacamole-frontend/cypress.config.ts
e2e: {
  setupNodeEvents(on, config) {
      on('before:browser:launch', (browser, launchOptions) => {

          if (browser.family === 'chromium') {
              launchOptions.args.push('--disable-web-security');
          }

          return launchOptions;
      })
  },
  baseUrl: "http://localhost:4200"
}

@leonard2901 leonard2901 closed this Nov 8, 2023
@leonard2901 leonard2901 reopened this Nov 8, 2023
@suncase
Copy link

suncase commented Mar 14, 2024

@leonard2901: when you are planning to release your guacamole-client-angular as a npm package?

@leonard2901
Copy link
Contributor Author

@suncase Thank you for you interest in the Angular client. As you can see in the description of the PR, there are still a few things I need to work on before this could possibly be merged. Unfortunately, I currently have less time for the project than I would have liked. So I can't tell you when this will be merged.

That being said, I don't think the frontend of the Guacamole Client will be released as an npm package.
My idea is to publish the packages "guacamole-frontend-ext-lib" and "guacamole-frontend-lib" on npm to facilitate 1) the creation of extensions for the frontend and 2) the creation of custom Guacamole-Angular applications.
If I have overlooked a use case, please feel free to describe it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants