From 501ccaf6a75e91d8a977698641ad6b818b78b3c0 Mon Sep 17 00:00:00 2001 From: Guilherme Gabriel Date: Sat, 16 Dec 2023 02:34:45 -0300 Subject: [PATCH 1/6] feat/AB#80252_Allow-frontend-to-reload-when-admin-updates/create-a-form --- .../src/app/application/pages/add-page/add-page.component.ts | 1 + .../app/dashboard/pages/form-builder/form-builder.component.ts | 1 + 2 files changed, 2 insertions(+) diff --git a/apps/back-office/src/app/application/pages/add-page/add-page.component.ts b/apps/back-office/src/app/application/pages/add-page/add-page.component.ts index c611f65973..4bad2813ea 100644 --- a/apps/back-office/src/app/application/pages/add-page/add-page.component.ts +++ b/apps/back-office/src/app/application/pages/add-page/add-page.component.ts @@ -202,6 +202,7 @@ export class AddPageComponent extends UnsubscribeComponent implements OnInit { ); this.onSubmit(); + window.location.reload(); } }, error: (err) => { diff --git a/apps/back-office/src/app/dashboard/pages/form-builder/form-builder.component.ts b/apps/back-office/src/app/dashboard/pages/form-builder/form-builder.component.ts index bf3f4a1e88..0e158abc5a 100644 --- a/apps/back-office/src/app/dashboard/pages/form-builder/form-builder.component.ts +++ b/apps/back-office/src/app/dashboard/pages/form-builder/form-builder.component.ts @@ -301,6 +301,7 @@ export class FormBuilderComponent implements OnInit { localStorage.removeItem(`form:${this.id}`); this.hasChanges = false; this.authService.canLogout.next(true); + window.location.reload(); } }, error: (err) => { From 4fe40adf2e2b08c92b601d54791d3482199c0d34 Mon Sep 17 00:00:00 2001 From: Guilherme Gabriel Date: Tue, 19 Dec 2023 07:23:13 -0300 Subject: [PATCH 2/6] fix: wait for the server to be ready again --- .../form-builder/form-builder.component.ts | 53 +++++++- .../pages/form-builder/graphql/queries.ts | 118 ++++++++++++++++++ .../query-builder/query-builder.service.ts | 9 ++ 3 files changed, 175 insertions(+), 5 deletions(-) diff --git a/apps/back-office/src/app/dashboard/pages/form-builder/form-builder.component.ts b/apps/back-office/src/app/dashboard/pages/form-builder/form-builder.component.ts index 0e158abc5a..b9d2475d77 100644 --- a/apps/back-office/src/app/dashboard/pages/form-builder/form-builder.component.ts +++ b/apps/back-office/src/app/dashboard/pages/form-builder/form-builder.component.ts @@ -7,7 +7,7 @@ import { EDIT_FORM_STATUS, EDIT_FORM_STRUCTURE, } from './graphql/mutations'; -import { GET_SHORT_FORM_BY_ID } from './graphql/queries'; +import { GET_SHORT_FORM_BY_ID, GET_QUERY_TYPES } from './graphql/queries'; import { Dialog } from '@angular/cdk/dialog'; import { AuthService, @@ -19,8 +19,9 @@ import { EditFormMutationResponse, SnackbarSpinnerComponent, } from '@oort-front/shared'; + import { SpinnerComponent } from '@oort-front/ui'; -import { Observable } from 'rxjs'; +import { Observable, firstValueFrom } from 'rxjs'; import { map } from 'rxjs/operators'; import { TranslateService } from '@ngx-translate/core'; import { SnackbarService } from '@oort-front/ui'; @@ -29,6 +30,7 @@ import { isEqual } from 'lodash'; import { GraphQLError } from 'graphql'; import { Overlay, OverlayRef } from '@angular/cdk/overlay'; import { ComponentPortal } from '@angular/cdk/portal'; +import { QueryBuilderService } from 'libs/shared/src/lib/services/query-builder/query-builder.service'; /** Default snackbar config for after request complete */ const REQUEST_SNACKBAR_CONF = { @@ -101,7 +103,8 @@ export class FormBuilderComponent implements OnInit { private confirmService: ConfirmService, private translate: TranslateService, private breadcrumbService: BreadcrumbService, - private overlay: Overlay + private overlay: Overlay, + private queryBuilder: QueryBuilderService ) {} /** @@ -301,7 +304,6 @@ export class FormBuilderComponent implements OnInit { localStorage.removeItem(`form:${this.id}`); this.hasChanges = false; this.authService.canLogout.next(true); - window.location.reload(); } }, error: (err) => { @@ -309,9 +311,50 @@ export class FormBuilderComponent implements OnInit { loadingSnackbarRef.instance.dismiss(); this.snackBar.openSnackBar(err.message, { error: true }); }, - complete: () => { + complete: async () => { // Detach the current set overlay overlayRef.detach(); + + // Wait for backend connection to be established + const checkBackendConnectionWithGetQueryTypes = + async (): Promise => { + let isConnected = true; + + try { + const result = await firstValueFrom( + this.apollo.query({ + query: GET_QUERY_TYPES, + }) + ); + + const { data, errors, networkStatus } = result; + + if (errors || networkStatus !== 7) { + isConnected = false; + } else { + // Set available types in query builder + this.queryBuilder.setAvailableTypes( + (data as any).__schema.types + ); + } + } catch (err) { + isConnected = false; + } + + return isConnected; + }; + + // Wait for backend connection to be established + await new Promise((resolve) => setTimeout(resolve, 3000)); + const waitForBackendConnection = async () => { + while ( + (await checkBackendConnectionWithGetQueryTypes()) === false + ) { + await new Promise((resolve) => setTimeout(resolve, 1000)); + } + }; + + await waitForBackendConnection(); }, }); } diff --git a/apps/back-office/src/app/dashboard/pages/form-builder/graphql/queries.ts b/apps/back-office/src/app/dashboard/pages/form-builder/graphql/queries.ts index de5adab574..dd2ed38894 100644 --- a/apps/back-office/src/app/dashboard/pages/form-builder/graphql/queries.ts +++ b/apps/back-office/src/app/dashboard/pages/form-builder/graphql/queries.ts @@ -38,3 +38,121 @@ export const GET_SHORT_FORM_BY_ID = gql` } } `; + +/** Graphql request for getting query types */ +export const GET_QUERY_TYPES = gql` + query GetQueryTypes { + __schema { + types { + name + kind + fields { + name + args { + name + type { + name + kind + inputFields { + name + type { + name + kind + } + } + } + } + type { + name + kind + fields { + name + args { + name + type { + name + kind + inputFields { + name + type { + name + kind + } + } + } + } + type { + name + kind + ofType { + name + fields { + name + type { + name + kind + ofType { + name + } + } + } + } + } + } + ofType { + name + fields { + name + type { + name + kind + ofType { + name + } + } + } + } + } + } + } + queryType { + name + kind + fields { + name + args { + name + type { + name + kind + inputFields { + name + type { + name + kind + } + } + } + } + type { + name + kind + ofType { + name + fields { + name + type { + name + kind + ofType { + name + } + } + } + } + } + } + } + } + } +`; diff --git a/libs/shared/src/lib/services/query-builder/query-builder.service.ts b/libs/shared/src/lib/services/query-builder/query-builder.service.ts index 2f89e97bbc..78f12946fb 100644 --- a/libs/shared/src/lib/services/query-builder/query-builder.service.ts +++ b/libs/shared/src/lib/services/query-builder/query-builder.service.ts @@ -141,6 +141,15 @@ export class QueryBuilderService { }); } + /** + * Sets available queries. + * + * @param types Available types. + */ + public setAvailableTypes(types: any[]) { + this.availableTypes.next(types); + } + /** * Gets list of fields from a type. * From 937928b02ce45240395984f474710a932b483b6a Mon Sep 17 00:00:00 2001 From: Guilherme Gabriel Date: Tue, 19 Dec 2023 07:36:21 -0300 Subject: [PATCH 3/6] fix: lint --- .../app/dashboard/pages/form-builder/form-builder.component.ts | 3 ++- libs/shared/src/index.ts | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/apps/back-office/src/app/dashboard/pages/form-builder/form-builder.component.ts b/apps/back-office/src/app/dashboard/pages/form-builder/form-builder.component.ts index b9d2475d77..94ed220373 100644 --- a/apps/back-office/src/app/dashboard/pages/form-builder/form-builder.component.ts +++ b/apps/back-office/src/app/dashboard/pages/form-builder/form-builder.component.ts @@ -30,7 +30,7 @@ import { isEqual } from 'lodash'; import { GraphQLError } from 'graphql'; import { Overlay, OverlayRef } from '@angular/cdk/overlay'; import { ComponentPortal } from '@angular/cdk/portal'; -import { QueryBuilderService } from 'libs/shared/src/lib/services/query-builder/query-builder.service'; +import { QueryBuilderService } from '@oort-front/shared'; /** Default snackbar config for after request complete */ const REQUEST_SNACKBAR_CONF = { @@ -92,6 +92,7 @@ export class FormBuilderComponent implements OnInit { * @param translate Angular translate service * @param breadcrumbService Shared breadcrumb service * @param overlay Angular overlay service + * @param queryBuilder Query builder service */ constructor( private apollo: Apollo, diff --git a/libs/shared/src/index.ts b/libs/shared/src/index.ts index 938e3213b4..646b8084ee 100644 --- a/libs/shared/src/index.ts +++ b/libs/shared/src/index.ts @@ -24,6 +24,7 @@ export * from './lib/services/context/context.service'; export * from './lib/services/data-template/data-template.service'; export * from './lib/services/editor/editor.service'; export * from './lib/services/rest/rest.service'; +export * from './lib/services/query-builder/query-builder.service'; // === DIRECTIVES === export * from './lib/directives/skeleton/public-api'; From 29d8edcbfa4828397702c04e5a0ba6211431e201 Mon Sep 17 00:00:00 2001 From: Guilherme Gabriel Date: Tue, 19 Dec 2023 14:14:58 -0300 Subject: [PATCH 4/6] fix: new approach --- .../form-builder/form-builder.component.ts | 48 +++---- .../pages/form-builder/graphql/queries.ts | 120 +----------------- .../query-builder/query-builder.service.ts | 53 ++++---- 3 files changed, 50 insertions(+), 171 deletions(-) diff --git a/apps/back-office/src/app/dashboard/pages/form-builder/form-builder.component.ts b/apps/back-office/src/app/dashboard/pages/form-builder/form-builder.component.ts index 94ed220373..cb8803f531 100644 --- a/apps/back-office/src/app/dashboard/pages/form-builder/form-builder.component.ts +++ b/apps/back-office/src/app/dashboard/pages/form-builder/form-builder.component.ts @@ -7,7 +7,7 @@ import { EDIT_FORM_STATUS, EDIT_FORM_STRUCTURE, } from './graphql/mutations'; -import { GET_SHORT_FORM_BY_ID, GET_QUERY_TYPES } from './graphql/queries'; +import { GET_SHORT_FORM_BY_ID } from './graphql/queries'; import { Dialog } from '@angular/cdk/dialog'; import { AuthService, @@ -316,45 +316,33 @@ export class FormBuilderComponent implements OnInit { // Detach the current set overlay overlayRef.detach(); - // Wait for backend connection to be established - const checkBackendConnectionWithGetQueryTypes = - async (): Promise => { - let isConnected = true; + let connected = false; - try { - const result = await firstValueFrom( - this.apollo.query({ - query: GET_QUERY_TYPES, - }) - ); + // Subscribe to the isDoneLoading$ observable to get the current state of + // the backend connection after reloading the query types + await this.queryBuilder.isDoneLoading$.subscribe( + async (isDoneLoading) => { + connected = isDoneLoading; + } + ); - const { data, errors, networkStatus } = result; + // Wait for 3 seconds to start reloading the query types + await new Promise((resolve) => setTimeout(resolve, 3000)); - if (errors || networkStatus !== 7) { - isConnected = false; - } else { - // Set available types in query builder - this.queryBuilder.setAvailableTypes( - (data as any).__schema.types - ); - } - } catch (err) { - isConnected = false; - } + // Reload the query types + this.queryBuilder.reloadQueryTypes.next(null); - return isConnected; - }; + // Set the isDoneLoading to false to wait for the backend connection + this.queryBuilder.isDoneLoading.next(false); // Wait for backend connection to be established - await new Promise((resolve) => setTimeout(resolve, 3000)); - const waitForBackendConnection = async () => { - while ( - (await checkBackendConnectionWithGetQueryTypes()) === false - ) { + const waitForBackendConnection = async (): Promise => { + while (!connected) { await new Promise((resolve) => setTimeout(resolve, 1000)); } }; + // Start waiting for backend connection await waitForBackendConnection(); }, }); diff --git a/apps/back-office/src/app/dashboard/pages/form-builder/graphql/queries.ts b/apps/back-office/src/app/dashboard/pages/form-builder/graphql/queries.ts index dd2ed38894..59eacd54b4 100644 --- a/apps/back-office/src/app/dashboard/pages/form-builder/graphql/queries.ts +++ b/apps/back-office/src/app/dashboard/pages/form-builder/graphql/queries.ts @@ -37,122 +37,4 @@ export const GET_SHORT_FORM_BY_ID = gql` } } } -`; - -/** Graphql request for getting query types */ -export const GET_QUERY_TYPES = gql` - query GetQueryTypes { - __schema { - types { - name - kind - fields { - name - args { - name - type { - name - kind - inputFields { - name - type { - name - kind - } - } - } - } - type { - name - kind - fields { - name - args { - name - type { - name - kind - inputFields { - name - type { - name - kind - } - } - } - } - type { - name - kind - ofType { - name - fields { - name - type { - name - kind - ofType { - name - } - } - } - } - } - } - ofType { - name - fields { - name - type { - name - kind - ofType { - name - } - } - } - } - } - } - } - queryType { - name - kind - fields { - name - args { - name - type { - name - kind - inputFields { - name - type { - name - kind - } - } - } - } - type { - name - kind - ofType { - name - fields { - name - type { - name - kind - ofType { - name - } - } - } - } - } - } - } - } - } -`; +`; \ No newline at end of file diff --git a/libs/shared/src/lib/services/query-builder/query-builder.service.ts b/libs/shared/src/lib/services/query-builder/query-builder.service.ts index 78f12946fb..9f6bcad4ca 100644 --- a/libs/shared/src/lib/services/query-builder/query-builder.service.ts +++ b/libs/shared/src/lib/services/query-builder/query-builder.service.ts @@ -107,10 +107,13 @@ export class QueryBuilderService { } /** Loading indicator that asserts whether available queries are done loading */ - private isDoneLoading = new ReplaySubject(); + public isDoneLoading = new ReplaySubject(); /** Loading indicator as observable */ public isDoneLoading$ = this.isDoneLoading.asObservable(); + /** Reload indicator for query types */ + public reloadQueryTypes = new BehaviorSubject(null); + /** User fields */ private userFields = []; @@ -122,34 +125,40 @@ export class QueryBuilderService { */ constructor(private apollo: Apollo) { this.isDoneLoading.next(false); + this.fetchTypes(); + this.reloadQueryTypes.subscribe(() => { + this.fetchTypes(); + }); + } + + /** + * Fetches the types from the schema. + */ + private async fetchTypes() { this.apollo .query({ query: GET_QUERY_TYPES, }) - .subscribe(({ data }) => { - this.isDoneLoading.next(true); - this.availableTypes.next(data.__schema.types); - this.availableQueries.next( - data.__schema.queryType.fields.filter( - (x: any) => - x.name.startsWith('all') || x.name.endsWith(REFERENCE_DATA_END) - ) - ); - this.userFields = data.__schema.types - .find((x: any) => x.name === 'User') - .fields.filter((x: any) => USER_FIELDS.includes(x.name)); + .subscribe({ + next: ({ data, errors }) => { + this.isDoneLoading.next(true); + this.availableTypes.next(data.__schema.types); + this.availableQueries.next( + data.__schema.queryType.fields.filter( + (x: any) => + x.name.startsWith('all') || x.name.endsWith(REFERENCE_DATA_END) + ) + ); + this.userFields = data.__schema.types + .find((x: any) => x.name === 'User') + .fields.filter((x: any) => USER_FIELDS.includes(x.name)); + }, + error: (error) => { + this.isDoneLoading.next(false); + }, }); } - /** - * Sets available queries. - * - * @param types Available types. - */ - public setAvailableTypes(types: any[]) { - this.availableTypes.next(types); - } - /** * Gets list of fields from a type. * From 7edc7f40efb7cc9ae2152dbd87d03d1edfb38b7f Mon Sep 17 00:00:00 2001 From: Guilherme Gabriel Date: Tue, 19 Dec 2023 14:18:58 -0300 Subject: [PATCH 5/6] fix: lint --- .../dashboard/pages/form-builder/form-builder.component.ts | 4 ++-- .../src/app/dashboard/pages/form-builder/graphql/queries.ts | 2 +- .../src/lib/services/query-builder/query-builder.service.ts | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/apps/back-office/src/app/dashboard/pages/form-builder/form-builder.component.ts b/apps/back-office/src/app/dashboard/pages/form-builder/form-builder.component.ts index cb8803f531..25e5d1108e 100644 --- a/apps/back-office/src/app/dashboard/pages/form-builder/form-builder.component.ts +++ b/apps/back-office/src/app/dashboard/pages/form-builder/form-builder.component.ts @@ -21,7 +21,7 @@ import { } from '@oort-front/shared'; import { SpinnerComponent } from '@oort-front/ui'; -import { Observable, firstValueFrom } from 'rxjs'; +import { Observable } from 'rxjs'; import { map } from 'rxjs/operators'; import { TranslateService } from '@ngx-translate/core'; import { SnackbarService } from '@oort-front/ui'; @@ -318,7 +318,7 @@ export class FormBuilderComponent implements OnInit { let connected = false; - // Subscribe to the isDoneLoading$ observable to get the current state of + // Subscribe to the isDoneLoading$ observable to get the current state of // the backend connection after reloading the query types await this.queryBuilder.isDoneLoading$.subscribe( async (isDoneLoading) => { diff --git a/apps/back-office/src/app/dashboard/pages/form-builder/graphql/queries.ts b/apps/back-office/src/app/dashboard/pages/form-builder/graphql/queries.ts index 59eacd54b4..de5adab574 100644 --- a/apps/back-office/src/app/dashboard/pages/form-builder/graphql/queries.ts +++ b/apps/back-office/src/app/dashboard/pages/form-builder/graphql/queries.ts @@ -37,4 +37,4 @@ export const GET_SHORT_FORM_BY_ID = gql` } } } -`; \ No newline at end of file +`; diff --git a/libs/shared/src/lib/services/query-builder/query-builder.service.ts b/libs/shared/src/lib/services/query-builder/query-builder.service.ts index 9f6bcad4ca..0076c9389d 100644 --- a/libs/shared/src/lib/services/query-builder/query-builder.service.ts +++ b/libs/shared/src/lib/services/query-builder/query-builder.service.ts @@ -140,7 +140,7 @@ export class QueryBuilderService { query: GET_QUERY_TYPES, }) .subscribe({ - next: ({ data, errors }) => { + next: ({ data }) => { this.isDoneLoading.next(true); this.availableTypes.next(data.__schema.types); this.availableQueries.next( @@ -153,7 +153,7 @@ export class QueryBuilderService { .find((x: any) => x.name === 'User') .fields.filter((x: any) => USER_FIELDS.includes(x.name)); }, - error: (error) => { + error: () => { this.isDoneLoading.next(false); }, }); From 27c8411006fdbcaa3099ed369543c498abeadfaa Mon Sep 17 00:00:00 2001 From: Guilherme Gabriel Date: Tue, 19 Dec 2023 14:23:14 -0300 Subject: [PATCH 6/6] fix: remove old code --- .../src/app/application/pages/add-page/add-page.component.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/apps/back-office/src/app/application/pages/add-page/add-page.component.ts b/apps/back-office/src/app/application/pages/add-page/add-page.component.ts index 4bad2813ea..c611f65973 100644 --- a/apps/back-office/src/app/application/pages/add-page/add-page.component.ts +++ b/apps/back-office/src/app/application/pages/add-page/add-page.component.ts @@ -202,7 +202,6 @@ export class AddPageComponent extends UnsubscribeComponent implements OnInit { ); this.onSubmit(); - window.location.reload(); } }, error: (err) => {