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

refactor: replace $resource in angularjs form-api.client.factory.js with typescript FormService #1947

Merged
merged 37 commits into from
Jun 9, 2021

Conversation

chowyiyin
Copy link
Contributor

@chowyiyin chowyiyin commented May 21, 2021

Problem

This PR replaces the $resource object in form-api.client.factory.js with API call services provided byFormService.ts. Due to coupling between the interceptors and form-fields.client.factory, interceptors are kept intact in form-api.client.factory.js. Previously, the accessMode query parameter was also added to all API calls. This migration removes this from any API calls in which it is irrelevant.

Closes #1835, #1768

Solution

getInterceptor is called in form-api.client.factory.js and the relevant interceptor is passed to functions in FormService.ts, that handle all API calls.

Tests

Unit Tests

  • FormService.test.ts: add unit tests for functions in FormService.ts

Manual Tests

  • Load forms dashboard page. Check that all available forms are present. (query)
  • Click on any form. Should be redirected to edit page. Check that previous fields (if any) are present. (getAdmin)
  • Click on open in new window in share tab without activating form. Should be redirected to error page. (getPublic)
  • Click on open in new window in share tab after activating form. Should be redirected to public view of form. (getPublic)
  • Duplicate a field in a form. Check that the field is duplicated correctly i.e. contents of the field are correct (update)
  • Duplicate any form. Ensure duplicate form modal appears and duplicated form appears on the dashboard upon completion (save)
  • Delete a form. Ensure that the form is no longer visible on the dashboard (delete)
  • Create a form from scratch in storage mode and email mode. Should be redirected to edit page with no existing fields. Check that form appears on dashboard. (create)
  • Select create new form and select any template. Modal with template form in public view should be displayed. (template)
  • Select use template (following from previous check). Perform same checks done for create form.
  • Select preview mode of any existing form. Should be redirected to preview page. (preview)
  • Add a collaborator and change role to owner. Ownership should have changed. (transferOwner)
  • Create myinfo fields. Check that myinfo fields are correctly stripped and injected.
  • Duplicate myinfo fields. Check that myinfo fields are correctly stripped and injected.
  • Duplicate a form with myinfo fields. Check that myinfo fields are correctly stripped and injected.
  • Check that myinfo fields are correctly injected into public form view
  • Check that forms can be createdfrom the examples page
  • Check that forms can be created from the "Share Template" link under the "Share" tab

@chowyiyin chowyiyin requested a review from mantariksh May 21, 2021 10:09
@liangyuanruo
Copy link
Contributor

@mantariksh @chowyiyin Thanks for working on this - I'm thinking it could help with the React migration to also take a look at organising the different services better - FormApi, FormFields, FormService etc, probably in a separate PR.

Copy link
Contributor

@mantariksh mantariksh left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was a tough one to disentangle, great job!

When thinking about the implementation of the services, our first priority is to ensure that they are reusable in React. The point of the frontend services migration is to maximise the amount of code which is battle-tested in production in order to minimise the risk of the final cutover to React.

The FormService is currently doing quite a lot: injecting/stripping MyInfo data, converting POJOs into classes, handling error redirects etc. The issue with this is that it's entirely possible that we will handle all these things completely differently in React. For example, it's unlikely that we will port over the existing viewmodel classes (e.g. Form.class.js) into React.

I think a better approach might be to make the service dumb - it takes in the relevant data to call the correct endpoint, and returns the response. That's it. Any additional formatting of the request and response must be done by the caller. Then in the existing AngularJS FormAPI service, we perform all the necessary transformations on the request and response before and after calling the new TypeScript service. This way we can be sure that the new service is reusable - it's completely framework-agnostic as it only makes API calls.

Wdyt? Looping in @karrui and @tshuli too

@chowyiyin
Copy link
Contributor Author

chowyiyin commented May 24, 2021

This was a tough one to disentangle, great job!

Thank you! :)

When thinking about the implementation of the services, our first priority is to ensure that they are reusable in React. The point of the frontend services migration is to maximise the amount of code which is battle-tested in production in order to minimise the risk of the final cutover to React.

The FormService is currently doing quite a lot: injecting/stripping MyInfo data, converting POJOs into classes, handling error redirects etc. The issue with this is that it's entirely possible that we will handle all these things completely differently in React. For example, it's unlikely that we will port over the existing viewmodel classes (e.g. Form.class.js) into React.

I think a better approach might be to make the service dumb - it takes in the relevant data to call the correct endpoint, and returns the response. That's it. Any additional formatting of the request and response must be done by the caller. Then in the existing AngularJS FormAPI service, we perform all the necessary transformations on the request and response before and after calling the new TypeScript service. This way we can be sure that the new service is reusable - it's completely framework-agnostic as it only makes API calls.

