Skip to content

Commit

Permalink
feat: search config slot in search header and column group slot in in…
Browse files Browse the repository at this point in the history
…teractive-data-view (#369)

* feat: slot passes down inputs and outputs

* feat: update remote components inputs and outputs

* feat: change type of emitters

* feat: slot used in search header

* feat: correct prop passing not optimised

* feat: emitter column type change

* feat: column group slot + search-config slot adjustment

* fix: removed redundant sub

* feat: viewMode passing added

* feat: added search config topic

* feat: formgroup viewchild prep

* feat: prop passing adjustments

* feat: default column group and bug fixes

* refactor: comment out unused code

* feat: removed pageName and search header comment

* feat: disable search button when form is invalid

* refactor: removed not needed log

* feat: removed topic

* feat: lowered debounce time

* feat: allow undefined in config selection changed

* feat: search header passes visible values only

* feat: added skeletons for slots

* feat: display search config slot only if client observes config changes

* feat: tests for search header and interactive data view

* feat: search header state changed on selected search config

* fix: fix interactive data view tests

* refactor: lint

* fix: fix data table reload

* feat: interactive data view adjustments to correctly choose columns

* feat: add layout as input for search config slot

* feat: correct reinit of column group selection remtoe component

* refactor: lint

* feat: permission directive adjusted and permissions for slot displaying added

* feat: search header and interactive data view params change, guard for pageName in search header and interactive data view slot always active

* fix: tests fixed

* feat: saving only search config name in search header state

* feat: provide slot service token in module instead of component

* feat: slot error on slot service

* fix: lint

* fix: lint

* feat: remote translate loader with mfe translations

* feat: SLOT_SERVICE provided in remote components module

* fix: group selection change async

* feat: pageName default and search config selection change emitters split

* fix: async behavior in layout change sub

* refactor: changed name of translate loader

* feat: dropdown harness update

* feat: slot-service mock in angular remote components

* feat: emitter now use types

* fix: fixed slot hiding mechanism

* feat: search-config cleanup

* fix: lint fixes
  • Loading branch information
markuczy authored Oct 7, 2024
1 parent b1984ed commit bbf7073
Show file tree
Hide file tree
Showing 41 changed files with 458 additions and 589 deletions.
4 changes: 1 addition & 3 deletions libs/angular-accelerator/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,12 @@ export * from './lib/components/diagram/diagram.component'
export * from './lib/components/group-by-count-diagram/group-by-count-diagram.component'
export * from './lib/components/interactive-data-view/interactive-data-view.component'
export * from './lib/components/page-header/page-header.component'
export * from './lib/components/search-config/search-config.component'
export * from './lib/components/search-header/search-header.component'
export * from './lib/components/data-loading-error/data-loading-error.component'

// services
export * from './lib/services/breadcrumb.service'
export * from './lib/services/translation-cache.service'
export * from './lib/services/app-config-service'

// pipes
export * from './lib/pipes/dynamic.pipe'
Expand All @@ -40,7 +38,6 @@ export * from './lib/model/data-table-column.model'
export * from './lib/model/diagram-column'
// export * from './lib/model/diagram-data'
export * from './lib/model/diagram-type'
export * from './lib/model/search-config-info'

// core
export * from './lib/angular-accelerator.module'
Expand All @@ -59,6 +56,7 @@ export * from './lib/utils/dateutils'
export * from './lib/utils/objectutils'
export * from './lib/utils/primeicon.utils'
export * from './lib/utils/translate.combined.loader'
export * from './lib/utils/create-remote-component-and-mfe-translate-loader.utils'
export * from './lib/utils/create-remote-component-translate-loader.utils'
export * from './lib/utils/enum-to-dropdown-options.utils'
export * from './lib/utils/criteria.utils'
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ import { FormsModule, ReactiveFormsModule } from '@angular/forms'
import { RouterModule } from '@angular/router'
import { MissingTranslationHandler, MissingTranslationHandlerParams, TranslateModule } from '@ngx-translate/core'

import { UserService } from '@onecx/angular-integration-interface'
import { AppConfigService, UserService } from '@onecx/angular-integration-interface'
import { AngularRemoteComponentsModule } from '@onecx/angular-remote-components'

import { firstValueFrom, skip } from 'rxjs'
import { AngularAcceleratorPrimeNgModule } from './angular-accelerator-primeng.module'
Expand All @@ -20,7 +21,6 @@ import { GroupByCountDiagramComponent } from './components/group-by-count-diagra
import { InteractiveDataViewComponent } from './components/interactive-data-view/interactive-data-view.component'
import { PageHeaderComponent } from './components/page-header/page-header.component'
import { DataLoadingErrorComponent } from './components/data-loading-error/data-loading-error.component'
import { SearchConfigComponent } from './components/search-config/search-config.component'
import { SearchHeaderComponent } from './components/search-header/search-header.component'
import { AdvancedDirective } from './directives/advanced.directive'
import { IfBreakpointDirective } from './directives/if-breakpoint.directive'
Expand All @@ -29,7 +29,6 @@ import { SrcDirective } from './directives/src.directive'
import { TooltipOnOverflowDirective } from './directives/tooltipOnOverflow.directive'
import { DynamicPipe } from './pipes/dynamic.pipe'
import { OcxTimeAgoPipe } from './pipes/ocxtimeago.pipe'
import { AppConfigService } from './services/app-config-service'
import { DynamicLocaleId } from './utils/dynamic-locale-id'

export class AngularAcceleratorMissingTranslationHandler implements MissingTranslationHandler {
Expand All @@ -49,6 +48,7 @@ function appInitializer(userService: UserService) {
imports: [
CommonModule,
AngularAcceleratorPrimeNgModule,
AngularRemoteComponentsModule,
TranslateModule,
FormsModule,
RouterModule,
Expand All @@ -63,7 +63,6 @@ function appInitializer(userService: UserService) {
DataTableComponent,
DataViewComponent,
InteractiveDataViewComponent,
SearchConfigComponent,
PageHeaderComponent,
DynamicPipe,
SearchHeaderComponent,
Expand Down Expand Up @@ -96,14 +95,14 @@ function appInitializer(userService: UserService) {
AppConfigService,
],
exports: [
AngularRemoteComponentsModule,
ColumnGroupSelectionComponent,
CustomGroupColumnSelectorComponent,
DataLayoutSelectionComponent,
DataListGridComponent,
DataTableComponent,
DataViewComponent,
InteractiveDataViewComponent,
SearchConfigComponent,
PageHeaderComponent,
SearchHeaderComponent,
DiagramComponent,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,18 +23,32 @@
></ocx-data-list-grid-sorting>
</div>

<div *ngIf="layout === 'table'" class="flex flex-wrap justify-content-between align-items-center gap-2">
<ocx-column-group-selection
[selectedGroupKey]="selectedGroupKey"
[columns]="columns"
[defaultGroupKey]="defaultGroupKey"
[customGroupKey]="customGroupKey"
[placeholderKey]="groupSelectionNoGroupSelectedKey"
(groupSelectionChanged)="onColumnGroupSelectionChange($event)"
(componentStateChanged)="columnGroupSelectionComponentState$.next($event)"
></ocx-column-group-selection>
<div
[ngStyle]="layout !== 'table' ? {
'position': 'absolute'
} : {}"
class="flex flex-wrap justify-content-between align-items-center gap-2"
>
<ng-container *ngIf="isColumnGroupSelectionComponentDefined$ | async; else defaultColumnGroupSelectionComponent">
<ng-container *ngIf="displayedColumnKeys$ | async as displayedColumnKeys">
<ocx-slot
[ngStyle]="layout !== 'table' ? {'display' : 'none'} : {}"
*ocxIfPermission="searchConfigPermission; elseTemplate: defaultColumnGroupSelectionComponent"
name="{{columnGroupSlotName}}"
[inputs]="{ placeholderKey: groupSelectionNoGroupSelectedKey, defaultGroupKey: defaultGroupKey, customGroupKey: customGroupKey, columns: columns, selectedGroupKey: selectedGroupKey, layout: layout, displayedColumnsIds: displayedColumnKeys }"
[outputs]="{ groupSelectionChanged: groupSelectionChangedSlotEmitter }"
>
<ng-template #skeleton>
<div class="flex">
<p-skeleton width="18rem" height="3rem"></p-skeleton>
</div>
</ng-template>
</ocx-slot>
</ng-container>
</ng-container>

<ocx-custom-group-column-selector
*ngIf="layout === 'table'"
[columns]="columns"
[displayedColumns]="(displayedColumns$ | async) ?? []"
(columnSelectionChanged)="onColumnSelectionChange($event)"
Expand Down Expand Up @@ -118,6 +132,19 @@
>
</ocx-data-view>
</div>

<ng-template #defaultColumnGroupSelectionComponent>
<ocx-column-group-selection
[selectedGroupKey]="selectedGroupKey ?? defaultGroupKey"
[columns]="columns"
[defaultGroupKey]="defaultGroupKey"
[customGroupKey]="customGroupKey"
[placeholderKey]="groupSelectionNoGroupSelectedKey"
(groupSelectionChanged)="onColumnGroupSelectionChange($event)"
(componentStateChanged)="columnGroupSelectionComponentState$.next($event)"
></ocx-column-group-selection>
</ng-template>

<ng-template #stringTableCell let-rowObject="rowObject" let-column="column">
<ng-container
*ngIf="_stringTableCell"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,13 @@ import {
DefaultGridItemHarness,
DefaultListItemHarness,
InteractiveDataViewHarness,
SlotHarness,
} from '../../../../testing'
import { DateUtils } from '../../utils/dateutils'
import { provideRouter } from '@angular/router'
import { SlotService } from '@onecx/angular-remote-components'
import { SlotServiceMock } from '@onecx/angular-remote-components/mocks'
import { IfPermissionDirective } from '../../directives/if-permission.directive'

describe('InteractiveDataViewComponent', () => {
const mutationObserverMock = jest.fn(function MutationObserver(callback) {
Expand All @@ -63,6 +67,7 @@ describe('InteractiveDataViewComponent', () => {
let deleteItemEvent: RowListGridData | undefined

let dateUtils: DateUtils
let slotService: SlotServiceMock

const mockData = [
{
Expand Down Expand Up @@ -229,6 +234,7 @@ describe('InteractiveDataViewComponent', () => {
DataViewComponent,
ColumnGroupSelectionComponent,
CustomGroupColumnSelectorComponent,
IfPermissionDirective,
],
imports: [
TranslateModule.forRoot(),
Expand All @@ -244,6 +250,10 @@ describe('InteractiveDataViewComponent', () => {
],
providers: [
{ provide: UserService, useClass: MockUserService },
{
provide: SlotService,
useClass: SlotServiceMock,
},
provideHttpClient(withInterceptorsFromDi()),
provideRouter([]),
provideAppStateServiceMock(),
Expand All @@ -256,6 +266,7 @@ describe('InteractiveDataViewComponent', () => {
component.editPermission = 'TEST_MGMT#TEST_EDIT'
component.deletePermission = 'TEST_MGMT#TEST_DELETE'
component.defaultGroupKey = 'PREDEFINED_GROUP.DEFAULT'
component.searchConfigPermission = 'PRODUCT#USE_SEARCHCONFIG'
component.viewItem.subscribe((event) => (viewItemEvent = event))
component.editItem.subscribe((event) => (editItemEvent = event))
component.deleteItem.subscribe((event) => (deleteItemEvent = event))
Expand All @@ -270,6 +281,7 @@ describe('InteractiveDataViewComponent', () => {
interactiveDataViewHarness = await TestbedHarnessEnvironment.harnessForFixture(fixture, InteractiveDataViewHarness)

dateUtils = TestBed.inject(DateUtils)
slotService = TestBed.inject(SlotService) as any as SlotServiceMock

viewItemEvent = undefined
editItemEvent = undefined
Expand All @@ -290,9 +302,26 @@ describe('InteractiveDataViewComponent', () => {
expect(dataLayoutSelection).toBeTruthy()
})

it('should load column-group-selection slot', async () => {
slotService.assignComponentToSlot('column-group-selection', component.columnGroupSlotName)
const userService = TestBed.inject(UserService)
jest.spyOn(userService, 'hasPermission').mockReturnValue(true)
fixture.detectChanges()

const slot = await loader.getHarness(SlotHarness)
expect(slot).toBeTruthy()
})

it('should load ColumnGroupSelectionDropdown', async () => {
const columnGroupSelectionDropdown = await loader.getHarness(ColumnGroupSelectionHarness)
expect(columnGroupSelectionDropdown).toBeTruthy()

slotService.assignComponentToSlot('column-group-selection', component.columnGroupSlotName)
const userService = TestBed.inject(UserService)
jest.spyOn(userService, 'hasPermission').mockReturnValue(false)

const columnGroupSelectionDropdownNoPermission = await loader.getHarness(ColumnGroupSelectionHarness)
expect(columnGroupSelectionDropdownNoPermission).toBeTruthy()
})

it('should load CustomGroupColumnSelector', async () => {
Expand Down Expand Up @@ -933,18 +962,18 @@ describe('InteractiveDataViewComponent', () => {
it('should move item up in picklist active columns list', async () => {
const spy = jest.spyOn(CustomGroupColumnSelectorComponent.prototype, 'onSaveClick')
const expectedHeaders = [
'COLUMN_HEADER_NAME.DESCRIPTION',
'COLUMN_HEADER_NAME.NAME',
'COLUMN_HEADER_NAME.DESCRIPTION',
'COLUMN_HEADER_NAME.STATUS',
'COLUMN_HEADER_NAME.RESPONSIBLE',
'Actions',
]
const expectedRowsData = [
['', 'some name', 'some status', 'someone responsible'],
['example description', 'example', 'status example', ''],
['', 'name 1', 'status name 1', ''],
['', 'name 2', 'status name 2', ''],
['', 'name 3', 'status name 3', ''],
['some name', '', 'some status', 'someone responsible'],
['example', 'example description', 'status example', ''],
['name 1', '', 'status name 1', ''],
['name 2', '', 'status name 2', ''],
['name 3', '', 'status name 3', ''],
]
await activeColumnsList[1].selectItem()
await sourceControlsButtons[0].click()
Expand All @@ -963,17 +992,17 @@ describe('InteractiveDataViewComponent', () => {
const spy = jest.spyOn(CustomGroupColumnSelectorComponent.prototype, 'onSaveClick')
const expectedHeaders = [
'COLUMN_HEADER_NAME.NAME',
'COLUMN_HEADER_NAME.STATUS',
'COLUMN_HEADER_NAME.DESCRIPTION',
'COLUMN_HEADER_NAME.STATUS',
'COLUMN_HEADER_NAME.RESPONSIBLE',
'Actions',
]
const expectedRowsData = [
['some name', 'some status', '', 'someone responsible'],
['example', 'status example', 'example description', ''],
['name 1', 'status name 1', '', ''],
['name 2', 'status name 2', '', ''],
['name 3', 'status name 3', '', ''],
['some name', '', 'some status', 'someone responsible'],
['example', 'example description', 'status example', ''],
['name 1', '', 'status name 1', ''],
['name 2', '', 'status name 2', ''],
['name 3', '', 'status name 3', ''],
]

await activeColumnsList[1].selectItem()
Expand Down Expand Up @@ -1698,4 +1727,26 @@ describe('InteractiveDataViewComponent', () => {
})
})
})

it('should react on group selection change event emit', () => {
const columnsChangeSpy = jest.spyOn(component.displayedColumnsChange, 'emit')
const columnKeysChangeSpy = jest.spyOn(component.displayedColumnKeysChange, 'emit')

component.groupSelectionChangedSlotEmitter.emit({
activeColumns: [
{
id: 'first-col',
} as any,
{
id: 'second-col',
} as any,
],
groupKey: 'my-search-config',
})

expect(component.displayedColumnKeys).toStrictEqual(['first-col', 'second-col'])
expect(component.selectedGroupKey).toBe('my-search-config')
expect(columnsChangeSpy).toHaveBeenCalled()
expect(columnKeysChangeSpy).toHaveBeenCalledWith(['first-col', 'second-col'])
})
})
Loading

0 comments on commit bbf7073

Please sign in to comment.