diff --git a/CHANGELOG.md b/CHANGELOG.md index e6c0c70c0c..c33150605f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -23,6 +23,7 @@ _**For better traceability add the corresponding GitHub issue number in each cha - XXX Added interceptor to EdcRestTemplates to log requests - #915 Added section to documentation: EDC-BPN configuration - #1037 Added link from contracts view to the corresponding filtered part table view +- #985 Added reference to part/notification under contract ### Removed diff --git a/frontend/src/app/mocks/services/admin-mock/admin.model.ts b/frontend/src/app/mocks/services/admin-mock/admin.model.ts index f6d708d94e..3165c962d6 100644 --- a/frontend/src/app/mocks/services/admin-mock/admin.model.ts +++ b/frontend/src/app/mocks/services/admin-mock/admin.model.ts @@ -19,8 +19,8 @@ * SPDX-License-Identifier: Apache-2.0 ********************************************************************************/ -import {PaginationResponse} from '@core/model/pagination.model'; -import {BpnConfigResponse, ContractResponse, ContractState} from '@page/admin/core/admin.model'; +import { PaginationResponse } from '@core/model/pagination.model'; +import { BpnConfigResponse, ContractResponse, ContractState, ContractType } from '@page/admin/core/admin.model'; export const getBpnConfig = (): BpnConfigResponse[] => [ @@ -221,6 +221,7 @@ export const getContracts = (): PaginationResponse => { content: [ { "contractId": "abc1", + 'contractType': ContractType.ASSET_AS_BUILT, "counterpartyAddress": "https://trace-x-edc-e2e-a.dev.demo.catena-x.net/api/v1/dsp", "creationDate": "2024-02-26T13:38:07+01:00", "endDate": null, @@ -229,6 +230,7 @@ export const getContracts = (): PaginationResponse => { }, { "contractId": "abc2", + 'contractType': ContractType.ASSET_AS_BUILT, "counterpartyAddress": "https://trace-x-edc-e2e-a.dev.demo.catena-x.net/api/v1/dsp", "creationDate": "2022-05-01T12:34:12", "endDate": null, @@ -237,6 +239,7 @@ export const getContracts = (): PaginationResponse => { }, { "contractId": "abc3", + 'contractType': ContractType.ASSET_AS_BUILT, "counterpartyAddress": "https://trace-x-edc-e2e-a.dev.demo.catena-x.net/api/v1/dsp", "creationDate": "2022-05-01T12:34:12", "endDate": null, @@ -245,6 +248,7 @@ export const getContracts = (): PaginationResponse => { }, { "contractId": "abc4", + 'contractType': ContractType.ASSET_AS_BUILT, "counterpartyAddress": "https://trace-x-edc-e2e-a.dev.demo.catena-x.net/api/v1/dsp", "creationDate": "2022-05-01T12:34:12", "endDate": null, @@ -253,6 +257,7 @@ export const getContracts = (): PaginationResponse => { }, { "contractId": "abc5", + 'contractType': ContractType.ASSET_AS_PLANNED, "counterpartyAddress": "https://trace-x-edc-e2e-a.dev.demo.catena-x.net/api/v1/dsp", "creationDate": "2022-05-01T12:34:12", "endDate": null, @@ -261,6 +266,7 @@ export const getContracts = (): PaginationResponse => { }, { "contractId": "abc6", + 'contractType': ContractType.ASSET_AS_PLANNED, "counterpartyAddress": "https://trace-x-edc-e2e-a.dev.demo.catena-x.net/api/v1/dsp", "creationDate": "2022-05-01T12:34:12", "endDate": null, @@ -269,6 +275,7 @@ export const getContracts = (): PaginationResponse => { }, { "contractId": "abc7", + 'contractType': ContractType.ASSET_AS_PLANNED, "counterpartyAddress": "https://trace-x-edc-e2e-a.dev.demo.catena-x.net/api/v1/dsp", "creationDate": "2022-05-01T12:34:12", "endDate": null, @@ -277,6 +284,7 @@ export const getContracts = (): PaginationResponse => { }, { "contractId": "abc8", + 'contractType': ContractType.ASSET_AS_PLANNED, "counterpartyAddress": "https://trace-x-edc-e2e-a.dev.demo.catena-x.net/api/v1/dsp", "creationDate": "2022-05-01T12:34:12", "endDate": null, @@ -285,6 +293,7 @@ export const getContracts = (): PaginationResponse => { }, { "contractId": "abc9", + 'contractType': ContractType.NOTIFICATION, "counterpartyAddress": "https://trace-x-edc-e2e-a.dev.demo.catena-x.net/api/v1/dsp", "creationDate": "2022-05-01T12:34:12", "endDate": null, @@ -293,6 +302,7 @@ export const getContracts = (): PaginationResponse => { }, { "contractId": "abc10", + 'contractType': ContractType.NOTIFICATION, "counterpartyAddress": "https://trace-x-edc-e2e-a.dev.demo.catena-x.net/api/v1/dsp", "creationDate": "2022-05-01T12:34:12", "endDate": null, @@ -301,6 +311,7 @@ export const getContracts = (): PaginationResponse => { }, { "contractId": "abc11", + 'contractType': ContractType.NOTIFICATION, "counterpartyAddress": "https://trace-x-edc-e2e-a.dev.demo.catena-x.net/api/v1/dsp", "creationDate": "2022-05-01T12:34:12", "endDate": null, @@ -309,6 +320,7 @@ export const getContracts = (): PaginationResponse => { }, { "contractId": "abc12", + 'contractType': ContractType.NOTIFICATION, "counterpartyAddress": "https://trace-x-edc-e2e-a.dev.demo.catena-x.net/api/v1/dsp", "creationDate": "2022-05-01T12:34:12", "endDate": null, @@ -317,6 +329,7 @@ export const getContracts = (): PaginationResponse => { }, { "contractId": "abc13", + 'contractType': ContractType.NOTIFICATION, "counterpartyAddress": "https://trace-x-edc-e2e-a.dev.demo.catena-x.net/api/v1/dsp", "creationDate": "2022-05-01T12:34:12", "endDate": null, diff --git a/frontend/src/app/modules/page/admin/core/admin.model.ts b/frontend/src/app/modules/page/admin/core/admin.model.ts index 0205a23ba5..4d857cd960 100644 --- a/frontend/src/app/modules/page/admin/core/admin.model.ts +++ b/frontend/src/app/modules/page/admin/core/admin.model.ts @@ -54,6 +54,7 @@ export type BpnConfigFormGroup = FormGroup<{ bpnConfig: FormArray; export type Contracts = Pagination; export function assembleContract(contractResponse: ContractResponse): Contract { return { contractId: contractResponse.contractId, + contractType: contractResponse.contractType, counterpartyAddress: contractResponse.counterpartyAddress, creationDate: new CalendarDateModel(contractResponse.creationDate), endDate: new CalendarDateModel(contractResponse.endDate), diff --git a/frontend/src/app/modules/page/admin/core/admin.service.ts b/frontend/src/app/modules/page/admin/core/admin.service.ts index 18f653566f..1e03757ec1 100644 --- a/frontend/src/app/modules/page/admin/core/admin.service.ts +++ b/frontend/src/app/modules/page/admin/core/admin.service.ts @@ -19,12 +19,12 @@ * SPDX-License-Identifier: Apache-2.0 ********************************************************************************/ -import {HttpParams} from '@angular/common/http'; -import {Injectable} from '@angular/core'; -import {ApiService} from '@core/api/api.service'; -import {Pagination} from '@core/model/pagination.model'; -import {environment} from '@env'; -import {AdminAssembler} from '@page/admin/core/admin.assembler'; +import { HttpParams } from '@angular/common/http'; +import { Injectable } from '@angular/core'; +import { ApiService } from '@core/api/api.service'; +import { Pagination } from '@core/model/pagination.model'; +import { environment } from '@env'; +import { AdminAssembler } from '@page/admin/core/admin.assembler'; import { assembleContract, BpnConfig, @@ -32,9 +32,9 @@ import { Contract, ContractResponse, } from '@page/admin/core/admin.model'; -import {TableHeaderSort} from '@shared/components/table/table.model'; -import {Observable} from 'rxjs'; -import {map} from 'rxjs/operators'; +import { TableHeaderSort } from '@shared/components/table/table.model'; +import { Observable } from 'rxjs'; +import { map } from 'rxjs/operators'; @Injectable() export class AdminService { @@ -109,7 +109,7 @@ export class AdminService { Object.entries(filter).forEach(([ entry, values ]) => { if (values.length) { values.forEach(value => { - filterList.push(`${ entry },EQUAL,${ value },AND`); + filterList.push(`${ entry },EQUAL,${ value },OR`); }); } }); diff --git a/frontend/src/app/modules/page/admin/presentation/contracts/contracts.component.html b/frontend/src/app/modules/page/admin/presentation/contracts/contracts.component.html index 07c88ef5e6..eac54274d8 100644 --- a/frontend/src/app/modules/page/admin/presentation/contracts/contracts.component.html +++ b/frontend/src/app/modules/page/admin/presentation/contracts/contracts.component.html @@ -4,7 +4,9 @@ -
+
+ +
{ it('should navigate if viewAssets clicked', async () => { const { fixture } = await renderContractTableComponent(); const { componentInstance } = fixture; - componentInstance.viewAssetsClicked.emit({ contractId: 'test' }); + componentInstance.viewItemsClicked.emit({ contractId: 'test' }); expect(routerMock.navigate).toHaveBeenCalled(); }); @@ -98,7 +98,7 @@ describe('ContractTableComponent', () => { it('should emit viewAssetsClicked', async () => { const { fixture } = await renderContractTableComponent(); const { componentInstance } = fixture; - let spy = spyOn(componentInstance.viewAssetsClicked, 'emit'); + let spy = spyOn(componentInstance.viewItemsClicked, 'emit'); const viewAssetsAction = componentInstance.tableConfig.menuActionsConfig.filter(action => action.label === 'actions.viewParts')[0]; viewAssetsAction.action(null); expect(spy).toHaveBeenCalled(); diff --git a/frontend/src/app/modules/page/admin/presentation/contracts/contracts.component.ts b/frontend/src/app/modules/page/admin/presentation/contracts/contracts.component.ts index 8c861c9dff..3d83500f7a 100644 --- a/frontend/src/app/modules/page/admin/presentation/contracts/contracts.component.ts +++ b/frontend/src/app/modules/page/admin/presentation/contracts/contracts.component.ts @@ -2,12 +2,15 @@ import { Component, EventEmitter } from '@angular/core'; import { Router } from '@angular/router'; import { Pagination } from '@core/model/pagination.model'; import { AdminFacade } from '@page/admin/core/admin.facade'; -import { Contract, KnownAdminRoutes } from '@page/admin/core/admin.model'; +import { Contract, ContractType, KnownAdminRoutes } from '@page/admin/core/admin.model'; import { ContractsFacade } from '@page/admin/presentation/contracts/contracts.facade'; import { TableType } from '@shared/components/multi-select-autocomplete/table-type.model'; import { CreateHeaderFromColumns, TableConfig, TableEventConfig } from '@shared/components/table/table.model'; +import { ToastService } from '@shared/components/toasts/toast.service'; import { View } from '@shared/model/view.model'; import { NotificationAction } from '@shared/modules/notification/notification-action.enum'; +import { NotificationService } from '@shared/service/notification.service'; +import { PartsService } from '@shared/service/parts.service'; import { Observable } from 'rxjs'; import { take } from 'rxjs/operators'; @@ -22,40 +25,73 @@ export class ContractsComponent { selectedContracts: Contract[]; contractFilter: any; pagination: TableEventConfig; - viewAssetsClicked: EventEmitter = new EventEmitter; + viewItemsClicked: EventEmitter = new EventEmitter; - constructor(public readonly adminFacade: AdminFacade, private readonly contractsFacade: ContractsFacade, private readonly router: Router) {} + constructor(public readonly adminFacade: AdminFacade, private readonly contractsFacade: ContractsFacade, private readonly router: Router, private readonly partsService: PartsService, private readonly notificationsService: NotificationService, private readonly toastService: ToastService) { + } public ngOnInit() { this.contractsView$ = this.contractsFacade.contracts$; this.contractsView$.pipe(take(1)).subscribe(data => { - if(data?.data?.content.length) { + if (data?.data?.content.length) { return; } else { - this.contractsFacade.setContracts(0,10,[null,null]); + this.contractsFacade.setContracts(0, 10, [ null, null ]); } - }) + }); + + this.viewItemsClicked.subscribe((data) => { + const contractId = data?.contractId; - this.viewAssetsClicked.subscribe((data) => { - this.router.navigate([ 'parts' ], { queryParams: { contractId: data?.['contractId'] } }); + if (data?.contractType === ContractType.NOTIFICATION) { + this.notificationsService.getNotifications(0, 1, [], undefined, undefined, { contractAgreementId: contractId }).subscribe({ + next: data => { + data?.content?.length > 0 ? this.router.navigate([ 'inbox', data?.content[0]?.id ]) : this.toastService.error('pageAdmin.contracts.noItemsFoundError'); + }, + error: error => this.toastService.error(error), + }, + ); + } else { + this.partsService.getPartsByFilter({ contractAgreementId: contractId }, data?.contractType === ContractType.ASSET_AS_BUILT).subscribe({ + next: data => data?.content?.length > 0 ? this.router.navigate([ 'parts', data?.content[0]?.id ], { queryParams: { isAsBuilt: data?.content[0]?.partId !== undefined } }) : this.toastService.error('pageAdmin.contracts.noItemsFoundError'), + error: error => this.toastService.error(error), + + }); + } }); this.pagination = { page: 0, pageSize: 10, sorting: [ '', null ] }; + + this.tableConfig = { - displayedColumns: [ 'select', 'contractId', 'counterpartyAddress', 'creationDate', 'endDate', 'state', 'menu' ], - header: CreateHeaderFromColumns([ 'contractId', 'counterpartyAddress', 'creationDate', 'endDate', 'state', 'menu' ], 'pageAdmin.contracts'), + displayedColumns: [ 'select', 'contractId', 'contractType', 'counterpartyAddress', 'creationDate', 'endDate', 'state', 'menu' ], + header: CreateHeaderFromColumns([ 'contractId', 'contractType', 'counterpartyAddress', 'creationDate', 'endDate', 'state', 'menu' ], 'pageAdmin.contracts'), menuActionsConfig: [ { label: 'actions.viewParts', icon: 'build', action: (data: Record) => { - this.viewAssetsClicked.emit(data); + this.viewItemsClicked.emit(data); + }, + condition: (data: Contract) => { + return (data?.contractType === ContractType.ASSET_AS_BUILT || data?.contractType === ContractType.ASSET_AS_PLANNED); + }, + }, + { + label: 'actions.viewNotifications', + icon: 'announcement', + action: (data: Record) => { + this.viewItemsClicked.emit(data); + }, + condition: (data: Contract) => { + return (data?.contractType === ContractType.NOTIFICATION); }, }, ], sortableColumns: { select: false, + contractType: false, contractId: true, counterpartyAddress: false, creationDate: false, @@ -72,7 +108,7 @@ export class ContractsComponent { public onTableConfigChange(pagination: TableEventConfig): void { this.pagination = pagination; - this.contractsFacade.setContracts(pagination.page, pagination.pageSize,[pagination.sorting]); + this.contractsFacade.setContracts(pagination.page, pagination.pageSize, [ pagination.sorting ], this.contractFilter); } multiSelection(selectedContracts: Contract[]) { @@ -114,7 +150,15 @@ export class ContractsComponent { openDetailedView(selectedContract: Record) { this.contractsFacade.selectedContract = selectedContract as unknown as Contract; - this.router.navigate(['admin/'+KnownAdminRoutes.CONTRACT+'/'+this.contractsFacade.selectedContract.contractId]); + this.router.navigate([ 'admin/' + KnownAdminRoutes.CONTRACT + '/' + this.contractsFacade.selectedContract.contractId ]); + } + + filterContractType(filterList: any) { + this.contractFilter = { + ...this.contractFilter, + contractType: filterList, + }; + this.contractsFacade.setContracts(this.pagination.page, this.pagination.pageSize, [ this.pagination.sorting ], this.contractFilter); } ngOnDestroy() { diff --git a/frontend/src/app/modules/page/admin/presentation/contracts/contracts.facade.ts b/frontend/src/app/modules/page/admin/presentation/contracts/contracts.facade.ts index a6d8cba5df..2f624b4eef 100644 --- a/frontend/src/app/modules/page/admin/presentation/contracts/contracts.facade.ts +++ b/frontend/src/app/modules/page/admin/presentation/contracts/contracts.facade.ts @@ -23,9 +23,9 @@ export class ContractsFacade { return this.contractsState.contracts$ } - public setContracts(page, pageSize = 50, sorting: TableHeaderSort[]): void { + public setContracts(page, pageSize = 50, sorting: TableHeaderSort[], filter?: any): void { this.contractsSubscription?.unsubscribe(); - this.contractsSubscription = this.adminService.getContracts(page,pageSize,sorting).subscribe({ + this.contractsSubscription = this.adminService.getContracts(page, pageSize, sorting, filter).subscribe({ next: data => (this.contractsState.contracts = { data: provideDataObject(data) }), error: error => (this.contractsState.contracts = { error}) }) diff --git a/frontend/src/app/modules/shared/components/contracts-quick-filter/contracts-quick-filter.component.html b/frontend/src/app/modules/shared/components/contracts-quick-filter/contracts-quick-filter.component.html new file mode 100644 index 0000000000..1c71b652a3 --- /dev/null +++ b/frontend/src/app/modules/shared/components/contracts-quick-filter/contracts-quick-filter.component.html @@ -0,0 +1,41 @@ + +
+ + {{ 'quickFilter.asBuilt' | i18n }} + + + {{ 'quickFilter.asPlanned' | i18n }} + + + {{ 'quickFilter.notification' | i18n }} + +
diff --git a/frontend/src/app/modules/shared/components/contracts-quick-filter/contracts-quick-filter.component.scss b/frontend/src/app/modules/shared/components/contracts-quick-filter/contracts-quick-filter.component.scss new file mode 100644 index 0000000000..4dc513f2ee --- /dev/null +++ b/frontend/src/app/modules/shared/components/contracts-quick-filter/contracts-quick-filter.component.scss @@ -0,0 +1,22 @@ +/******************************************************************************** + * Copyright (c) 2023 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ +.button-container { + display: flex; + flex-direction: row; +} diff --git a/frontend/src/app/modules/shared/components/contracts-quick-filter/contracts-quick-filter.component.spec.ts b/frontend/src/app/modules/shared/components/contracts-quick-filter/contracts-quick-filter.component.spec.ts new file mode 100644 index 0000000000..29fe1fcbfd --- /dev/null +++ b/frontend/src/app/modules/shared/components/contracts-quick-filter/contracts-quick-filter.component.spec.ts @@ -0,0 +1,38 @@ +import { ContractType } from '@page/admin/core/admin.model'; +import { SharedModule } from '@shared/shared.module'; +import { renderComponent } from '@tests/test-render.utils'; +import { ContractsQuickFilterComponent } from './contracts-quick-filter.component'; + +describe('BomLifecycleActivatorComponent', () => { + + const renderQuickFilter = () => { + return renderComponent(ContractsQuickFilterComponent, { + imports: [ SharedModule ], + providers: [], + componentProperties: {}, + }); + }; + + it('should create the component', async () => { + const { fixture } = await renderQuickFilter(); + const { componentInstance } = fixture; + expect(componentInstance).toBeTruthy(); + }); + + + it('should set state when initially called', async () => { + const { fixture } = await renderQuickFilter(); + const { componentInstance } = fixture; + componentInstance.activeContractTypes = []; + componentInstance.emitQuickFilter(ContractType.ASSET_AS_BUILT); + expect(componentInstance.activeContractTypes).toEqual([ ContractType.ASSET_AS_BUILT ]); + }); + + it('should unset state when called again', async () => { + const { fixture } = await renderQuickFilter(); + const { componentInstance } = fixture; + componentInstance.activeContractTypes = [ ContractType.ASSET_AS_PLANNED ]; + componentInstance.emitQuickFilter(ContractType.ASSET_AS_PLANNED); + expect(componentInstance.activeContractTypes).toEqual([]); + }); +}); diff --git a/frontend/src/app/modules/shared/components/contracts-quick-filter/contracts-quick-filter.component.ts b/frontend/src/app/modules/shared/components/contracts-quick-filter/contracts-quick-filter.component.ts new file mode 100644 index 0000000000..31b821b946 --- /dev/null +++ b/frontend/src/app/modules/shared/components/contracts-quick-filter/contracts-quick-filter.component.ts @@ -0,0 +1,49 @@ +/******************************************************************************** + * Copyright (c) 2023 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ +import { Component, EventEmitter, Output } from '@angular/core'; +import { ContractType } from '@page/admin/core/admin.model'; + +@Component({ + selector: 'app-contracts-quick-filter', + templateUrl: './contracts-quick-filter.component.html', + styleUrls: [ './contracts-quick-filter.component.scss' ], +}) +export class ContractsQuickFilterComponent { + + activeContractTypes: ContractType[] = []; + @Output() buttonClickEvent = new EventEmitter(); + + emitQuickFilter(contractType: ContractType) { + if (this.activeContractTypes?.includes(contractType)) { + this.activeContractTypes = this.activeContractTypes.filter(type => type !== contractType); + } else { + this.activeContractTypes.push(contractType); + } + this.buttonClickEvent.emit(this.activeContractTypes); + } + + + handleKeyDownByOwner(event: KeyboardEvent, type: ContractType) { + if (event.key === 'Enter') { + this.emitQuickFilter(type); + } + } + + protected readonly ContractType = ContractType; +} diff --git a/frontend/src/app/modules/shared/components/table/table.component.html b/frontend/src/app/modules/shared/components/table/table.component.html index 83c43ef666..8888d5d0c7 100644 --- a/frontend/src/app/modules/shared/components/table/table.component.html +++ b/frontend/src/app/modules/shared/components/table/table.component.html @@ -342,12 +342,12 @@

{{ 'table.noResultFound' | i18n }}

> {{ config.icon }}
{{ config.label | i18n }} diff --git a/frontend/src/app/modules/shared/service/notification.service.ts b/frontend/src/app/modules/shared/service/notification.service.ts index da78b9575f..692fccd9b7 100644 --- a/frontend/src/app/modules/shared/service/notification.service.ts +++ b/frontend/src/app/modules/shared/service/notification.service.ts @@ -49,7 +49,7 @@ export class NotificationService { constructor(private readonly apiService: ApiService) { } - public getNotifications(page: number, pageSize: number, sorting: TableHeaderSort[], channel: NotificationChannel, filter?: NotificationDeeplinkFilter, fullFilter?: any): Observable { + public getNotifications(page: number, pageSize: number, sorting: TableHeaderSort[], channel?: NotificationChannel, filter?: NotificationDeeplinkFilter, fullFilter?: any): Observable { const sort = sorting.length ? sorting.map(array => `${ array[0] },${ array[1] }`) : [ 'createdDate,desc' ]; const requestUrl = this.notificationUrl() + '/filter'; const channelFilter = channel === NotificationChannel.RECEIVER ? 'channel,EQUAL,RECEIVER,AND' : 'channel,EQUAL,SENDER,AND'; diff --git a/frontend/src/app/modules/shared/service/parts.service.ts b/frontend/src/app/modules/shared/service/parts.service.ts index a0e347f26d..f415672eec 100644 --- a/frontend/src/app/modules/shared/service/parts.service.ts +++ b/frontend/src/app/modules/shared/service/parts.service.ts @@ -166,6 +166,16 @@ export class PartsService { } } + public getPartsByFilter(filter: any, isAsBuilt: boolean): Observable> { + const params = enrichFilterAndGetUpdatedParams(filter, new HttpParams(), 'OR'); + const mainAspectType = isAsBuilt ? MainAspectType.AS_BUILT : MainAspectType.AS_PLANNED; + const path = isAsBuilt ? 'as-built' : 'as-planned'; + + return this.apiService + .getBy(`${ this.url }/assets/${ path }`, params) + .pipe(map(parts => PartsAssembler.assembleParts(parts, mainAspectType))); + } + public sortParts(data: Part[], key: string, direction: SortDirection): Part[] { const clonedData: Part[] = _deepClone(data); return clonedData.sort((partA, partB) => { diff --git a/frontend/src/app/modules/shared/shared.module.ts b/frontend/src/app/modules/shared/shared.module.ts index f68ed2e791..44b29d50ef 100644 --- a/frontend/src/app/modules/shared/shared.module.ts +++ b/frontend/src/app/modules/shared/shared.module.ts @@ -26,6 +26,7 @@ import { RouterModule } from '@angular/router'; import { AssetPublisherComponent } from '@shared/components/asset-publisher/asset-publisher.component'; import { CardMetricComponent } from '@shared/components/card-metric/card-metric.component'; import { ChipComponent } from '@shared/components/chip/chip.component'; +import { ContractsQuickFilterComponent } from '@shared/components/contracts-quick-filter/contracts-quick-filter.component'; import { CountryFlagGeneratorComponent } from '@shared/components/country-flag-generator/country-flag-generator.component'; import { DateTimeComponent } from '@shared/components/dateTime/dateTime.component'; import { FormErrorMessageComponent } from '@shared/components/formErrorMessage/formErrorMessage.component'; @@ -123,6 +124,7 @@ import { TemplateModule } from './template.module'; TypeSelectComponent, InputComponent, QuickFilterComponent, + ContractsQuickFilterComponent, ViewSelectorComponent, MultiSelectAutocompleteComponent, CountryFlagGeneratorComponent, @@ -174,6 +176,7 @@ import { TemplateModule } from './template.module'; FormatPartSemanticDataModelToCamelCasePipe, FormatPartlistSemanticDataModelToCamelCasePipe, QuickFilterComponent, + ContractsQuickFilterComponent, ViewSelectorComponent, PartsTableComponent, MultiSelectAutocompleteComponent, diff --git a/frontend/src/assets/locales/de/common.json b/frontend/src/assets/locales/de/common.json index 9128f41455..56df65dca5 100644 --- a/frontend/src/assets/locales/de/common.json +++ b/frontend/src/assets/locales/de/common.json @@ -70,8 +70,10 @@ "userSettings" : "Tabellen Einstellung", "uploadFile" : "Richtlinien JSON-Datei hochladen", "downloadFile" : "Vorlage als Datei herunterladen", - "viewParts" : "Produkte ansehen", - "viewPartsTooltip" : "Produkte mit diesem Vertrag ansehen" + "viewParts" : "Produkt ansehen", + "viewNotifications" : "Qualitätsthema ansehen", + "viewPartsTooltip" : "Produkt unter diesem Vertrag ansehen", + "viewNotificationsTooltip" : "Qualitätsthema unter diesem Vertrag ansehen" }, "publisher": { "selectedAssets": "Ausgewählte Produkte", @@ -394,7 +396,10 @@ "quickFilter": { "own": "Eigene", "supplier": "LIEFERANT", - "customer": "KUNDE" + "customer" : "KUNDE", + "asBuilt" : "As built", + "asPlanned" : "As planned", + "notification" : "Qualitätsthemen" }, "multiSelect": { "filterLabel": "Filter", diff --git a/frontend/src/assets/locales/de/page.admin.json b/frontend/src/assets/locales/de/page.admin.json index 7616c7517c..9899fa9a5f 100644 --- a/frontend/src/assets/locales/de/page.admin.json +++ b/frontend/src/assets/locales/de/page.admin.json @@ -54,7 +54,9 @@ "overview": "Übersicht", "policyDetail" : "Vereinbarungsdetails", "jsonViewer": "Json Ansicht", - "jsonTreeViewer": "Json-Baumansicht" + "jsonTreeViewer" : "Json-Baumansicht", + "contractType" : "Vertragsart", + "noItemsFoundError" : "Es wurden keine Einträge unter dem selektierten Vertrag gefunden." }, "policyManagement" : { "policyManagement" : "Richtlinienverwaltung", diff --git a/frontend/src/assets/locales/en/common.json b/frontend/src/assets/locales/en/common.json index db45a21c05..4d3172f548 100644 --- a/frontend/src/assets/locales/en/common.json +++ b/frontend/src/assets/locales/en/common.json @@ -68,8 +68,10 @@ "userSettings" : "Table settings", "uploadFile" : "Upload policy JSON file", "downloadFile" : "Download template as file", - "viewParts" : "View parts", - "viewPartsTooltip" : "View parts using this contract" + "viewParts" : "View part", + "viewNotifications" : "View notification", + "viewPartsTooltip" : "View part using this contract", + "viewNotificationsTooltip" : "View notification using this contract" }, "publisher": { "selectedAssets": "Assets selected", @@ -393,7 +395,10 @@ "quickFilter": { "own": "OWN", "supplier": "SUPPLIER", - "customer": "CUSTOMER" + "customer" : "CUSTOMER", + "asBuilt" : "As built", + "asPlanned" : "As planned", + "notification" : "Quality incidents" }, "multiSelect": { "filterLabel": "Filter", diff --git a/frontend/src/assets/locales/en/page.admin.json b/frontend/src/assets/locales/en/page.admin.json index adb2c3693f..acf17d5693 100644 --- a/frontend/src/assets/locales/en/page.admin.json +++ b/frontend/src/assets/locales/en/page.admin.json @@ -54,7 +54,9 @@ "overview": "Overview", "policyDetail" : "Agreement details", "jsonViewer": "Json Viewer", - "jsonTreeViewer": "Json Tree Viewer" + "jsonTreeViewer" : "Json Tree Viewer", + "contractType" : "Contract type", + "noItemsFoundError" : "Could not find any item under the selected contract." }, "policyManagement" : { "policyManagement" : "Policy management",