Do correct me if I am wrong, but I think this service is, in a way, framework agnostic since the things mentioned above (e.g. injecting and stripping MyInfo data) are actually handled in the interceptor? FormService simply uses the interceptor that is passed in. The way the interceptor transforms the response and request is up to the caller to decide (in this case, form-api.client.factory.js.

@mantariksh
Copy link
Contributor

Do correct me if I am wrong, but I think this service is, in a way, framework agnostic since the things mentioned above (e.g. injecting and stripping MyInfo data) are actually handled in the interceptor?

This is true! But the reasons for needing interceptors are not framework-agnostic, eg the fact that a Form POJO has to be converted into a Form class. This reflects itself in the code too, e.g. in how the Interceptor type requires a responseError, which is needed purely because of how we handle redirects in AngularJS.

Furthermore, if the service just trusts the interceptors passed to it, then ultimately the caller has to implement the interceptor correctly, meaning there isn't much value in terms of code reuse.

@tshuli
Copy link
Contributor

tshuli commented May 24, 2021

Agree with @mantariksh on scoping the service to calling the correct API and returning the response - I think this is also consistent with how we've written the other services!

@chowyiyin chowyiyin marked this pull request as ready for review May 25, 2021 04:44
@chowyiyin chowyiyin changed the title refactor - replace $resource in angularjs form-api.client.factory.js with typescript FormService refactor: replace $resource in angularjs form-api.client.factory.js with typescript FormService May 25, 2021
Copy link
Contributor

@mantariksh mantariksh left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

first round of review, let's address these first before the next round!

src/public/services/FormService.ts Outdated Show resolved Hide resolved
src/public/services/FormService.ts Outdated Show resolved Hide resolved
src/public/services/FormService.ts Outdated Show resolved Hide resolved
src/public/services/FormService.ts Outdated Show resolved Hide resolved
src/public/services/FormService.ts Outdated Show resolved Hide resolved
src/public/services/FormService.ts Outdated Show resolved Hide resolved
src/public/services/FormService.ts Outdated Show resolved Hide resolved
src/public/services/FormService.ts Outdated Show resolved Hide resolved
src/public/services/FormService.ts Outdated Show resolved Hide resolved
src/public/services/FormService.ts Outdated Show resolved Hide resolved
src/public/services/FormService.ts Outdated Show resolved Hide resolved
src/public/services/FormService.ts Outdated Show resolved Hide resolved
src/public/services/FormService.ts Outdated Show resolved Hide resolved
src/public/services/FormService.ts Outdated Show resolved Hide resolved
src/public/services/FormService.ts Outdated Show resolved Hide resolved
src/public/services/FormService.ts Outdated Show resolved Hide resolved
src/public/services/FormService.ts Outdated Show resolved Hide resolved
src/public/modules/forms/config/forms.client.routes.js Outdated Show resolved Hide resolved
src/public/modules/forms/config/forms.client.routes.js Outdated Show resolved Hide resolved
src/public/modules/forms/config/forms.client.routes.js Outdated Show resolved Hide resolved
src/public/services/CreateFormService.ts Outdated Show resolved Hide resolved
src/public/services/AdminViewFormService.ts Outdated Show resolved Hide resolved
src/public/services/CreateFormService.ts Outdated Show resolved Hide resolved
src/public/services/ExamplesService.ts Outdated Show resolved Hide resolved
src/public/services/PublicFormService.ts Outdated Show resolved Hide resolved
src/public/services/UpdateFormService.ts Outdated Show resolved Hide resolved
@mantariksh
Copy link
Contributor

Blocked by #2061

@chowyiyin chowyiyin force-pushed the refactor/formApiClientFactory branch from 9174626 to 8837971 Compare June 4, 2021 05:22
@chowyiyin chowyiyin force-pushed the refactor/formApiClientFactory branch from f962176 to b2994ff Compare June 7, 2021 04:42
Copy link
Contributor

@mantariksh mantariksh left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm, really well done! let's test this super thoroughly on staging because it touches nearly every single important API. you can add the following checks to your manual tests:

  • myinfo fields are correctly stripped and injected when creating myinfo fields
  • myinfo fields are correctly stripped and injected when duplicating myinfo fields
  • myinfo fields are correctly stripped and injected when duplicating a form with myinfo fields
  • myinfo fields are correctly injected into public form view
  • forms can be created from the examples page
  • forms can be created from the "Share Template" link under the "Share" tab

FormErrorService.redirect({
response: err.response,
targetState: errorTargetState,
targetFormId: extractFormId(get(err.response, 'config.url')),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I actually think the current implementation of extractFormId is wrong because we don't always have the form ID at the start of the path, but that can be fixed separately

Copy link
Contributor

@mantariksh mantariksh left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks for the thorough testing! I know it's a lot of work but I hope the importance is clear, since this PR touches a lot of core functionality.

@chowyiyin chowyiyin merged commit e8f6c65 into develop Jun 9, 2021
@chowyiyin chowyiyin deleted the refactor/formApiClientFactory branch June 9, 2021 04:27
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.

Convert form-api.client.factory.js to TypeScript
4 participants