Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
fbca736
admin panel: refactor table view
lyubov-voloshko Aug 2, 2025
ad2ef97
saved filters:
lyubov-voloshko Aug 2, 2025
d84dc0f
saved filters: map saved filters into tabs
lyubov-voloshko Aug 2, 2025
bc94f8a
saved filters: apply filters when switch between saved filters
lyubov-voloshko Aug 2, 2025
e00bd7b
saved filters: refactor chips behavior, use id, show filter to edit
lyubov-voloshko Aug 3, 2025
d481bfc
saved filters: edit form for single filter
lyubov-voloshko Aug 3, 2025
9efc57a
saved filters:
lyubov-voloshko Aug 3, 2025
0d40c60
saved filters, edit dialog: pass foreign keys and fix foreign key field.
lyubov-voloshko Aug 4, 2025
3ea68b0
saved filters: add dynamic_column
lyubov-voloshko Aug 4, 2025
612a5ed
remove commented lines and consolelogs
lyubov-voloshko Aug 5, 2025
dbfc183
saved filters:
lyubov-voloshko Aug 6, 2025
16ab608
saved filters: hide active filters chips when saved filter is activated
lyubov-voloshko Aug 6, 2025
e254b3e
fix switching between filters, saved filters and search
lyubov-voloshko Aug 9, 2025
88736e2
saved filters: read dynamic field from url params correctly
lyubov-voloshko Aug 9, 2025
6b8e9c2
table view: use route.snapshot in setTable to avoid subscription
lyubov-voloshko Aug 9, 2025
95f9309
saved filters panel: add paramMap subscription to update saved filtes…
lyubov-voloshko Aug 9, 2025
ebc0cd2
saved filter:
lyubov-voloshko Aug 9, 2025
fec3e7e
saved filters: update list on add and delete
lyubov-voloshko Aug 9, 2025
949da92
saved filters: element visibility diponding on access level
lyubov-voloshko Aug 9, 2025
0e5f9b5
saved filters: subscription on saved_filter param and deselect saved …
lyubov-voloshko Aug 10, 2025
7b8061f
Merge branch 'main' into saved-filters-2
lyubov-voloshko Aug 10, 2025
a823242
Merge branch 'main' into saved-filters-2
lyubov-voloshko Aug 10, 2025
3d949cb
fix pathes after merge with main
lyubov-voloshko Aug 11, 2025
f4bf785
saved filter: update filters list on update filters, fix saved filter…
lyubov-voloshko Aug 11, 2025
288a4c1
saved filters: errors into snakbar
lyubov-voloshko Aug 11, 2025
c18927d
saved filters panel: fix styles
lyubov-voloshko Aug 13, 2025
5b0b08b
saved filters: debounce and update table on dynamic filter value change
lyubov-voloshko Aug 13, 2025
bc96ab0
saved filters: fix structure passing
lyubov-voloshko Aug 13, 2025
4fa278e
saved filter: fix styles
lyubov-voloshko Aug 13, 2025
b9428a5
saved filters: update url if editing currently applied filter
lyubov-voloshko Aug 13, 2025
2b0c41d
saved filters: fix unit tests
lyubov-voloshko Aug 13, 2025
519f2f9
Merge branch 'main' into saved-filters-2
lyubov-voloshko Aug 13, 2025
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
7 changes: 3 additions & 4 deletions frontend/src/app/app-routing.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,10 @@ import { ConnectDBComponent } from './components/connect-db/connect-db.component
import { ConnectionSettingsComponent } from './components/connection-settings/connection-settings.component';
import { ConnectionsListComponent } from './components/connections-list/connections-list.component';
import { DashboardComponent } from './components/dashboard/dashboard.component'
import { DbTableActionsComponent } from './components/dashboard/db-table-actions/db-table-actions.component';
import { DbTableComponent } from './components/dashboard/db-table/db-table.component';
import { DbTableActionsComponent } from './components/dashboard/db-table-view/db-table-actions/db-table-actions.component';
import { DbTableRowEditComponent } from './components/db-table-row-edit/db-table-row-edit.component';
import { DbTableSettingsComponent } from './components/dashboard/db-table-settings/db-table-settings.component';
import { DbTableWidgetsComponent } from './components/dashboard/db-table-widgets/db-table-widgets.component';
import { DbTableSettingsComponent } from './components/dashboard/db-table-view/db-table-settings/db-table-settings.component';
import { DbTableWidgetsComponent } from './components/dashboard/db-table-view/db-table-widgets/db-table-widgets.component';
import { EmailChangeComponent } from './components/email-change/email-change.component';
import { EmailVerificationComponent } from './components/email-verification/email-verification.component';
import { LoginComponent } from './components/login/login.component';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ <h3 class='mat-subheading-2'>Rocketadmin can not find any tables</h3>
</div>

