Skip to content

Ab#78019 changing the context filter to use the filter builder #2020

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

Open
wants to merge 19 commits into
base: alpha
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
faea5df
feat: creating shared filter on context filter interface, widget.
guisoares1 Oct 27, 2023
b22839d
feat: creating shared filter on context filter interface, widget.
guisoares1 Oct 27, 2023
2677376
feat: Creating filter and its helper methods on contextual filters se…
guisoares1 Oct 30, 2023
7d33cac
Merge branch 'beta' into AB#78019_Changing_the_context_filter_to_use_…
guisoares1 Oct 31, 2023
c554a55
feat: Created structure of how the new component will be called.
guisoares1 Oct 31, 2023
01a3b6b
feat: Correcting naming and logic errors.
guisoares1 Nov 1, 2023
fa324e5
feat: Created new component responsible for rendering the filter buil…
guisoares1 Nov 2, 2023
7554a3a
refactor: Improved code quality and removed unnecessary methods.
guisoares1 Nov 3, 2023
02d42b4
refactor: Improved code quality and removed unnecessary methods.
guisoares1 Nov 3, 2023
fba8ac4
Merge branch 'beta' into AB#78019_Changing_the_context_filter_to_use_…
guisoares1 Nov 6, 2023
442e687
feat: Modifications necessary for the filter to be saved, changed and…
guisoares1 Nov 7, 2023
129753c
From last commit.
guisoares1 Nov 7, 2023
baa493a
feat: Implemented the new parameter for all 'shared-contextual-filter…
guisoares1 Nov 7, 2023
1c1faad
Merge branch 'beta' into AB#78019_Changing_the_context_filter_to_use_…
guisoares1 Nov 7, 2023
47a1d21
fix: Fix syntax problems.
guisoares1 Nov 8, 2023
23e3f4f
feat: logic to set the dataFilter variable inside of contextual-filte…
guisoares1 Dec 7, 2023
5c3fb7c
fix: merge conflits with alpha.
guisoares1 Dec 7, 2023
05b8c7e
fix: Fixed some merge issues and finalized adjustments to centralize …
guisoares1 Dec 7, 2023
6655877
AB#78019_Changing_the_context_filter_to_use_the_filter_builder fix: a…
unai-reliefapp Dec 22, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@
</div>
</ng-container>
<ui-tabs *ngIf="form.getRawValue().name">
<ui-tab>
<ui-tab *ngIf="showFields">
<ng-container ngProjectAs="label">{{
'components.queryBuilder.fields.title' | translate
}}</ng-container>
Expand All @@ -92,7 +92,7 @@
></shared-tab-fields>
</ng-template>
</ui-tab>
<ui-tab *ngIf="form.get('sort')">
<ui-tab *ngIf="showSort && form.get('sort')">
<ng-container ngProjectAs="label">{{
(showLimit && form.get('first') !== null
? 'components.queryBuilder.sort.limitTitle'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ export class QueryBuilderComponent
@Input() showStyle = true;
@Input() showFilter = true;
@Input() showSort = true;
@Input() showFields = true;
/** Toggles the column width parameter */
@Input() showColumnWidth = false;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
<ng-template uiTabContent>
<shared-contextual-filters-settings
[form]="formGroup"
[resourceId]="resourceId"
></shared-contextual-filters-settings>
</ng-template>
</ui-tab>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,12 @@ export class ChartSettingsComponent
public types = CHART_TYPES;
/** Current chart type */
public type: any;
public dataFilter: any;

// === DISPLAY PREVIEW ===
public settings: any;
public grid: any;
public resourceId: any;

/** @returns the form for the chart */
public get chartForm(): UntypedFormGroup {
Expand All @@ -55,5 +61,6 @@ export class ChartSettingsComponent
.subscribe((value) => {
this.type = this.types.find((x) => x.name === value);
});
this.resourceId = this.formGroup.get('resource')?.value;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ <h2 class="flex">
</div>
</div>
<!-- Dashboard filter -->
<div class="flex-1 flex flex-col">
<div class="flex-1 flex flex-col" *ngIf="showFilterBuilder"> <!-- create a variable to control this-->
<h2 class="flex">
{{ 'models.dashboard.dashboardFilter' | translate
}}<ui-icon
Expand All @@ -29,13 +29,19 @@ <h2 class="flex">
[uiTooltip]="'models.dashboard.tooltip.filter.fields' | translate"
></ui-icon>
</h2>
<div class="grow overflow-y-auto overflow-x-hidden w-full">
<ngx-monaco-editor
class="!h-full min-h-[450px]"
(onInit)="initEditor($event)"
[options]="editorOptions"
[formControl]="$any(form.get('contextFilters'))"
></ngx-monaco-editor>
</div>
<ng-container ngProjectAs="content">
<ng-container *ngIf="!loading; else loadingTmpl">
<div class="flex flex-col">
<shared-filter-builder
[form]="$any(queryBuilderForm)"
></shared-filter-builder>
</div>
</ng-container>
<ng-template #loadingTmpl>
<div class="w-full h-full flex">
<ui-spinner class="my-auto mx-auto" [size]="'large'"></ui-spinner>
</div>
</ng-template>
</ng-container>
</div>
</div>
Original file line number Diff line number Diff line change
@@ -1,52 +1,167 @@
import { Component, Input } from '@angular/core';
import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
import { CommonModule } from '@angular/common';
import { MonacoEditorModule } from 'ngx-monaco-editor-v2';
import { FormGroup, FormsModule, ReactiveFormsModule } from '@angular/forms';
import {
FormControl,
FormGroup,
FormsModule,
ReactiveFormsModule,
} from '@angular/forms';
import { TranslateModule } from '@ngx-translate/core';
import { FormWrapperModule, IconModule, TooltipModule } from '@oort-front/ui';
import { QueryBuilderService } from '../../../../services/query-builder/query-builder.service';
import { QueryBuilderModule } from '../../../query-builder/query-builder.module';
import { SpinnerModule } from '@oort-front/ui';
import { Observable, takeUntil } from 'rxjs';
import { UnsubscribeComponent } from '../../../utils/unsubscribe/unsubscribe.component';
import { Apollo } from 'apollo-angular';
import { ResourceQueryResponse } from '../../../../models/resource.model';
import { GET_RESOURCE } from '../../editor-settings/graphql/queries';
import { FilterBuilderComponent } from './filter-builder/filter-builder.component';

/**
* Interface that describes the structure of the data shown in the dialog
*/
interface DialogData {
form: any;
resourceName: string;
}

/** Component to define the contextual filters of a widget or a map layer */
@Component({
selector: 'shared-contextual-filters-settings',
standalone: true,
templateUrl: './contextual-filters-settings.component.html',
styleUrls: ['./contextual-filters-settings.component.scss'],
imports: [
CommonModule,
MonacoEditorModule,
FormsModule,
ReactiveFormsModule,
TranslateModule,
FormWrapperModule,
IconModule,
TooltipModule,
QueryBuilderModule,
SpinnerModule,
FilterBuilderComponent,
],
templateUrl: './contextual-filters-settings.component.html',
styleUrls: ['./contextual-filters-settings.component.scss'],
})
export class ContextualFiltersSettingsComponent {
export class ContextualFiltersSettingsComponent
extends UnsubscribeComponent
implements OnInit
{
@Input() form!: FormGroup;
/** resource id used to get information of dataFilter */
@Input() resourceId!: any;
@Input() canExpand = true;

@Output() closeField: EventEmitter<boolean> = new EventEmitter();

public editorOptions = {
theme: 'vs-dark',
language: 'json',
fixedOverflowWidgets: true,
};
public dataFilter!: DialogData;
public filterFields: any[] = [];
public availableFields: any[] = [];
public filteredQueries: any[] = [];
public allQueries: any[] = [];
public query: any;
public showFilterBuilder = true;
public formChange = false;
public loading = true;
// === FIELD EDITION ===
public isField = false;
// === QUERY BUILDER ===
public availableQueries?: Observable<any[]>;
public queryBuilderForm?: FormGroup;

/**
* On initialization of editor, format code
* Getter for the available scalar fields
*
* @param editor monaco editor used for scss edition
* @returns the available scalar fields
*/
public initEditor(editor: any): void {
if (editor) {
setTimeout(() => {
editor
.getAction('editor.action.formatDocument')
.run()
.finally(() => {
const control = this.form.get('dashboardFilters');
control?.markAsPristine();
});
}, 100);
get availableScalarFields(): any[] {
return this.availableFields.filter(
(x) => x.type.kind === 'SCALAR' || x.type.kind === 'OBJECT'
);
// return this.availableFields.filter((x) => x.type.kind === 'SCALAR');
}

/**
* The constructor function is a special function that is called when a new instance of the class is
* created.
*
* @param queryBuilder The service used to build queries
* @param apollo Apollo client
*/
constructor(
private queryBuilder: QueryBuilderService,
private apollo: Apollo
) {
super();
}

ngOnInit() {
if (!this.resourceId) {
this.showFilterBuilder = false;
return;
}
this.setUpFilterForm();
}

/**
* Set custom editors for contextFilters.
*/
private updateForm(): void {
this.form
.get('contextFilters')
?.setValue(JSON.stringify(this.queryBuilderForm?.get('filter')?.value));
}

/**
* Updates the query builder form
*/
private updateQueryBuilderForm(): void {
this.queryBuilder.availableQueries$
.pipe(takeUntil(this.destroy$))
.subscribe(() => {
const hasDataForm = this.dataFilter.form !== null;
const queryName = this.queryBuilder.getQueryNameFromResourceName(
this.dataFilter.resourceName
);
this.queryBuilderForm = new FormGroup({
name: new FormControl(queryName),
filter: new FormControl(hasDataForm ? this.dataFilter.form : {}),
});
this.loading = false;
});

this.queryBuilderForm?.valueChanges
.pipe(takeUntil(this.destroy$))
.subscribe(() => {
this.updateForm();
});
}

/**
* Gets the data filter from the resource
*/
private setUpFilterForm() {
this.apollo
.query<ResourceQueryResponse>({
query: GET_RESOURCE,
variables: {
id: this.resourceId,
},
})
.subscribe(({ data }) => {
if (data.resource && data.resource.name) {
const nameTrimmed = data.resource.name
.replace(/\s/g, '')
.toLowerCase();
const formValue = this.form.get('contextFilters')?.value;
this.dataFilter = {
form: typeof formValue === 'string' ? JSON.parse(formValue) : null,
resourceName: nameTrimmed,
};
}
this.updateQueryBuilderForm();
});
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<shared-filter [form]="formUntyped" [fields]="filterFields"></shared-filter>
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';

import { FilterBuilderComponent } from './filter-builder.component';

describe('FilterBuilderComponent', () => {
let component: FilterBuilderComponent;
let fixture: ComponentFixture<FilterBuilderComponent>;

beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [FilterBuilderComponent],
}).compileComponents();

fixture = TestBed.createComponent(FilterBuilderComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});

it('should create', () => {
expect(component).toBeTruthy();
});
});
Loading