From 1fe5a6cca096bf34e55b32a5b1a82d713b29d2af Mon Sep 17 00:00:00 2001 From: RenzoPrats Date: Thu, 7 Dec 2023 17:20:20 -0300 Subject: [PATCH 1/6] feat: started to add geographic context --- .../pages/dashboard/dashboard.component.ts | 194 +++++++++++++----- libs/shared/src/lib/models/page.model.ts | 3 + .../services/dashboard/dashboard.service.ts | 2 +- .../services/dashboard/graphql/mutations.ts | 14 +- 4 files changed, 160 insertions(+), 53 deletions(-) diff --git a/apps/back-office/src/app/dashboard/pages/dashboard/dashboard.component.ts b/apps/back-office/src/app/dashboard/pages/dashboard/dashboard.component.ts index 6e76af9446..a46a0f72b4 100644 --- a/apps/back-office/src/app/dashboard/pages/dashboard/dashboard.component.ts +++ b/apps/back-office/src/app/dashboard/pages/dashboard/dashboard.component.ts @@ -231,50 +231,29 @@ export class DashboardComponent ) .subscribe(() => { this.loading = true; - // Reset context - this.contextRecord = null; - this.contextId.setValue(null, { - emitEvent: false, - emitModelToViewChange: false, - emitViewToModelChange: false, - }); - this.contextId.markAsPristine(); - this.contextId.markAsUntouched(); - // Reset scroll when changing page - const pageContainer = this.document.getElementById('appPageContainer'); - if (pageContainer) { - pageContainer.scrollTop = 0; - } - - /** Extract main dashboard id */ - const id = this.route.snapshot.paramMap.get('id'); - /** Extract query id to load template */ - const queryId = this.route.snapshot.queryParamMap.get('id'); - if (id) { - if (queryId) { - this.loadDashboard(id).then(() => { - const templates = this.dashboard?.page?.contentWithContext; - const type = this.contextType; - if (type) { - // Find template from parent's templates, based on query params id + if (this.dashboard?.page?.geographicContext?.enabled) { + // Reset scroll when changing page + const pageContainer = + this.document.getElementById('appPageContainer'); + if (pageContainer) { + pageContainer.scrollTop = 0; + } + /** Extract main dashboard id */ + const id = this.route.snapshot.paramMap.get('id'); + /** Extract query id to load template */ + const queryId = this.route.snapshot.queryParamMap.get('id'); + if (id) { + if (queryId) { + this.loadDashboard(id).then(() => { + const templates = this.dashboard?.page?.contentWithContext; const template = templates?.find((d) => { - // If templates use reference data - if (type === 'element') - return ( - 'element' in d && - d.element.toString().trim() === queryId.trim() - ); - // If templates use resource - else if (type === 'record') - return ( - 'record' in d && - d.record.toString().trim() === queryId.trim() - ); - return false; + return ( + 'geographic' in d && + d.geographic.toString().trim() === queryId.trim() + ); }); - if (template) { - // if we found the contextual dashboard, load it + // if we found the geographic dashboard, load it this.loadDashboard(template.content).then( () => (this.loading = false) ); @@ -288,7 +267,7 @@ export class DashboardComponent this.dashboardService .createDashboardWithContext( this.dashboard?.page?.id as string, - type, // type of context + 'geographic', // type of context queryId // id of the context ) .then(({ data }) => { @@ -298,21 +277,110 @@ export class DashboardComponent 'models.dashboard.context.notifications.templateCreated' ) ); - // load the contextual dashboard + // load the geographic dashboard this.loadDashboard( data.addDashboardWithContext.id ).then(() => (this.loading = false)); }); } } - } else { - this.loading = false; - } - }); - } else { - // if there is no id, we are not on a contextual dashboard, we simply load the dashboard - this.loadDashboard(id).then(() => (this.loading = false)); + }); + } } + } else { + // Reset context + this.contextRecord = null; + this.contextId.setValue(null, { + emitEvent: false, + emitModelToViewChange: false, + emitViewToModelChange: false, + }); + this.contextId.markAsPristine(); + this.contextId.markAsUntouched(); + // Reset scroll when changing page + const pageContainer = + this.document.getElementById('appPageContainer'); + if (pageContainer) { + pageContainer.scrollTop = 0; + } + + /** Extract main dashboard id */ + const id = this.route.snapshot.paramMap.get('id'); + /** Extract query id to load template */ + const queryId = this.route.snapshot.queryParamMap.get('id'); + if (id) { + if (queryId) { + this.loadDashboard(id).then(() => { + const templates = this.dashboard?.page?.contentWithContext; + const type = this.contextType; + if (type) { + // Find template from parent's templates, based on query params id + const template = templates?.find((d) => { + // If templates use reference data + if (type === 'element') + return ( + 'element' in d && + d.element.toString().trim() === queryId.trim() + ); + // If templates use resource + else if (type === 'record') + return ( + 'record' in d && + d.record.toString().trim() === queryId.trim() + ); + return false; + }); + + if (template) { + // if we found the contextual dashboard, load it + this.loadDashboard(template.content).then( + () => (this.loading = false) + ); + } else { + if (this.dashboard?.page && this.canUpdate) { + this.snackBar.openSnackBar( + this.translate.instant( + 'models.dashboard.context.notifications.creatingTemplate' + ) + ); + this.dashboardService + .createDashboardWithContext( + this.dashboard?.page?.id as string, + type, // type of context + queryId // id of the context + ) + .then(({ data }) => { + if (!data?.addDashboardWithContext?.id) return; + this.snackBar.openSnackBar( + this.translate.instant( + 'models.dashboard.context.notifications.templateCreated' + ) + ); + // load the contextual dashboard + this.loadDashboard( + data.addDashboardWithContext.id + ).then(() => (this.loading = false)); + }); + } + } + } else { + this.loading = false; + } + }); + } else { + // if there is no id, we are not on a contextual dashboard, we simply load the dashboard + this.loadDashboard(id).then(() => (this.loading = false)); + } + } + } + }); + this.countryCode.valueChanges + .pipe(debounceTime(500), takeUntil(this.destroy$)) + .subscribe((value) => { + console.log(value); + console.log(this.dashboard); + if (value) { + this.onGeographicContextChange(value); } }); } @@ -716,6 +784,32 @@ export class DashboardComponent } } + private async onGeographicContextChange(value: string | null | undefined) { + if ( + !this.dashboard?.id || + !this.dashboard?.page?.id || + !this.dashboard.page.geographicContext + ) + return; + if (value) { + console.log("aqui1"); + this.router.navigate(['.'], { + relativeTo: this.route, + queryParams: { + id: value, + }, + }); + } else { + console.log("aqui2"); + this.snackBar.openSnackBar( + this.translate.instant( + 'models.dashboard.context.notifications.loadDefault' + ) + ); + this.router.navigate(['.'], { relativeTo: this.route }); + } + } + /** * Handle dashboard context change by simply updating the url. * diff --git a/libs/shared/src/lib/models/page.model.ts b/libs/shared/src/lib/models/page.model.ts index a495d14d24..ed74b59572 100644 --- a/libs/shared/src/lib/models/page.model.ts +++ b/libs/shared/src/lib/models/page.model.ts @@ -93,6 +93,9 @@ export interface Page { | { record: string; } + | { + geographic: string; + } ) & { content: string; })[]; diff --git a/libs/shared/src/lib/services/dashboard/dashboard.service.ts b/libs/shared/src/lib/services/dashboard/dashboard.service.ts index a05a450875..a2862d96c3 100644 --- a/libs/shared/src/lib/services/dashboard/dashboard.service.ts +++ b/libs/shared/src/lib/services/dashboard/dashboard.service.ts @@ -164,7 +164,7 @@ export class DashboardService { */ public createDashboardWithContext( page: string, - context: 'element' | 'record', + context: 'element' | 'record' | 'geographic', id: string | number ) { return firstValueFrom( diff --git a/libs/shared/src/lib/services/dashboard/graphql/mutations.ts b/libs/shared/src/lib/services/dashboard/graphql/mutations.ts index 0917e4a252..74e90b0d24 100644 --- a/libs/shared/src/lib/services/dashboard/graphql/mutations.ts +++ b/libs/shared/src/lib/services/dashboard/graphql/mutations.ts @@ -64,8 +64,18 @@ export const UPDATE_PAGE_CONTEXT = gql` /** GraphQL mutation for creating a dashboard with context */ export const CREATE_DASHBOARD_WITH_CONTEXT = gql` - mutation createDashboardWithContext($page: ID!, $element: JSON, $record: ID) { - addDashboardWithContext(page: $page, element: $element, record: $record) { + mutation createDashboardWithContext( + $page: ID! + $element: JSON + $record: ID + $geographic: String! + ) { + addDashboardWithContext( + page: $page + element: $element + record: $record + geographic: $geographic + ) { id structure page { From 2430cd07c7a0ede140bb7940da36b649f60f5eae Mon Sep 17 00:00:00 2001 From: RenzoPrats Date: Fri, 8 Dec 2023 16:16:55 -0300 Subject: [PATCH 2/6] feat: continued allow to use region and contry context wi th element or record context --- .../pages/dashboard/dashboard.component.ts | 350 +++++++++++------- libs/shared/src/lib/models/page.model.ts | 5 +- .../services/dashboard/dashboard.service.ts | 8 +- .../services/dashboard/graphql/mutations.ts | 2 +- 4 files changed, 215 insertions(+), 150 deletions(-) diff --git a/apps/back-office/src/app/dashboard/pages/dashboard/dashboard.component.ts b/apps/back-office/src/app/dashboard/pages/dashboard/dashboard.component.ts index a46a0f72b4..fa4e4863b8 100644 --- a/apps/back-office/src/app/dashboard/pages/dashboard/dashboard.component.ts +++ b/apps/back-office/src/app/dashboard/pages/dashboard/dashboard.component.ts @@ -231,154 +231,216 @@ export class DashboardComponent ) .subscribe(() => { this.loading = true; - if (this.dashboard?.page?.geographicContext?.enabled) { - // Reset scroll when changing page - const pageContainer = - this.document.getElementById('appPageContainer'); - if (pageContainer) { - pageContainer.scrollTop = 0; - } - /** Extract main dashboard id */ - const id = this.route.snapshot.paramMap.get('id'); - /** Extract query id to load template */ - const queryId = this.route.snapshot.queryParamMap.get('id'); - if (id) { - if (queryId) { - this.loadDashboard(id).then(() => { - const templates = this.dashboard?.page?.contentWithContext; - const template = templates?.find((d) => { - return ( - 'geographic' in d && - d.geographic.toString().trim() === queryId.trim() - ); - }); - if (template) { - // if we found the geographic dashboard, load it - this.loadDashboard(template.content).then( - () => (this.loading = false) - ); - } else { - if (this.dashboard?.page && this.canUpdate) { - this.snackBar.openSnackBar( - this.translate.instant( - 'models.dashboard.context.notifications.creatingTemplate' - ) - ); - this.dashboardService - .createDashboardWithContext( - this.dashboard?.page?.id as string, - 'geographic', // type of context - queryId // id of the context - ) - .then(({ data }) => { - if (!data?.addDashboardWithContext?.id) return; - this.snackBar.openSnackBar( - this.translate.instant( - 'models.dashboard.context.notifications.templateCreated' - ) + // Reset context + this.contextRecord = null; + this.contextId.setValue(null, { + emitEvent: false, + emitModelToViewChange: false, + emitViewToModelChange: false, + }); + this.contextId.markAsPristine(); + this.contextId.markAsUntouched(); + // Reset scroll when changing page + const pageContainer = this.document.getElementById('appPageContainer'); + if (pageContainer) { + pageContainer.scrollTop = 0; + } + + /** Extract main dashboard id */ + const id = this.route.snapshot.paramMap.get('id'); + /** Extract query id to load template */ + const queryId = this.route.snapshot.queryParamMap.get('id'); + const queryGeographic = + this.route.snapshot.queryParamMap.get('geographic'); + const context: any = {}; + + if (id) { + if (queryId || queryGeographic) { + this.loadDashboard(id).then(() => { + const templates = this.dashboard?.page?.contentWithContext; + const type = this.contextType; + let template: any; + + if (queryGeographic) { + // geographic and queryId + if (queryId) { + if (type) { + template = templates?.find((d) => { + // If templates use reference data + if (type === 'element') + return ( + 'element' in d && + d.element.toString().trim() === queryId.trim() && + 'geographic' in d && + d.geographic && + d.geographic.toString().trim() === + queryGeographic.trim() + ); + // If templates use resource + else if (type === 'record') + return ( + 'record' in d && + d.record.toString().trim() === queryId.trim() && + 'geographic' in d && + d.geographic && + d.geographic.toString().trim() === + queryGeographic.trim() ); - // load the geographic dashboard - this.loadDashboard( - data.addDashboardWithContext.id - ).then(() => (this.loading = false)); - }); + return false; + }); } - } - }); - } - } - } else { - // Reset context - this.contextRecord = null; - this.contextId.setValue(null, { - emitEvent: false, - emitModelToViewChange: false, - emitViewToModelChange: false, - }); - this.contextId.markAsPristine(); - this.contextId.markAsUntouched(); - // Reset scroll when changing page - const pageContainer = - this.document.getElementById('appPageContainer'); - if (pageContainer) { - pageContainer.scrollTop = 0; - } - /** Extract main dashboard id */ - const id = this.route.snapshot.paramMap.get('id'); - /** Extract query id to load template */ - const queryId = this.route.snapshot.queryParamMap.get('id'); - if (id) { - if (queryId) { - this.loadDashboard(id).then(() => { - const templates = this.dashboard?.page?.contentWithContext; - const type = this.contextType; - if (type) { - // Find template from parent's templates, based on query params id - const template = templates?.find((d) => { + // geographic + } else { + console.log("here123"); + template = templates?.find((d) => { // If templates use reference data - if (type === 'element') - return ( - 'element' in d && - d.element.toString().trim() === queryId.trim() - ); - // If templates use resource - else if (type === 'record') - return ( - 'record' in d && - d.record.toString().trim() === queryId.trim() - ); - return false; + return ( + 'geographic' in d && + d.geographic && + d.geographic.toString().trim() === queryGeographic.trim() + ); }); - - if (template) { - // if we found the contextual dashboard, load it - this.loadDashboard(template.content).then( - () => (this.loading = false) + } + // queryId + } else if (queryId) { + template = templates?.find((d) => { + // If templates use reference data + if (type === 'element') + return ( + 'element' in d && + d.element.toString().trim() === queryId.trim() ); - } else { - if (this.dashboard?.page && this.canUpdate) { + // If templates use resource + else if (type === 'record') + return ( + 'record' in d && + d.record.toString().trim() === queryId.trim() + ); + return false; + }); + } + + if (template) { + console.log("aqui456"); + // if we found the contextual dashboard, load it + this.loadDashboard(template.content).then( + () => (this.loading = false) + ); + } else { + console.log("aqui789"); + if (this.dashboard?.page && this.canUpdate) { + this.snackBar.openSnackBar( + this.translate.instant( + 'models.dashboard.context.notifications.creatingTemplate' + ) + ); + console.log('AAAAAAAAAAAA'); + console.log("type = ", type); + if (queryGeographic && queryId && type) { + console.log("1"); + context[type] = queryId; + context['geographic'] = queryGeographic; + } else if (queryId && type) { + console.log("2"); + context[type] = queryId; + } else if (queryGeographic) { + console.log("3"); + context['geographic'] = queryGeographic; + } + + console.log("context = ", context); + + this.dashboardService + .createDashboardWithContext( + this.dashboard?.page?.id as string, + context + ) + .then(({ data }) => { + if (!data?.addDashboardWithContext?.id) return; this.snackBar.openSnackBar( this.translate.instant( - 'models.dashboard.context.notifications.creatingTemplate' + 'models.dashboard.context.notifications.templateCreated' ) ); - this.dashboardService - .createDashboardWithContext( - this.dashboard?.page?.id as string, - type, // type of context - queryId // id of the context - ) - .then(({ data }) => { - if (!data?.addDashboardWithContext?.id) return; - this.snackBar.openSnackBar( - this.translate.instant( - 'models.dashboard.context.notifications.templateCreated' - ) - ); - // load the contextual dashboard - this.loadDashboard( - data.addDashboardWithContext.id - ).then(() => (this.loading = false)); - }); - } - } - } else { - this.loading = false; + // load the contextual dashboard + this.loadDashboard(data.addDashboardWithContext.id).then( + () => (this.loading = false) + ); + }); } - }); - } else { - // if there is no id, we are not on a contextual dashboard, we simply load the dashboard - this.loadDashboard(id).then(() => (this.loading = false)); - } + } + // if (type) { + // // Find template from parent's templates, based on query params id + // const template = templates?.find((d) => { + // // If templates use reference data + // if (type === 'element') + // return ( + // 'element' in d && + // d.element.toString().trim() === queryId.trim() + // ); + // // If templates use resource + // else if (type === 'record') + // return ( + // 'record' in d && + // d.record.toString().trim() === queryId.trim() + // ); + // return false; + // }); + + // if (template) { + // // if we found the contextual dashboard, load it + // this.loadDashboard(template.content).then( + // () => (this.loading = false) + // ); + // } else { + // if (this.dashboard?.page && this.canUpdate) { + // this.snackBar.openSnackBar( + // this.translate.instant( + // 'models.dashboard.context.notifications.creatingTemplate' + // ) + // ); + // this.dashboardService + // .createDashboardWithContext( + // this.dashboard?.page?.id as string, + // type, // type of context + // queryId // id of the context + // ) + // .then(({ data }) => { + // if (!data?.addDashboardWithContext?.id) return; + // this.snackBar.openSnackBar( + // this.translate.instant( + // 'models.dashboard.context.notifications.templateCreated' + // ) + // ); + // // load the contextual dashboard + // this.loadDashboard( + // data.addDashboardWithContext.id + // ).then(() => (this.loading = false)); + // }); + // } + // } + // } else { + // this.loading = false; + // } + }); + } else { + // if there is no id, we are not on a contextual dashboard, we simply load the dashboard + this.loadDashboard(id).then(() => (this.loading = false)); } } + // } + }); + this.regionCode.valueChanges + .pipe(debounceTime(1000), takeUntil(this.destroy$)) + .subscribe((value) => { + if (value) { + this.onGeographicContextChange(value); + } }); this.countryCode.valueChanges .pipe(debounceTime(500), takeUntil(this.destroy$)) .subscribe((value) => { - console.log(value); - console.log(this.dashboard); if (value) { this.onGeographicContextChange(value); } @@ -788,19 +850,22 @@ export class DashboardComponent if ( !this.dashboard?.id || !this.dashboard?.page?.id || - !this.dashboard.page.geographicContext + !this.dashboard.page.geographicContext?.enabled ) return; if (value) { - console.log("aqui1"); + const queryParams = { ...this.route.snapshot.queryParams }; + // Update the 'geographic' parameter if it exists, or set it if it's undefined + if ('geographic' in queryParams) { + queryParams.geographic = value; + } else { + queryParams['geographic'] = value; + } this.router.navigate(['.'], { relativeTo: this.route, - queryParams: { - id: value, - }, + queryParams, }); } else { - console.log("aqui2"); this.snackBar.openSnackBar( this.translate.instant( 'models.dashboard.context.notifications.loadDefault' @@ -824,11 +889,16 @@ export class DashboardComponent ) return; if (value) { + const queryParams = { ...this.route.snapshot.queryParams }; + // Update the 'id' parameter if it exists, or set it if it's undefined + if ('id' in queryParams) { + queryParams.id = value; + } else { + queryParams['id'] = value; + } this.router.navigate(['.'], { relativeTo: this.route, - queryParams: { - id: value, - }, + queryParams, }); // const urlArr = this.router.url.split('/'); // urlArr[urlArr.length - 1] = `${parentDashboardId}?id=${value}`; diff --git a/libs/shared/src/lib/models/page.model.ts b/libs/shared/src/lib/models/page.model.ts index ed74b59572..13e0f6cf0a 100644 --- a/libs/shared/src/lib/models/page.model.ts +++ b/libs/shared/src/lib/models/page.model.ts @@ -93,11 +93,10 @@ export interface Page { | { record: string; } - | { - geographic: string; - } ) & { content: string; + } & { + geographic?: string; })[]; geographicContext?: PageGeographicContextType; autoDeletedAt?: Date; diff --git a/libs/shared/src/lib/services/dashboard/dashboard.service.ts b/libs/shared/src/lib/services/dashboard/dashboard.service.ts index a2862d96c3..b2a1571608 100644 --- a/libs/shared/src/lib/services/dashboard/dashboard.service.ts +++ b/libs/shared/src/lib/services/dashboard/dashboard.service.ts @@ -162,17 +162,13 @@ export class DashboardService { * @param id The id of the context to be added to the dashboard * @returns The newly created dashboard */ - public createDashboardWithContext( - page: string, - context: 'element' | 'record' | 'geographic', - id: string | number - ) { + public createDashboardWithContext(page: string, context: any) { return firstValueFrom( this.apollo.mutate({ mutation: CREATE_DASHBOARD_WITH_CONTEXT, variables: { page, - [context]: id, + ...context, }, }) ); diff --git a/libs/shared/src/lib/services/dashboard/graphql/mutations.ts b/libs/shared/src/lib/services/dashboard/graphql/mutations.ts index 74e90b0d24..f838b005f0 100644 --- a/libs/shared/src/lib/services/dashboard/graphql/mutations.ts +++ b/libs/shared/src/lib/services/dashboard/graphql/mutations.ts @@ -68,7 +68,7 @@ export const CREATE_DASHBOARD_WITH_CONTEXT = gql` $page: ID! $element: JSON $record: ID - $geographic: String! + $geographic: String ) { addDashboardWithContext( page: $page From 10e64dee23a4a2271d8d93d6a18bf155f8c6c35f Mon Sep 17 00:00:00 2001 From: RenzoPrats Date: Mon, 11 Dec 2023 16:07:55 -0300 Subject: [PATCH 3/6] feat: finished geographic context --- .../pages/dashboard/dashboard.component.ts | 116 +++++------------- 1 file changed, 29 insertions(+), 87 deletions(-) diff --git a/apps/back-office/src/app/dashboard/pages/dashboard/dashboard.component.ts b/apps/back-office/src/app/dashboard/pages/dashboard/dashboard.component.ts index fa4e4863b8..10cd6e1de5 100644 --- a/apps/back-office/src/app/dashboard/pages/dashboard/dashboard.component.ts +++ b/apps/back-office/src/app/dashboard/pages/dashboard/dashboard.component.ts @@ -260,7 +260,6 @@ export class DashboardComponent const templates = this.dashboard?.page?.contentWithContext; const type = this.contextType; let template: any; - if (queryGeographic) { // geographic and queryId if (queryId) { @@ -289,10 +288,8 @@ export class DashboardComponent return false; }); } - - // geographic + // geographic } else { - console.log("here123"); template = templates?.find((d) => { // If templates use reference data return ( @@ -320,37 +317,26 @@ export class DashboardComponent return false; }); } - if (template) { - console.log("aqui456"); // if we found the contextual dashboard, load it this.loadDashboard(template.content).then( () => (this.loading = false) ); } else { - console.log("aqui789"); if (this.dashboard?.page && this.canUpdate) { this.snackBar.openSnackBar( this.translate.instant( 'models.dashboard.context.notifications.creatingTemplate' ) ); - console.log('AAAAAAAAAAAA'); - console.log("type = ", type); if (queryGeographic && queryId && type) { - console.log("1"); context[type] = queryId; context['geographic'] = queryGeographic; } else if (queryId && type) { - console.log("2"); context[type] = queryId; } else if (queryGeographic) { - console.log("3"); context['geographic'] = queryGeographic; } - - console.log("context = ", context); - this.dashboardService .createDashboardWithContext( this.dashboard?.page?.id as string, @@ -370,59 +356,6 @@ export class DashboardComponent }); } } - // if (type) { - // // Find template from parent's templates, based on query params id - // const template = templates?.find((d) => { - // // If templates use reference data - // if (type === 'element') - // return ( - // 'element' in d && - // d.element.toString().trim() === queryId.trim() - // ); - // // If templates use resource - // else if (type === 'record') - // return ( - // 'record' in d && - // d.record.toString().trim() === queryId.trim() - // ); - // return false; - // }); - - // if (template) { - // // if we found the contextual dashboard, load it - // this.loadDashboard(template.content).then( - // () => (this.loading = false) - // ); - // } else { - // if (this.dashboard?.page && this.canUpdate) { - // this.snackBar.openSnackBar( - // this.translate.instant( - // 'models.dashboard.context.notifications.creatingTemplate' - // ) - // ); - // this.dashboardService - // .createDashboardWithContext( - // this.dashboard?.page?.id as string, - // type, // type of context - // queryId // id of the context - // ) - // .then(({ data }) => { - // if (!data?.addDashboardWithContext?.id) return; - // this.snackBar.openSnackBar( - // this.translate.instant( - // 'models.dashboard.context.notifications.templateCreated' - // ) - // ); - // // load the contextual dashboard - // this.loadDashboard( - // data.addDashboardWithContext.id - // ).then(() => (this.loading = false)); - // }); - // } - // } - // } else { - // this.loading = false; - // } }); } else { // if there is no id, we are not on a contextual dashboard, we simply load the dashboard @@ -434,16 +367,16 @@ export class DashboardComponent this.regionCode.valueChanges .pipe(debounceTime(1000), takeUntil(this.destroy$)) .subscribe((value) => { - if (value) { - this.onGeographicContextChange(value); - } + // reset country code as it's not possible to have country and region selected + this.countryCode.setValue(value, { emitEvent: false }); + this.onGeographicContextChange(value); }); this.countryCode.valueChanges .pipe(debounceTime(500), takeUntil(this.destroy$)) .subscribe((value) => { - if (value) { - this.onGeographicContextChange(value); - } + // reset region code as it's not possible to have country and region selected + this.regionCode.setValue(value, { emitEvent: false }); + this.onGeographicContextChange(value); }); } @@ -481,15 +414,15 @@ export class DashboardComponent scrollToNewItems: false, }; if (this.dashboard.page?.geographicContext?.enabled) { - this.countryCode.setValue( - this.dashboard.page?.geographicContext?.country - ); - this.regionCode.setValue( - this.dashboard.page?.geographicContext?.region - ); - } else { - this.countryCode.setValue(''); - this.regionCode.setValue(''); + if (this.dashboard.page.geographicContext.country) { + this.countryCode.setValue( + this.dashboard.page?.geographicContext?.country + ); + } else { + this.regionCode.setValue( + this.dashboard.page?.geographicContext?.region + ); + } } this.initContext(); this.updateContextOptions(); @@ -846,7 +779,13 @@ export class DashboardComponent } } + /** + * Handle dashboard geographic context change by simply updating the url. + * + * @param value value of the geographic field + */ private async onGeographicContextChange(value: string | null | undefined) { + const queryParams = { ...this.route.snapshot.queryParams }; if ( !this.dashboard?.id || !this.dashboard?.page?.id || @@ -854,7 +793,6 @@ export class DashboardComponent ) return; if (value) { - const queryParams = { ...this.route.snapshot.queryParams }; // Update the 'geographic' parameter if it exists, or set it if it's undefined if ('geographic' in queryParams) { queryParams.geographic = value; @@ -866,12 +804,14 @@ export class DashboardComponent queryParams, }); } else { + // remove geographic from query params + delete queryParams['geographic']; this.snackBar.openSnackBar( this.translate.instant( 'models.dashboard.context.notifications.loadDefault' ) ); - this.router.navigate(['.'], { relativeTo: this.route }); + this.router.navigate(['.'], { relativeTo: this.route, queryParams }); } } @@ -881,6 +821,7 @@ export class DashboardComponent * @param value id of the element or record */ private async onContextChange(value: string | number | undefined | null) { + const queryParams = { ...this.route.snapshot.queryParams }; if ( !this.dashboard?.id || !this.dashboard?.page?.id || @@ -889,7 +830,6 @@ export class DashboardComponent ) return; if (value) { - const queryParams = { ...this.route.snapshot.queryParams }; // Update the 'id' parameter if it exists, or set it if it's undefined if ('id' in queryParams) { queryParams.id = value; @@ -904,12 +844,14 @@ export class DashboardComponent // urlArr[urlArr.length - 1] = `${parentDashboardId}?id=${value}`; // this.router.navigateByUrl(urlArr.join('/')); } else { + // remove id from query params + delete queryParams['id']; this.snackBar.openSnackBar( this.translate.instant( 'models.dashboard.context.notifications.loadDefault' ) ); - this.router.navigate(['.'], { relativeTo: this.route }); + this.router.navigate(['.'], { relativeTo: this.route, queryParams }); // const urlArr = this.router.url.split('/'); // urlArr[urlArr.length - 1] = parentDashboardId; // this.router.navigateByUrl(urlArr.join('/')); From c7b2f7297389be85ae025bdfce1aab8729ddce22 Mon Sep 17 00:00:00 2001 From: RenzoPrats Date: Mon, 11 Dec 2023 16:09:00 -0300 Subject: [PATCH 4/6] fixed lint --- .../src/app/dashboard/pages/dashboard/dashboard.component.ts | 2 +- libs/shared/src/lib/services/dashboard/dashboard.service.ts | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/apps/back-office/src/app/dashboard/pages/dashboard/dashboard.component.ts b/apps/back-office/src/app/dashboard/pages/dashboard/dashboard.component.ts index 10cd6e1de5..90bd6f20b4 100644 --- a/apps/back-office/src/app/dashboard/pages/dashboard/dashboard.component.ts +++ b/apps/back-office/src/app/dashboard/pages/dashboard/dashboard.component.ts @@ -299,7 +299,7 @@ export class DashboardComponent ); }); } - // queryId + // queryId } else if (queryId) { template = templates?.find((d) => { // If templates use reference data diff --git a/libs/shared/src/lib/services/dashboard/dashboard.service.ts b/libs/shared/src/lib/services/dashboard/dashboard.service.ts index b2a1571608..80c50ebe14 100644 --- a/libs/shared/src/lib/services/dashboard/dashboard.service.ts +++ b/libs/shared/src/lib/services/dashboard/dashboard.service.ts @@ -159,7 +159,6 @@ export class DashboardService { * * @param page Page to copy content from * @param context The type of context to be added to the dashboard - * @param id The id of the context to be added to the dashboard * @returns The newly created dashboard */ public createDashboardWithContext(page: string, context: any) { From b46de50c351648a6651443e90f39b4339084c574 Mon Sep 17 00:00:00 2001 From: Unai Zalba Date: Tue, 12 Dec 2023 10:56:34 +0100 Subject: [PATCH 5/6] feat/AB#80877_add_logic_to_create_edit_load_page_with_geographic_context feat: add context enable checker on the query params load for dashboard template in order to avoid the context page creation if not enabled by manually setting params in the url browser bar refactor: onContextChange method for both record and geographic context in order to handle it in the same function refactor: create function for context listeners to keep all in the same place in favor of a more readable code refactor: dashboard template load logic in order to have a clearer and more understandable flow read of the logic within refactor: remove unnecessary debounceTime pipe for select menus(search debounceTime is handled in the ui component) --- .../pages/dashboard/dashboard.component.ts | 359 +++++++++--------- .../application/application.service.ts | 2 +- 2 files changed, 171 insertions(+), 190 deletions(-) diff --git a/apps/back-office/src/app/dashboard/pages/dashboard/dashboard.component.ts b/apps/back-office/src/app/dashboard/pages/dashboard/dashboard.component.ts index 58403617b9..b36a456a35 100644 --- a/apps/back-office/src/app/dashboard/pages/dashboard/dashboard.component.ts +++ b/apps/back-office/src/app/dashboard/pages/dashboard/dashboard.component.ts @@ -37,13 +37,7 @@ import { GET_RESOURCE_RECORDS, } from './graphql/queries'; import { TranslateService } from '@ngx-translate/core'; -import { - map, - takeUntil, - filter, - startWith, - debounceTime, -} from 'rxjs/operators'; +import { map, takeUntil, filter, startWith } from 'rxjs/operators'; import { Observable, firstValueFrom } from 'rxjs'; import { FormControl } from '@angular/forms'; import { cloneDeep, isEqual } from 'lodash'; @@ -187,12 +181,7 @@ export class DashboardComponent } ngOnInit(): void { - this.contextId.valueChanges - .pipe(debounceTime(500), takeUntil(this.destroy$)) - .subscribe((value) => { - // Load template, or go back to default one - this.onContextChange(value); - }); + this.setUpContextFieldListeners(); /** Listen to router events navigation end, to get last version of params & queryParams. */ this.router.events .pipe( @@ -217,138 +206,163 @@ export class DashboardComponent pageContainer.scrollTop = 0; } - /** Extract main dashboard id */ - const id = this.route.snapshot.paramMap.get('id'); - /** Extract query id to load template */ - const queryId = this.route.snapshot.queryParamMap.get('id'); - const queryGeographic = - this.route.snapshot.queryParamMap.get('geographic'); - const context: any = {}; - - if (id) { - if (queryId || queryGeographic) { - this.loadDashboard(id).then(() => { - const templates = this.dashboard?.page?.contentWithContext; - const type = this.contextType; - let template: any; - if (queryGeographic) { - // geographic and queryId - if (queryId) { - if (type) { - template = templates?.find((d) => { - // If templates use reference data - if (type === 'element') - return ( - 'element' in d && - d.element.toString().trim() === queryId.trim() && - 'geographic' in d && - d.geographic && - d.geographic.toString().trim() === - queryGeographic.trim() - ); - // If templates use resource - else if (type === 'record') - return ( - 'record' in d && - d.record.toString().trim() === queryId.trim() && - 'geographic' in d && - d.geographic && - d.geographic.toString().trim() === - queryGeographic.trim() - ); - return false; - }); - } - // geographic - } else { - template = templates?.find((d) => { - // If templates use reference data + this.handleContextTemplateLoad(); + }); + } + + /** + * Set up all the listeners for the possible context set in the current page + */ + private setUpContextFieldListeners() { + this.contextId.valueChanges + .pipe(takeUntil(this.destroy$)) + .subscribe((value) => { + // Load template, or go back to default one + this.onContextChange(value); + }); + this.regionCode.valueChanges + .pipe(takeUntil(this.destroy$)) + .subscribe((value) => { + // reset country code as it's not possible to have country and region selected + this.countryCode.setValue(value, { emitEvent: false }); + this.onContextChange(value, 'geographic'); + }); + this.countryCode.valueChanges + .pipe(takeUntil(this.destroy$)) + .subscribe((value) => { + // reset region code as it's not possible to have country and region selected + this.regionCode.setValue(value, { emitEvent: false }); + this.onContextChange(value, 'geographic'); + }); + } + + /** + * Load the correct context template for the given context params on the current dashboard + */ + private handleContextTemplateLoad() { + /** Extract main dashboard id */ + const id = this.route.snapshot.paramMap.get('id'); + /** Extract query id to load template */ + const queryId = this.route.snapshot.queryParamMap.get('id'); + const queryGeographic = this.route.snapshot.queryParamMap.get('geographic'); + const context: any = {}; + + if (id) { + // Even if query params exists, we don't want to load/create any template if option is not enabled in the dashboard + if ( + (this.contextType && queryId) || + (this.dashboard?.page?.geographicContext?.enabled && queryGeographic) + ) { + this.loadDashboard(id).then(() => { + const templates = this.dashboard?.page?.contentWithContext; + const type = this.contextType; + let template: any; + if (queryId) { + // No geographic, then check reference data and record templates + if (!queryGeographic) { + template = templates?.find((d) => { + // If templates use reference data + if (type === 'element') + return ( + 'element' in d && + d.element.toString().trim() === queryId.trim() + ); + // If templates use resource + else if (type === 'record') + return ( + 'record' in d && + d.record.toString().trim() === queryId.trim() + ); + return false; + }); + } else { + if (type) { + template = templates?.find((d) => { + // If templates use reference data with the geographic context + if (type === 'element') { return ( + 'element' in d && + d.element.toString().trim() === queryId.trim() && 'geographic' in d && d.geographic && d.geographic.toString().trim() === queryGeographic.trim() ); - }); - } - // queryId - } else if (queryId) { - template = templates?.find((d) => { - // If templates use reference data - if (type === 'element') - return ( - 'element' in d && - d.element.toString().trim() === queryId.trim() - ); - // If templates use resource - else if (type === 'record') + } + // If templates use resource with geographic context + else if (type === 'record') { return ( 'record' in d && - d.record.toString().trim() === queryId.trim() + d.record.toString().trim() === queryId.trim() && + 'geographic' in d && + d.geographic && + d.geographic.toString().trim() === queryGeographic.trim() ); + } return false; }); } - if (template) { - // if we found the contextual dashboard, load it - this.loadDashboard(template.content).then( - () => (this.loading = false) + } + } else { + // If no context data but we have a geographic context + if (queryGeographic) { + template = templates?.find((d) => { + // If templates use geographic context + return ( + 'geographic' in d && + d.geographic && + d.geographic.toString().trim() === queryGeographic.trim() ); - } else { - if (this.dashboard?.page && this.canUpdate) { + }); + } + } + + if (template) { + // if we found the contextual dashboard, load it + this.loadDashboard(template.content).then( + () => (this.loading = false) + ); + } else { + if (this.dashboard?.page && this.canUpdate) { + this.snackBar.openSnackBar( + this.translate.instant( + 'models.dashboard.context.notifications.creatingTemplate' + ) + ); + if (queryGeographic && queryId && type) { + context[type] = queryId; + context['geographic'] = queryGeographic; + } else if (queryId && type) { + context[type] = queryId; + } else if (queryGeographic) { + context['geographic'] = queryGeographic; + } + this.dashboardService + .createDashboardWithContext( + this.dashboard?.page?.id as string, + context + ) + .then(({ data }) => { + if (!data?.addDashboardWithContext?.id) { + return; + } this.snackBar.openSnackBar( this.translate.instant( - 'models.dashboard.context.notifications.creatingTemplate' + 'models.dashboard.context.notifications.templateCreated' ) ); - if (queryGeographic && queryId && type) { - context[type] = queryId; - context['geographic'] = queryGeographic; - } else if (queryId && type) { - context[type] = queryId; - } else if (queryGeographic) { - context['geographic'] = queryGeographic; - } - this.dashboardService - .createDashboardWithContext( - this.dashboard?.page?.id as string, - context - ) - .then(({ data }) => { - if (!data?.addDashboardWithContext?.id) return; - this.snackBar.openSnackBar( - this.translate.instant( - 'models.dashboard.context.notifications.templateCreated' - ) - ); - // load the contextual dashboard - this.loadDashboard(data.addDashboardWithContext.id).then( - () => (this.loading = false) - ); - }); - } - } - }); - } else { - // if there is no id, we are not on a contextual dashboard, we simply load the dashboard - this.loadDashboard(id).then(() => (this.loading = false)); + // load the contextual dashboard + this.loadDashboard(data.addDashboardWithContext.id).then( + () => (this.loading = false) + ); + }); + } } - } - // } - }); - this.regionCode.valueChanges - .pipe(debounceTime(1000), takeUntil(this.destroy$)) - .subscribe((value) => { - // reset country code as it's not possible to have country and region selected - this.countryCode.setValue(value, { emitEvent: false }); - this.onGeographicContextChange(value); - }); - this.countryCode.valueChanges - .pipe(debounceTime(500), takeUntil(this.destroy$)) - .subscribe((value) => { - // reset region code as it's not possible to have country and region selected - this.regionCode.setValue(value, { emitEvent: false }); - this.onGeographicContextChange(value); - }); + }); + } else { + // if there is no id, we are not on a contextual dashboard, we simply load the dashboard + this.loadDashboard(id).then(() => (this.loading = false)); + } + } } /** @@ -745,82 +759,46 @@ export class DashboardComponent } /** - * Handle dashboard geographic context change by simply updating the url. + * Handle dashboard context type change by simply updating the url. * - * @param value value of the geographic field + * @param value id of the element or record, + * @param contextType set for the current page */ - private async onGeographicContextChange(value: string | null | undefined) { + private async onContextChange( + value: string | number | undefined | null, + contextType: 'record' | 'geographic' = 'record' + ) { const queryParams = { ...this.route.snapshot.queryParams }; if ( !this.dashboard?.id || !this.dashboard?.page?.id || - !this.dashboard.page.geographicContext?.enabled - ) + (contextType === 'record' && + (!this.dashboard.page.context || !this.contextType)) || + (contextType === 'geographic' && + !this.dashboard?.page?.geographicContext?.enabled) + ) { return; - if (value) { - // Update the 'geographic' parameter if it exists, or set it if it's undefined - if ('geographic' in queryParams) { - queryParams.geographic = value; - } else { - queryParams['geographic'] = value; - } - this.router.navigate(['.'], { - relativeTo: this.route, - queryParams, - }); - } else { - // remove geographic from query params - delete queryParams['geographic']; - this.snackBar.openSnackBar( - this.translate.instant( - 'models.dashboard.context.notifications.loadDefault' - ) - ); - this.router.navigate(['.'], { relativeTo: this.route, queryParams }); } - } - - /** - * Handle dashboard context change by simply updating the url. - * - * @param value id of the element or record - */ - private async onContextChange(value: string | number | undefined | null) { - const queryParams = { ...this.route.snapshot.queryParams }; - if ( - !this.dashboard?.id || - !this.dashboard?.page?.id || - !this.dashboard.page.context || - !this.contextType - ) - return; + const queryParamKey = contextType === 'record' ? 'id' : 'geographic'; if (value) { - // Update the 'id' parameter if it exists, or set it if it's undefined - if ('id' in queryParams) { - queryParams.id = value; - } else { - queryParams['id'] = value; - } - this.router.navigate(['.'], { - relativeTo: this.route, - queryParams, - }); + // Update the related key parameter if it exists, or set it if it's undefined + queryParams[queryParamKey] = value; // const urlArr = this.router.url.split('/'); // urlArr[urlArr.length - 1] = `${parentDashboardId}?id=${value}`; // this.router.navigateByUrl(urlArr.join('/')); } else { - // remove id from query params - delete queryParams['id']; + // remove related key from query params + delete queryParams[queryParamKey]; this.snackBar.openSnackBar( this.translate.instant( 'models.dashboard.context.notifications.loadDefault' ) ); - this.router.navigate(['.'], { relativeTo: this.route, queryParams }); - // const urlArr = this.router.url.split('/'); - // urlArr[urlArr.length - 1] = parentDashboardId; - // this.router.navigateByUrl(urlArr.join('/')); } + this.router.navigate(['.'], { relativeTo: this.route, queryParams }); + // const urlArr = this.router.url.split('/'); + // urlArr[urlArr.length - 1] = parentDashboardId; + // this.router.navigateByUrl(urlArr.join('/')); } /** Initializes the dashboard context */ @@ -987,8 +965,11 @@ export class DashboardComponent value: string | string[], geographicType: 'region' | 'country' ): void { - const geographicContext = { - ...this.dashboard?.page?.geographicContext, + // In case we switch from region to country + // remove previous geographic context property inside the dashboard object + delete this.dashboard?.page?.geographicContext; + const geographicContext: PageGeographicContextType = { + enabled: true, ...(value && { [geographicType]: value }), }; const callback = () => { @@ -996,14 +977,14 @@ export class DashboardComponent ...this.dashboard, page: { ...this.dashboard?.page, - geographicContext: geographicContext as PageGeographicContextType, + geographicContext: geographicContext, }, }; }; this.applicationService.updatePageGeographicContext( { id: this.dashboard?.page?.id, - geographicContext: geographicContext as PageGeographicContextType, + geographicContext: geographicContext, }, callback ); diff --git a/libs/shared/src/lib/services/application/application.service.ts b/libs/shared/src/lib/services/application/application.service.ts index d506e9e1df..2975e51e5f 100644 --- a/libs/shared/src/lib/services/application/application.service.ts +++ b/libs/shared/src/lib/services/application/application.service.ts @@ -2111,7 +2111,7 @@ export class ApplicationService { }, error: (errors: any) => { this.handleEditionMutationResponse( - errors, + [errors], this.translate.instant('common.page.one') ); }, From c671f45e3089008465b3e20a7c74924cb6b71800 Mon Sep 17 00:00:00 2001 From: Unai Zalba Date: Tue, 12 Dec 2023 11:25:00 +0100 Subject: [PATCH 6/6] feat/AB#80877_add_logic_to_create_edit_load_page_with_geographic_context fix: region and country property switch and save in order to exclude each other --- .../app/dashboard/pages/dashboard/dashboard.component.ts | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/apps/back-office/src/app/dashboard/pages/dashboard/dashboard.component.ts b/apps/back-office/src/app/dashboard/pages/dashboard/dashboard.component.ts index b36a456a35..cbbf5d5a49 100644 --- a/apps/back-office/src/app/dashboard/pages/dashboard/dashboard.component.ts +++ b/apps/back-office/src/app/dashboard/pages/dashboard/dashboard.component.ts @@ -225,6 +225,9 @@ export class DashboardComponent .subscribe((value) => { // reset country code as it's not possible to have country and region selected this.countryCode.setValue(value, { emitEvent: false }); + // In case we switch from country to region + // remove previous geographic context country property inside the dashboard object + delete this.dashboard?.page?.geographicContext?.country; this.onContextChange(value, 'geographic'); }); this.countryCode.valueChanges @@ -232,6 +235,9 @@ export class DashboardComponent .subscribe((value) => { // reset region code as it's not possible to have country and region selected this.regionCode.setValue(value, { emitEvent: false }); + // In case we switch from region to country + // remove previous geographic context region property inside the dashboard object + delete this.dashboard?.page?.geographicContext?.region; this.onContextChange(value, 'geographic'); }); } @@ -965,9 +971,6 @@ export class DashboardComponent value: string | string[], geographicType: 'region' | 'country' ): void { - // In case we switch from region to country - // remove previous geographic context property inside the dashboard object - delete this.dashboard?.page?.geographicContext; const geographicContext: PageGeographicContextType = { enabled: true, ...(value && { [geographicType]: value }),