<app-content-loader *ngIf="dataSource === null"></app-content-loader>
<app-db-table *ngIf="dataSource"
<app-db-table-view *ngIf="dataSource"
[displayName]="selectedTableDisplayName"
[activeFilters]="filters"
[filterComparators]="comparators"
Expand All @@ -89,8 +89,9 @@ <h3 class='mat-subheading-2'>Rocketadmin can not find any tables</h3>
(removeFilter)="removeFilter($event)"
(resetAllFilters)="clearAllFilters()"
(search)="search($event)"
(activateActions)="activateActions($event)">
</app-db-table>
(activateActions)="activateActions($event)"
(applyFilter)="applyFilter($event)">
</app-db-table-view>
</div>
<app-db-table-row-view *ngIf="selectedRow"
[activeFilters]="filters"
Expand Down
71 changes: 48 additions & 23 deletions frontend/src/app/components/dashboard/dashboard.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,16 @@ import { first, map } from 'rxjs/operators';

import { AlertComponent } from '../ui-components/alert/alert.component';
import { BannerComponent } from '../ui-components/banner/banner.component';
import { BbBulkActionConfirmationDialogComponent } from './db-bulk-action-confirmation-dialog/db-bulk-action-confirmation-dialog.component';
import { BbBulkActionConfirmationDialogComponent } from './db-table-view/db-bulk-action-confirmation-dialog/db-bulk-action-confirmation-dialog.component';
import { CommonModule } from '@angular/common';
import { CompanyService } from 'src/app/services/company.service';
import { ConnectionsService } from 'src/app/services/connections.service';
import { ContentLoaderComponent } from '../ui-components/content-loader/content-loader.component';
import { DbActionLinkDialogComponent } from './db-action-link-dialog/db-action-link-dialog.component';
import { DbTableAiPanelComponent } from './db-table-ai-panel/db-table-ai-panel.component';
import { DbTableComponent } from './db-table/db-table.component';
import { DbTableFiltersDialogComponent } from './db-table-filters-dialog/db-table-filters-dialog.component';
import { DbTableRowViewComponent } from './db-table-row-view/db-table-row-view.component';
import { DbActionLinkDialogComponent } from './db-table-view/db-action-link-dialog/db-action-link-dialog.component';
import { DbTableAiPanelComponent } from './db-table-view/db-table-ai-panel/db-table-ai-panel.component';
import { DbTableFiltersDialogComponent } from './db-table-view/db-table-filters-dialog/db-table-filters-dialog.component';
import { DbTableRowViewComponent } from './db-table-view/db-table-row-view/db-table-row-view.component';
import { DbTableViewComponent } from './db-table-view/db-table-view.component';
import { DbTablesListComponent } from './db-tables-list/db-tables-list.component';
import { HttpErrorResponse } from '@angular/common/http';
import JsonURL from "@jsonurl/jsonurl";
Expand Down Expand Up @@ -58,7 +58,7 @@ interface DataToActivateActions {
MatDialogModule,
MatSidenavModule,
DbTablesListComponent,
DbTableComponent,
DbTableViewComponent,
DbTableAiPanelComponent,
DbTableRowViewComponent,
AlertComponent,
Expand Down Expand Up @@ -151,6 +151,7 @@ export class DashboardComponent implements OnInit, OnDestroy {
this.shownTableTitles = settings?.connections[this.connectionID]?.shownTableTitles ?? true;

this.getData();
console.log('getData from ngOnInit');
});
}

Expand All @@ -159,6 +160,7 @@ export class DashboardComponent implements OnInit, OnDestroy {
}

