Repository navigation
[NAE-2487] Add Column Configuration and Sorting to Menu Item #359
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
base: release/7.1.0
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,40 @@ | ||
| import {HeaderColumn, HeaderColumnType} from "./header-column"; | ||
| import {CaseMetaField} from "../case-header/case-menta-enum"; | ||
| import {TaskMetaField} from "../task-header/task-meta-enum"; | ||
| import {WorkflowMetaField} from "../workflow-header/workflow-meta-enum"; | ||
|
|
||
| /** Returns meta-headers for case view */ | ||
| export function getCaseMetaHeaders(): HeaderColumn[] { | ||
| return [ | ||
| new HeaderColumn(HeaderColumnType.META, CaseMetaField.VISUAL_ID, 'headers.caseMeta.visualID', 'text'), | ||
| new HeaderColumn(HeaderColumnType.META, CaseMetaField.MONGO_ID, 'headers.caseMeta.mongoID', 'text', false), | ||
| new HeaderColumn(HeaderColumnType.META, CaseMetaField.TITLE, 'headers.caseMeta.title', 'text'), | ||
| new HeaderColumn(HeaderColumnType.META, CaseMetaField.AUTHOR, 'headers.caseMeta.author', 'user'), | ||
| new HeaderColumn(HeaderColumnType.META, CaseMetaField.CREATION_DATE, 'headers.caseMeta.creationDate', 'date') | ||
| ]; | ||
| } | ||
|
|
||
| /** Returns meta-headers for task view */ | ||
| export function getTaskMetaHeaders(): HeaderColumn[] { | ||
| return [ | ||
| new HeaderColumn(HeaderColumnType.META, TaskMetaField.CASE, 'headers.taskMeta.case', 'text'), | ||
| new HeaderColumn(HeaderColumnType.META, TaskMetaField.CASE_ID, 'headers.taskMeta.caseID', 'text', false), | ||
| new HeaderColumn(HeaderColumnType.META, TaskMetaField.TASK_ID, 'headers.taskMeta.taskID', 'text', false), | ||
| new HeaderColumn(HeaderColumnType.META, TaskMetaField.TITLE, 'headers.caseMeta.title', 'text'), | ||
| new HeaderColumn(HeaderColumnType.META, TaskMetaField.PRIORITY, 'headers.taskMeta.priority', 'enumeration'), | ||
| new HeaderColumn(HeaderColumnType.META, TaskMetaField.USER, 'headers.taskMeta.user', 'text'), | ||
| new HeaderColumn(HeaderColumnType.META, TaskMetaField.ASSIGN_DATE, 'headers.taskMeta.assignDate', 'date'), | ||
| ]; | ||
| } | ||
|
|
||
| /** Returns meta-headers for workflow view */ | ||
| export function getWorkflowMetaHeaders(): HeaderColumn[] { | ||
| return [ | ||
| new HeaderColumn(HeaderColumnType.META, WorkflowMetaField.INITIALS, 'headers.workflowMeta.initials', 'text'), | ||
| new HeaderColumn(HeaderColumnType.META, WorkflowMetaField.TITLE, 'headers.workflowMeta.title', 'text'), | ||
| new HeaderColumn(HeaderColumnType.META, WorkflowMetaField.NET_ID, 'headers.workflowMeta.netId', 'text', false), | ||
| new HeaderColumn(HeaderColumnType.META, WorkflowMetaField.VERSION, 'headers.workflowMeta.version', 'text'), | ||
| new HeaderColumn(HeaderColumnType.META, WorkflowMetaField.AUTHOR, 'headers.workflowMeta.author', 'text'), | ||
| new HeaderColumn(HeaderColumnType.META, WorkflowMetaField.CREATION_DATE, 'headers.workflowMeta.creationDate', 'date'), | ||
| ]; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,4 @@ | ||
| import {InjectionToken} from '@angular/core'; | ||
| import {SortChangeDescription} from '../../../header/models/user-changes/sort-change-description'; | ||
|
|
||
| export const NAE_DYNAMIC_DEFAULT_SORT = new InjectionToken<Array<SortChangeDescription[]>>('NaeDynamicDefaultSort'); | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,13 +1,13 @@ | ||
| import {Inject, Injectable, OnDestroy, Optional} from '@angular/core'; | ||
| import {CaseResourceService} from '../../../resources/engine-endpoint/case-resource.service'; | ||
| import {BehaviorSubject, Observable, of, Subject} from 'rxjs'; | ||
| import {ReplaySubject, Observable, of, Subject} from 'rxjs'; | ||
| import {HttpParams} from '@angular/common/http'; | ||
| import {Case} from '../../../resources/interface/case'; | ||
| import {LoggerService} from '../../../logger/services/logger.service'; | ||
| import {SnackBarService} from '../../../snack-bar/services/snack-bar.service'; | ||
| import {SearchService} from '../../../search/search-service/search.service'; | ||
| import {TranslateService} from '@ngx-translate/core'; | ||
| import {catchError, concatMap, filter, map, mergeMap, scan, switchMap, tap} from 'rxjs/operators'; | ||
| import {catchError, concatMap, filter, map, mergeMap, scan, switchMap, take, tap} from 'rxjs/operators'; | ||
| import {Pagination} from '../../../resources/interface/pagination'; | ||
| import {CaseMetaField} from '../../../header/case-header/case-menta-enum'; | ||
| import {PageLoadRequestContext} from '../../abstract/page-load-request-context'; | ||
|
|
@@ -37,6 +37,8 @@ | |
| import {createSortParam, PaginationSort} from '../../../utility/pagination/pagination-sort'; | ||
| import {MatDialog} from '@angular/material/dialog'; | ||
| import {NAE_NEW_CASE_DIALOG_COMPONENT} from '../../../dialog/injection-tokens'; | ||
| import {NAE_DYNAMIC_DEFAULT_SORT} from '../models/dynamic-default-sort-token'; | ||
| import {SortChangeDescription} from '../../../header/models/user-changes/sort-change-description'; | ||
|
|
||
| @Injectable() | ||
| export class CaseViewService extends AbstractSortableViewComponent implements OnDestroy { | ||
|
|
@@ -47,7 +49,7 @@ | |
|
|
||
| protected _loading$: LoadingWithFilterEmitter; | ||
| protected _cases$: Observable<Array<Case>>; | ||
| protected _nextPage$: BehaviorSubject<PageLoadRequestContext>; | ||
| protected _nextPage$: ReplaySubject<PageLoadRequestContext>; | ||
| protected _endOfData: boolean; | ||
| protected _pagination: Pagination; | ||
| protected _newCaseConfiguration: NewCaseConfiguration; | ||
|
|
@@ -64,6 +66,7 @@ | |
| protected _processService: ProcessService, | ||
| resolver: SearchIndexResolverService, | ||
| @Optional() @Inject(NAE_NEW_CASE_DIALOG_COMPONENT) protected _newCaseComponent: any, | ||
| @Optional() @Inject(NAE_DYNAMIC_DEFAULT_SORT) protected _dynamicDefaultSort$: Observable<SortChangeDescription[]>, | ||
| @Optional() @Inject(NAE_NEW_CASE_CONFIGURATION) newCaseConfig: NewCaseConfiguration, | ||
| protected _permissionService: PermissionService) { | ||
| super(resolver); | ||
|
|
@@ -82,9 +85,8 @@ | |
| totalPages: undefined, | ||
| number: -1 | ||
| }; | ||
| this._nextPage$ = new BehaviorSubject<PageLoadRequestContext>( | ||
| new PageLoadRequestContext(this.activeFilter, Object.assign({}, this._pagination, {number: 0})) | ||
| ); | ||
| this._nextPage$ = new ReplaySubject<PageLoadRequestContext>(1); | ||
| this.requestPageWithDynamicSort(new PageLoadRequestContext(this.activeFilter, Object.assign({}, this._pagination, {number: 0}))); | ||
|
Check warning on line 89 in projects/netgrif-components-core/src/lib/view/case-view/service/case-view-service.ts
|
||
|
|
||
| const casesMap = this._nextPage$.pipe( | ||
| mergeMap(p => this.loadPage(p)), | ||
|
|
@@ -213,7 +215,7 @@ | |
| if (this.isLoadingRelevantFilter(requestContext) || this._endOfData) { | ||
| return; | ||
| } | ||
| this._nextPage$.next(requestContext); | ||
| this.requestPageWithDynamicSort(requestContext); | ||
| } | ||
|
|
||
| private isLoadingRelevantFilter(requestContext?: PageLoadRequestContext): boolean { | ||
|
|
@@ -228,7 +230,7 @@ | |
| const dialogRef = this._dialog.open(this._newCaseComponent, { | ||
| width: '40%', | ||
| minWidth: '300px', | ||
| panelClass: "dialog-responsive", | ||
| panelClass: 'dialog-responsive', | ||
| data: { | ||
| allowedNets$: this.getNewCaseAllowedNets(newCaseCreationConfiguration.blockNets), | ||
| newCaseCreationConfiguration | ||
|
|
@@ -358,4 +360,31 @@ | |
| public viewEnabled(aCase: Case): boolean { | ||
| return this._permissionService.hasCasePermission(aCase, PermissionType.VIEW); | ||
| } | ||
|
|
||
| // todo check header sort resolving, this seems not user friendly + probably won't work with userPreferences | ||
|
Check warning on line 364 in projects/netgrif-components-core/src/lib/view/case-view/service/case-view-service.ts
|
||
| protected requestPageWithDynamicSort(requestContext: PageLoadRequestContext) { | ||
| if (!!this._dynamicDefaultSort$ | ||
| && this._lastHeaderSearchState.fieldIdentifier === '' | ||
| && this._preferredSortableHeaders.length === 0) { | ||
| this._dynamicDefaultSort$.pipe(take(1)).subscribe(changes => { | ||
| if (this._preferredSortableHeaders.length === 0) { | ||
| this._lastHeaderSearchState.sortDirection = ''; | ||
| changes.forEach( | ||
| change => this._preferredSortableHeaders.push( | ||
| { | ||
| propertyId: this.getPreferredSortableFieldIdByFieldIdentifier(change.fieldIdentifier, change.columnType, change.fieldType), | ||
| sortDirection: change.sortDirection | ||
| } | ||
| )); | ||
| } | ||
|
Comment on lines
+366
to
+379
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win 🔎 Supported by static analysis🏁 Script executed: #!/bin/bash
rg -n -C4 '_preferredSortableHeaders' projects/netgrif-components-core/src/lib/view/abstract/sortable-view.tsRepository: netgrif/components Length of output: 2040 🏁 Script executed: #!/bin/bash
set -o pipefail
printf '%s\n' '--- abstract sortable view ---'
nl -ba projects/netgrif-components-core/src/lib/view/abstract/sortable-view.ts | sed -n '1,125p'
printf '%s\n' '--- case view service relevant symbols ---'
rg -n -C8 --glob '*.ts' 'registerHeaderChange|registerPreferredSortableHeaders|requestPageWithDynamicSort|_preferredSortableHeaders|_lastHeaderSearchState' projects/netgrif-components-core/src/lib/view/case-view/service/case-view-service.ts projects/netgrif-components-core/src/lib/viewRepository: netgrif/components Length of output: 42081 🏁 Script executed: #!/bin/bash
set -o pipefail
printf '%s\n' '--- sort change model ---'
rg -n -C6 --glob '*.ts' 'interface SortChangeDescription|class SortChangeDescription|type SortChangeDescription|SortChangeDescription' projects/netgrif-components-core/src/lib/header
printf '%s\n' '--- sort direction producers ---'
rg -n -C5 --glob '*.ts' 'sortDirection:|SortChangeDescription|HeaderChangeType.SORT' projects/netgrif-components-core/src/lib/header projects/netgrif-components-core/src/lib/view | head -240Repository: netgrif/components Length of output: 35917 Clear preferred sorts when handling a sort change.
🐛 Suggested fix if (header.changeType === HeaderChangeType.SORT) {
+ this._preferredSortableHeaders = [];
this._lastHeaderSearchState = header.description as SortChangeDescription;
}🤖 Prompt for AI Agents |
||
| this.requestNextPage(requestContext); | ||
| }); | ||
| } else { | ||
| this.requestNextPage(requestContext); | ||
| } | ||
| } | ||
|
coderabbitai[bot] marked this conversation as resolved.
|
||
|
|
||
| protected requestNextPage(page: PageLoadRequestContext) { | ||
| this._nextPage$.next(page); | ||
| } | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🗄️ Data Integrity & Integration | 🟡 Minor | ⚡ Quick win
Fix the token type to match the provided and injected value.
The token is declared as
InjectionToken<Array<SortChangeDescription[]>>. The factories provideObservable<SortChangeDescription[]> | undefined.CaseViewServiceandTaskViewServiceinjectObservable<SortChangeDescription[]>. The declared type matches neither the producer nor the consumers. This hides type errors at the provider and injection sites. Declare the token as anObservableofSortChangeDescription[]. This is a duplicate of the earlier review comment, which still applies to the current code.♻️ Proposed fix
Add this import at the top of the file:
+import {Observable} from 'rxjs';🤖 Prompt for AI Agents