This major pull request refactors the entire organizations feature to the new standards of Angular v17. This pull request also rewrites most of the functionality to be more concise and readable, following the best conventions for future students in COMP 423 and 393, using everything we have learned so far. This is the first such refactor, and all of the features will go through the same refactor eventually.
Note: Initial thoughts for this PR noted in #454.
Also, I am adding @jadekeegan and @atoneyd to this PR as reviewers - you all do not need to submit a code review for this, however since this is a major refactor to the feature we worked on and this is the first refactor moving to the new Angular v17 standards, I wanted you all to get alerted! Feel free to check it out in your own time 😇✨ .
File Structure Changes
First, the file structure has been edited and simplified. This new structure will loosely be what all feature folders in the final frontend refactor will look like. Here is a comparison from the file structure before and after the refactor:
We will now only have one service per feature. In the existing organizations service, there were three services, some of which have redundant functionality. This refactor collapses this down to one service, and we will aim to collapse this down to one service where applicable in other refactors. In situations where a feature contains sub-features of large size (namely only coworking and office-hours), they can be separated based on their respective features. Mainly, we will no longer separate admin and permission services from the main service.
Pipes are now in their own folder. Instead of having their own folder with a feature name, pipes are moved into a common folder (like widgets).
Admin features will be moved out to an Admin module. As @KrisJordan mentioned, it might be better for all admin features to be moved to a separate admin folder rather than individual feature folders. Since services are not declared in modules and are injected from root, feature services would be available to the Admin module. This might allow for our file organization to be cleaner.
Reactive State Management with the new Signal<>
Currently, the service for the organizations feature returns RxJS Observable objects, the result of HTTP method calls, for which the components subscribe to. This, along with the RxObject construction (ReplaySubject + Observable), handle state and data transfer in the CSXL application.
The latest version of Angular has announced the Signal<> construction which allows us to more easily handle state in our application. There is also RxJS-Signal interoperability (in v17+) which allows us to easily convert to and from Observables to Signals.
Signals have a much more concise syntax and are significantly easier to use. In this refactor and elsewhere, Signal<T> will serve as the direct replacement to the RxObject abstraction - so, RxObject will soon be deprecated. RxOrganization and RxOrganizationList have been removed in the refactor.
This is how we are able to combine the regular and admin services into one. The new OrganizationService has an organizations signal, which is updated when getOrganizations(), createOrganization(), updateOrganization(), and deleteOrganization() are called.
My original goal was to remove Observable<> entirely outside of the service layer, and leave Signal<> as the only component abstraction. However, after a lot of research, experimentation, and debugging, I found that this is not feasible. The subscribe() functionality of observables and other more advanced features of RxJS are a necessity, so all of these service functions still ultimately return Observable<Organization>. Even though Angular v17 includes Rx <-> Signal interpolation and conversion functions, this is not necessarily a one-to-one conversion as you might expect.
This refactor also reduces the dependency on resolvers, as some of these resolvers have been replaced with signals, especially where reactive data is helpful.
Angular v17 HTML Changes
One interesting update and convention change in the Angular v17 version is how the built-in ngFor and ngIf directives work. They have added new, built-in control flow into the HTML, which is the new standard. The new standard helps to limit the number of operations needed to modify the DOM (so more efficient), and may be more readable. Here is an example of the old if-else statement vs the new one in the HTML file:
<!-- OLD (Pre Angular v17) -->
<p *ngIf="authenticated; else showAlert">Logged in!</p>
<ng-template #showAlert>
<p>Not logged in!</p>
</ng-template
<!-- NEW (Angular v17+) (yes, this is HTML code!) -->
@if (authenticated) {
<p>Logged in!</p>
} @else {
<p>Not logged in!</p>
}
This supports @if, @else if, and @else if-else-if-else statements, @for for for-loops, and @switch for switch-case statements. Since this is likely the convention we will be moving towards in Angular v17, I began making this conversion in the HTML.
Note that the Material upgrade refactor will occur after all of the features are refactored, so the HTML / CSS will be revisited again.
@KrisJordan, one annoying problem is the formatting with the linter with these new structures. We might need to check the settings to adjust.
General Code Improvements and Other Changes
Throughout all of the TS files, the code has become more concise and clean! There is also full documentation.
The admin gear functionality has been tweaked slightly. Now, non-root users are able to see the gear on the main organization page if they are an admin for one or more organizations. When they access the admin page, they only see the organizations that they are able to modify.
The ProfileService and PermissionService services were also modified to include signals. Since changes here would cascade throughout the entire site, only a small port was done. The functionality is in addition to, not in replacement of, what was already there.
Functionality to create a new role for an organization upon its creation has been moved from the frontend to the backend.
The admin feature has been collapsed into a single component.
The events card on the organization detail page has been temporarily hidden.
Future Considerations
The events refactor will also cause a few more changes in the organization feature.
We can consider trying to remove the final usage of the resolver in the organizationResolver (formerly organizationDetailResolver). We might be able to come up with a more clever way to do this, as this would make our code even more consistent.
We might be able to try to figure out a better construction to replace the existing titleResolver and the child route added to get it configured.
As @KrisJordan mentioned, it might be better for all admin features to be moved to a separate admin folder rather than individual feature folders. Since services are not declared in modules and are injected from root, feature services would be available to the Admin module. This might allow for our file organization to be cleaner.
This major pull request refactors the entire organizations feature to the new standards of Angular v17. This pull request also rewrites most of the functionality to be more concise and readable, following the best conventions for future students in COMP 423 and 393, using everything we have learned so far. This is the first such refactor, and all of the features will go through the same refactor eventually.
Note: Initial thoughts for this PR noted in #454.
Also, I am adding @jadekeegan and @atoneyd to this PR as reviewers - you all do not need to submit a code review for this, however since this is a major refactor to the feature we worked on and this is the first refactor moving to the new Angular v17 standards, I wanted you all to get alerted! Feel free to check it out in your own time 😇✨ .
File Structure Changes
First, the file structure has been edited and simplified. This new structure will loosely be what all feature folders in the final frontend refactor will look like. Here is a comparison from the file structure before and after the refactor:
This leads to a few considerations, as listed:
We will now only have one service per feature. In the existing organizations service, there were three services, some of which have redundant functionality. This refactor collapses this down to one service, and we will aim to collapse this down to one service where applicable in other refactors. In situations where a feature contains sub-features of large size (namely only
coworking
andoffice-hours
), they can be separated based on their respective features. Mainly, we will no longer separate admin and permission services from the main service.Pipes are now in their own folder. Instead of having their own folder with a feature name, pipes are moved into a common folder (like widgets).
Admin features will be moved out to an Admin module. As @KrisJordan mentioned, it might be better for all admin features to be moved to a separate admin folder rather than individual feature folders. Since services are not declared in modules and are injected from root, feature services would be available to the Admin module. This might allow for our file organization to be cleaner.
Reactive State Management with the new
Signal<>
Currently, the service for the organizations feature returns RxJS
Observable
objects, the result of HTTP method calls, for which the components subscribe to. This, along with theRxObject
construction (ReplaySubject
+Observable
), handle state and data transfer in the CSXL application.The latest version of Angular has announced the
Signal<>
construction which allows us to more easily handle state in our application. There is also RxJS-Signal interoperability (in v17+) which allows us to easily convert to and from Observables to Signals.Signals have a much more concise syntax and are significantly easier to use. In this refactor and elsewhere,
Signal<T>
will serve as the direct replacement to theRxObject
abstraction - so,RxObject
will soon be deprecated.RxOrganization
andRxOrganizationList
have been removed in the refactor.Sample Component TypeScript File:
In addition, working with signals in the HTML files much easier as well:
Sample Component HTML File:
This is how we are able to combine the regular and admin services into one. The new
OrganizationService
has anorganizations
signal, which is updated whengetOrganizations()
,createOrganization()
,updateOrganization()
, anddeleteOrganization()
are called.My original goal was to remove
Observable<>
entirely outside of the service layer, and leaveSignal<>
as the only component abstraction. However, after a lot of research, experimentation, and debugging, I found that this is not feasible. Thesubscribe()
functionality of observables and other more advanced features ofRxJS
are a necessity, so all of these service functions still ultimately returnObservable<Organization>
. Even though Angular v17 includes Rx <-> Signal interpolation and conversion functions, this is not necessarily a one-to-one conversion as you might expect.This refactor also reduces the dependency on resolvers, as some of these resolvers have been replaced with signals, especially where reactive data is helpful.
Angular v17 HTML Changes
One interesting update and convention change in the Angular v17 version is how the built-in
ngFor
andngIf
directives work. They have added new, built-in control flow into the HTML, which is the new standard. The new standard helps to limit the number of operations needed to modify the DOM (so more efficient), and may be more readable. Here is an example of the old if-else statement vs the new one in the HTML file:This supports
@if
,@else if
, and@else
if-else-if-else statements,@for
for for-loops, and@switch
for switch-case statements. Since this is likely the convention we will be moving towards in Angular v17, I began making this conversion in the HTML.Note that the Material upgrade refactor will occur after all of the features are refactored, so the HTML / CSS will be revisited again.
@KrisJordan, one annoying problem is the formatting with the linter with these new structures. We might need to check the settings to adjust.
General Code Improvements and Other Changes
ProfileService
andPermissionService
services were also modified to include signals. Since changes here would cascade throughout the entire site, only a small port was done. The functionality is in addition to, not in replacement of, what was already there.Future Considerations
organizationResolver
(formerlyorganizationDetailResolver
). We might be able to come up with a more clever way to do this, as this would make our code even more consistent.titleResolver
and the child route added to get it configured.