async getData() {
console.log('getData');
let tables;
try {
tables = await this.getTables();
Expand All @@ -185,6 +187,7 @@ export class DashboardComponent implements OnInit, OnDestroy {
if (tableName) {
this.selectedTableName = tableName;
this.setTable(tableName);
console.log('setTable from getData paramMap');
this.title.setTitle(`${this.selectedTableDisplayName} table | ${this._company.companyTabTitle || 'Rocketadmin'}`);
this.selection.clear();
} else {
Expand All @@ -201,12 +204,14 @@ export class DashboardComponent implements OnInit, OnDestroy {
this._tableRow.cast.subscribe((arg) => {
if (arg === 'delete row' && this.selectedTableName) {
this.setTable(this.selectedTableName);
console.log('setTable from getData _tableRow cast');
this.selection.clear();
};
});
this._tables.cast.subscribe((arg) => {
if ((arg === 'delete rows' || arg === 'import') && this.selectedTableName) {
this.setTable(this.selectedTableName);
console.log('setTable from getData _tables cast');
this.selection.clear();
};
if (arg === 'activate actions') {
Expand All @@ -217,6 +222,7 @@ export class DashboardComponent implements OnInit, OnDestroy {
}

getTables() {
console.log('getTables');
return this._tables.fetchTables(this.connectionID).toPromise();
}

Expand All @@ -243,17 +249,17 @@ export class DashboardComponent implements OnInit, OnDestroy {

setTable(tableName: string) {
this.selectedTableName = tableName;
this.route.queryParams.pipe(first()).subscribe((queryParams) => {
this.filters = JsonURL.parse( queryParams.filters );
this.comparators = getComparatorsFromUrl(this.filters);
this.pageIndex = parseInt(queryParams.page_index) || 0;
this.pageSize = parseInt(queryParams.page_size) || 30;
this.sortColumn = queryParams.sort_active;
this.sortOrder = queryParams.sort_direction;

const search = queryParams.search;
this.getRows(search);
})
const queryParams = this.route.snapshot.queryParams;
this.filters = JsonURL.parse(queryParams.filters);
this.comparators = getComparatorsFromUrl(this.filters);
this.pageIndex = parseInt(queryParams.page_index) || 0;
this.pageSize = parseInt(queryParams.page_size) || 30;
this.sortColumn = queryParams.sort_active;
this.sortOrder = queryParams.sort_direction;

const search = queryParams.search;
this.getRows(search);
console.log('getRows from setTable');

const selectedTableProperties = this.tablesList.find( (table: any) => table.table == this.selectedTableName);
if (selectedTableProperties) {
Expand All @@ -279,21 +285,27 @@ export class DashboardComponent implements OnInit, OnDestroy {
if (action === 'filter') {
const filtersFromDialog = {...filterDialodRef.componentInstance.tableRowFieldsShown};

console.log('Filters from dialog:', filtersFromDialog);

const nonEmptyFilters = omitBy(filtersFromDialog, (value) => value === undefined);
this.comparators = filterDialodRef.componentInstance.tableRowFieldsComparator;

if (Object.keys(nonEmptyFilters).length) {
this.filters = {};
for (const key in nonEmptyFilters) {
if (this.comparators[key] !== undefined) {
this.filters[key] = {
[this.comparators[key]]: nonEmptyFilters[key]
};
}
if (this.comparators[key] !== undefined) {
this.filters[key] = {
[this.comparators[key]]: nonEmptyFilters[key]
};
}
}

console.log('Filters to apply:', this.filters);

const filters = JsonURL.stringify( this.filters );

console.log('Filters to navigate:', filters);

this.router.navigate([`/dashboard/${this.connectionID}/${this.selectedTableName}`], {
queryParams: {
filters,
Expand All @@ -302,6 +314,8 @@ export class DashboardComponent implements OnInit, OnDestroy {
}
});
this.getRows();
console.log('getRows from afterClosed');


this.angulartics2.eventTrack.next({
action: 'Dashboard: filter is applied',
Expand All @@ -310,6 +324,7 @@ export class DashboardComponent implements OnInit, OnDestroy {
} else if (action === 'reset') {
this.filters = {};
this.getRows();
console.log('getRows from reset filters afterClosed');
this.router.navigate([`/dashboard/${this.connectionID}/${this.selectedTableName}`]);
}
})
Expand All @@ -324,6 +339,7 @@ export class DashboardComponent implements OnInit, OnDestroy {
this.selection.clear();

this.getRows();
console.log('getRows from removeFilter');
this.router.navigate([`/dashboard/${this.connectionID}/${this.selectedTableName}`], {
queryParams: {
filters,
Expand All @@ -337,6 +353,7 @@ export class DashboardComponent implements OnInit, OnDestroy {
this.filters = {};
this.comparators = {};
this.getRows();
console.log('getRows from clearAllFilters');
this.router.navigate([`/dashboard/${this.connectionID}/${this.selectedTableName}`], {
queryParams: {
page_index: 0,
Expand All @@ -347,6 +364,7 @@ export class DashboardComponent implements OnInit, OnDestroy {

search(value: string) {
this.getRows(value);
console.log('getRows from search');
this.filters = {};
this.router.navigate([`/dashboard/${this.connectionID}/${this.selectedTableName}`], {
queryParams: {
Expand All @@ -358,6 +376,7 @@ export class DashboardComponent implements OnInit, OnDestroy {
}

getRows(search?: string) {
console.log('getRows, filters:', this.filters);
this._uiSettings.getUiSettings()
.subscribe ((settings: UiSettings) => {
this.uiSettings = settings?.connections[this.connectionID];
Expand All @@ -376,7 +395,13 @@ export class DashboardComponent implements OnInit, OnDestroy {
shownColumns
});
});
}

applyFilter(filters: any) {
console.log('applyFilter with filters:', filters);
this.filters = filters?.filters;
this.getRows();
console.log('getRows from applyFilter');
}

openIntercome() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,18 @@ import { Component, OnInit } from '@angular/core';
import { CustomAction, CustomActionMethod, CustomActionType, CustomEvent, EventType, Rule } from 'src/app/models/table';

import { ActionDeleteDialogComponent } from './action-delete-dialog/action-delete-dialog.component';
import { AlertComponent } from '../../ui-components/alert/alert.component';
import { BreadcrumbsComponent } from '../../ui-components/breadcrumbs/breadcrumbs.component';
import { AlertComponent } from '../../../ui-components/alert/alert.component';
import { BreadcrumbsComponent } from '../../../ui-components/breadcrumbs/breadcrumbs.component';
import { ClipboardModule } from '@angular/cdk/clipboard';
import { CodeEditorModule } from '@ngstack/code-editor';
import { CommonModule } from '@angular/common';
import { CompanyMember } from 'src/app/models/company';
import { CompanyService } from 'src/app/services/company.service';
import { ConnectionsService } from 'src/app/services/connections.service';
import { ContentLoaderComponent } from '../../ui-components/content-loader/content-loader.component';
import { ContentLoaderComponent } from '../../../ui-components/content-loader/content-loader.component';
import { FormsModule } from '@angular/forms';
import { HttpErrorResponse } from '@angular/common/http';
import { IconPickerComponent } from '../../ui-components/icon-picker/icon-picker.component';
import { IconPickerComponent } from '../../../ui-components/icon-picker/icon-picker.component';
import { MatButtonModule } from '@angular/material/button';
import { MatCheckboxModule } from '@angular/material/checkbox';
import { MatDialog } from '@angular/material/dialog';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import JsonURL from "@jsonurl/jsonurl";
import { DynamicModule } from 'ng-dynamic-component';
import { RouterModule } from '@angular/router';
import { MatDialogModule } from '@angular/material/dialog';
import { ContentLoaderComponent } from '../../ui-components/content-loader/content-loader.component';
import { ContentLoaderComponent } from '../../../ui-components/content-loader/content-loader.component';
import { Angulartics2OnModule } from 'angulartics2';

@Component({
Expand Down Expand Up @@ -92,19 +92,33 @@ export class DbTableFiltersDialogComponent implements OnInit {
}));

const queryParams = this.route.snapshot.queryParams;
const filters = JsonURL.parse(queryParams.filters);
const filtersValues = getFiltersFromUrl(filters);

if (Object.keys(filtersValues).length) {
this.tableFilters = Object.keys(filtersValues).map(key => key);
this.tableRowFieldsShown = filtersValues;
this.tableRowFieldsComparator = getComparatorsFromUrl(filters);
// If saved_filter is present in queryParams, show empty form without applying filters
if (queryParams.saved_filter) {
// Show empty form without filters
this.tableFilters = [];
this.tableRowFieldsShown = {};
this.tableRowFieldsComparator = {};
} else {
const fieldsToSearch = this.data.structure.structure.filter((field: TableField) => field.isSearched);
if (fieldsToSearch.length) {
this.tableFilters = fieldsToSearch.map((field:TableField) => field.column_name);
this.tableRowFieldsShown = Object.assign({}, ...fieldsToSearch.map((field: TableField) => ({[field.column_name]: undefined})));
this.tableRowFieldsComparator = Object.assign({}, ...fieldsToSearch.map((field: TableField) => ({[field.column_name]: 'eq'})));
// Original behavior - parse and apply filters from URL
let filters = {};
if (queryParams.filters) filters = JsonURL.parse(queryParams.filters);
// const filters = JsonURL.parse(queryParams.filters || '{}');
const filtersValues = getFiltersFromUrl(filters);

console.log('Parsed filters from URL:', filtersValues);

if (Object.keys(filtersValues).length) {
this.tableFilters = Object.keys(filtersValues).map(key => key);
this.tableRowFieldsShown = filtersValues;
this.tableRowFieldsComparator = getComparatorsFromUrl(filters);
} else {
const fieldsToSearch = this.data.structure.structure.filter((field: TableField) => field.isSearched);
if (fieldsToSearch.length) {
this.tableFilters = fieldsToSearch.map((field:TableField) => field.column_name);
this.tableRowFieldsShown = Object.assign({}, ...fieldsToSearch.map((field: TableField) => ({[field.column_name]: undefined})));
this.tableRowFieldsComparator = Object.assign({}, ...fieldsToSearch.map((field: TableField) => ({[field.column_name]: 'eq'})));
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,13 @@ import { MatListModule } from '@angular/material/list';
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
import { MatTooltipModule } from '@angular/material/tooltip';
import { NotificationsService } from 'src/app/services/notifications.service';
import { PlaceholderRecordViewComponent } from '../../skeletons/placeholder-record-view/placeholder-record-view.component';
import { PlaceholderRecordViewComponent } from '../../../skeletons/placeholder-record-view/placeholder-record-view.component';
import { TableStateService } from 'src/app/services/table-state.service';
import { TablesService } from 'src/app/services/tables.service';
import { formatFieldValue } from 'src/app/lib/format-field-value';
import { ForeignKeyRecordViewComponent } from '../../ui-components/record-view-fields/foreign-key/foreign-key.component';
import { UIwidgets, recordViewFieldTypes } from 'src/app/consts/record-view-types';
import { DynamicModule } from 'ng-dynamic-component';
import { ForeignKeyRecordViewComponent } from 'src/app/components/ui-components/record-view-fields/foreign-key/foreign-key.component';

@Component({
selector: 'app-db-table-row-view',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,31 +2,31 @@ import {CdkDragDrop, moveItemInArray} from '@angular/cdk/drag-drop';
import { Component, Inject, OnInit } from '@angular/core';
import { TableField, TableOrdering, TableSettings } from 'src/app/models/table';

import { AlertComponent } from '../../ui-components/alert/alert.component';
import { AlertComponent } from '../../../ui-components/alert/alert.component';
import { Angulartics2 } from 'angulartics2';
import { BreadcrumbsComponent } from '../../ui-components/breadcrumbs/breadcrumbs.component';
import { BreadcrumbsComponent } from '../../../ui-components/breadcrumbs/breadcrumbs.component';
import { CommonModule } from '@angular/common';
import { CompanyService } from 'src/app/services/company.service';
import { ConnectionsService } from 'src/app/services/connections.service';
import { DragDropModule } from '@angular/cdk/drag-drop';
import { FormsModule } from '@angular/forms';
import { IconPickerComponent } from '../../ui-components/icon-picker/icon-picker.component';
import { IconPickerComponent } from '../../../ui-components/icon-picker/icon-picker.component';
import { Location } from '@angular/common';
import { MatButtonModule } from '@angular/material/button';
import { MatExpansionModule } from '@angular/material/expansion';
import { MatFormFieldModule } from '@angular/material/form-field';
import { MatIconModule } from '@angular/material/icon';
import { MatInputModule } from '@angular/material/input';
import { MatRadioModule } from '@angular/material/radio';
import { MatSelectModule } from '@angular/material/select';
import { MatSlideToggleModule } from '@angular/material/slide-toggle';
import { NgForm } from '@angular/forms';
import { PlaceholderTableSettingsComponent } from '../../skeletons/placeholder-table-settings/placeholder-table-settings.component';
import { PlaceholderTableSettingsComponent } from '../../../skeletons/placeholder-table-settings/placeholder-table-settings.component';
import { Router } from '@angular/router';
import { RouterModule } from '@angular/router';
import { TablesService } from 'src/app/services/tables.service';
import { Title } from '@angular/platform-browser';
import { normalizeTableName } from 'src/app/lib/normalize';
import { MatButtonModule } from '@angular/material/button';
import { MatSlideToggleModule } from '@angular/material/slide-toggle';
import { CompanyService } from 'src/app/services/company.service';

@Component({
selector: 'app-db-table-settings',
Expand Down
Loading