leonard2901 opened a new pull request, #896:
URL: https://github.com/apache/guacamole-client/pull/896

   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.
   
   Things that are not done yet:
   - any changes and new features after revision `46647641` (2023-06-02)
   - import module
   - `index/services/iconService.js`
   - `manage/directives/connectionPermissionEditor.js`
   - `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](https://www.npmjs.com/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.
   
   ### 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](https://webpack.js.org/concepts/module-federation) and the [module 
federation 
plugin](https://github.com/angular-architects/module-federation-plugin/blob/main/libs/mf/README.md)
 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/).
       - A noticeable difference is that transloco uses double curly braces by 
default to link to other translations keys
         instead of the `@:` prefix. However, I change it to `@:...:@` to 
prevent transcloco from removing parts of ICU messages 
(https://github.com/ngneat/transloco/issues/621).
   - 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](https://www.npmjs.com/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:
   ```typescript
   // 
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}`});
   ```
   
   ```typescript
   // 
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:
   
   ```typescript
   // 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";
   }
   ```


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: dev-unsubscr...@guacamole.apache.org

For queries about this service, please contact Infrastructure at:
us...@infra.apache.org

Reply via email to