From 752743a349dbe013fe46c6a00778cd77d42ce1a8 Mon Sep 17 00:00:00 2001 From: Aleix Suau Date: Thu, 25 Jun 2020 11:16:59 +0200 Subject: [PATCH 01/11] Commit for Olivers debug --- frontend/npm-shrinkwrap.json | 20 +++++++------- .../app/components/wp-list/wp-list.service.ts | 1 + .../wp-states-initialization.service.ts | 2 ++ .../bcf-list-container.component.ts | 25 +++++++++++++----- .../ifc-viewer/ifc-viewer.service.ts | 2 +- .../pages/viewer/bim-view.service.ts | 11 +++++--- .../bim-view-toggle-dropdown.directive.ts | 26 ++++++++++++++++--- .../wp-list-view/wp-list-view.component.ts | 14 ++++++++-- .../view-services/wp-view-base.service.ts | 4 +++ .../view-services/wp-view-columns.service.ts | 9 +++++++ 10 files changed, 87 insertions(+), 27 deletions(-) diff --git a/frontend/npm-shrinkwrap.json b/frontend/npm-shrinkwrap.json index a46eb9b48f..f1458dab3e 100644 --- a/frontend/npm-shrinkwrap.json +++ b/frontend/npm-shrinkwrap.json @@ -4719,7 +4719,7 @@ }, "camelcase-keys": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz", + "resolved": "http://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz", "integrity": "sha1-MIvur/3ygRkFHvodkyITyRuPkuc=", "requires": { "camelcase": "^2.0.0", @@ -9055,7 +9055,7 @@ }, "load-json-file": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", + "resolved": "http://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", "requires": { "graceful-fs": "^4.1.2", @@ -9075,7 +9075,7 @@ }, "pify": { "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "resolved": "http://registry.npmjs.org/pify/-/pify-2.3.0.tgz", "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=" } } @@ -9380,7 +9380,7 @@ }, "meow": { "version": "3.7.0", - "resolved": "https://registry.npmjs.org/meow/-/meow-3.7.0.tgz", + "resolved": "http://registry.npmjs.org/meow/-/meow-3.7.0.tgz", "integrity": "sha1-cstmi0JSKCkKu/qFaJJYcwioAfs=", "requires": { "camelcase-keys": "^2.0.0", @@ -9942,7 +9942,7 @@ "dependencies": { "semver": { "version": "5.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz", + "resolved": "http://registry.npmjs.org/semver/-/semver-5.3.0.tgz", "integrity": "sha1-myzl094C0XxgEq0yaqa00M9U+U8=" }, "tar": { @@ -10040,7 +10040,7 @@ }, "chalk": { "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", "requires": { "ansi-styles": "^2.2.1", @@ -10585,7 +10585,7 @@ }, "os-homedir": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", + "resolved": "http://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=" }, "os-tmpdir": { @@ -12074,7 +12074,7 @@ }, "pify": { "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "resolved": "http://registry.npmjs.org/pify/-/pify-2.3.0.tgz", "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=" } } @@ -12572,7 +12572,7 @@ "dependencies": { "source-map": { "version": "0.4.4", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz", + "resolved": "http://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz", "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=", "requires": { "amdefine": ">=0.0.4" @@ -13467,7 +13467,7 @@ }, "strip-ansi": { "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "resolved": "http://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", "requires": { "ansi-regex": "^2.0.0" diff --git a/frontend/src/app/components/wp-list/wp-list.service.ts b/frontend/src/app/components/wp-list/wp-list.service.ts index 708b96dce3..ae5f2db8ce 100644 --- a/frontend/src/app/components/wp-list/wp-list.service.ts +++ b/frontend/src/app/components/wp-list/wp-list.service.ts @@ -204,6 +204,7 @@ export class WorkPackagesListService { * Load the query from the given state params */ public loadCurrentQueryFromParams(projectIdentifier?:string) { + console.log('loadCurrentQueryFromParams: ', projectIdentifier); return this .fromQueryParams(this.$state.params as any, projectIdentifier) .toPromise(); diff --git a/frontend/src/app/components/wp-list/wp-states-initialization.service.ts b/frontend/src/app/components/wp-list/wp-states-initialization.service.ts index c029c1e927..daf0dec00d 100644 --- a/frontend/src/app/components/wp-list/wp-states-initialization.service.ts +++ b/frontend/src/app/components/wp-list/wp-states-initialization.service.ts @@ -54,6 +54,7 @@ export class WorkPackageStatesInitializationService { * @param results */ public initialize(query:QueryResource, results:WorkPackageCollectionResource) { + console.log('WorkPackageStatesInitializationService initialize: ', query, results); this.clearStates(); // Update the (global) wp query states @@ -132,6 +133,7 @@ export class WorkPackageStatesInitializationService { } public initializeFromQuery(query:QueryResource, results:WorkPackageCollectionResource) { + // console.log('WorkPackageStatesInitializationService initializeFromQuery: ', JSON.stringify(query.columns), results); this.querySpace.query.putValue(query); this.wpTableSum.initialize(query); diff --git a/frontend/src/app/modules/bim/ifc_models/bcf/list-container/bcf-list-container.component.ts b/frontend/src/app/modules/bim/ifc_models/bcf/list-container/bcf-list-container.component.ts index 8cdf323149..06275a6eaa 100644 --- a/frontend/src/app/modules/bim/ifc_models/bcf/list-container/bcf-list-container.component.ts +++ b/frontend/src/app/modules/bim/ifc_models/bcf/list-container/bcf-list-container.component.ts @@ -1,4 +1,4 @@ -import {ChangeDetectionStrategy, Component, OnInit} from "@angular/core"; +import {ChangeDetectionStrategy, Component, OnInit, AfterViewChecked} from "@angular/core"; import {WorkPackageViewHandlerToken} from "core-app/modules/work_packages/routing/wp-view-base/event-handling/event-handler-registry"; import {BcfCardViewHandlerRegistry} from "core-app/modules/bim/ifc_models/ifc-base-view/event-handler/bcf-card-view-handler-registry"; import {WorkPackageListViewComponent} from "core-app/modules/work_packages/routing/wp-list-view/wp-list-view.component"; @@ -9,8 +9,9 @@ import {DragAndDropService} from "core-app/modules/common/drag-and-drop/drag-and import {CausedUpdatesService} from "core-app/modules/boards/board/caused-updates/caused-updates.service"; import {bimSplitViewIdentifier, BimViewService} from "core-app/modules/bim/ifc_models/pages/viewer/bim-view.service"; import {InjectField} from "core-app/helpers/angular/inject-field.decorator"; -import {wpDisplayCardRepresentation} from "core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-display-representation.service"; +import {wpDisplayCardRepresentation, wpDisplayListRepresentation} from "core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-display-representation.service"; import {IfcModelsDataService} from "core-app/modules/bim/ifc_models/pages/viewer/ifc-models-data.service"; +import {WorkPackageViewColumnsService} from 'core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-columns.service'; @Component({ templateUrl: '/app/modules/work_packages/routing/wp-list-view/wp-list-view.component.html', @@ -23,17 +24,24 @@ import {IfcModelsDataService} from "core-app/modules/bim/ifc_models/pages/viewer ], changeDetection: ChangeDetectionStrategy.OnPush }) -export class BcfListContainerComponent extends WorkPackageListViewComponent implements OnInit { +export class BcfListContainerComponent extends WorkPackageListViewComponent implements OnInit, AfterViewChecked { @InjectField() bimView:BimViewService; @InjectField() ifcModelsService:IfcModelsDataService; + @InjectField() wpTableColumns:WorkPackageViewColumnsService; public wpTableConfiguration = { dragAndDropEnabled: false }; - + protected updateViewRepresentation(query:QueryResource) { - this.wpDisplayRepresentation.setDisplayRepresentation(wpDisplayCardRepresentation); - this.showListView = false; + console.log('updateViewRepresentation: ', this.wpTableColumns.id, this.wpTableColumns.getColumns(), query); + this.wpTableColumns.addColumn('bcfThumbnail', 2); + + if (this.wpDisplayRepresentation.current === null) { + this.wpDisplayRepresentation.setDisplayRepresentation(wpDisplayCardRepresentation); + } + + super.updateViewRepresentation(query); } protected showResizerInCardView():boolean { @@ -43,4 +51,9 @@ export class BcfListContainerComponent extends WorkPackageListViewComponent impl return this.bimView.currentViewerState() === bimSplitViewIdentifier; } } + + ngAfterViewChecked() { + console.log('COLUMNS: ', this.wpTableColumns.getColumns()); + // this.wpTableColumns.addColumn('bcfThumbnail', 2); + } } diff --git a/frontend/src/app/modules/bim/ifc_models/ifc-viewer/ifc-viewer.service.ts b/frontend/src/app/modules/bim/ifc_models/ifc-viewer/ifc-viewer.service.ts index aa08c950c0..d5f1bbebfd 100644 --- a/frontend/src/app/modules/bim/ifc_models/ifc-viewer/ifc-viewer.service.ts +++ b/frontend/src/app/modules/bim/ifc_models/ifc-viewer/ifc-viewer.service.ts @@ -33,7 +33,7 @@ export interface BCFLoadOptions { @Injectable() export class IFCViewerService extends ViewerBridgeService { - public shouldShowViewer = true; + public shouldShowViewer = false; private _viewer:any; private $loaded = new Subject(); diff --git a/frontend/src/app/modules/bim/ifc_models/pages/viewer/bim-view.service.ts b/frontend/src/app/modules/bim/ifc_models/pages/viewer/bim-view.service.ts index d9f9fc5e3a..a54ac1c733 100644 --- a/frontend/src/app/modules/bim/ifc_models/pages/viewer/bim-view.service.ts +++ b/frontend/src/app/modules/bim/ifc_models/pages/viewer/bim-view.service.ts @@ -35,10 +35,11 @@ import {takeUntil} from "rxjs/operators"; export const bimListViewIdentifier = 'list'; -export const bimViewerViewIdentifier = 'viewer'; +export const bimTableViewIdentifier = 'table'; export const bimSplitViewIdentifier = 'split'; +export const bimViewerViewIdentifier = 'viewer'; -export type BimViewState = 'list'|'viewer'|'split'; +export type BimViewState = 'list'|'viewer'|'split'|'table'; @Injectable() export class BimViewService implements OnDestroy { @@ -47,13 +48,15 @@ export class BimViewService implements OnDestroy { public text:any = { list: this.I18n.t('js.views.card'), viewer: this.I18n.t('js.ifc_models.views.viewer'), - split: this.I18n.t('js.ifc_models.views.split') + split: this.I18n.t('js.ifc_models.views.split'), + table: this.I18n.t('js.views.list'), }; public icon:any = { list: 'icon-view-card', viewer: 'icon-view-model', - split: 'icon-view-split2' + split: 'icon-view-split2', + table: 'icon-view-list', }; private transitionFn:Function; diff --git a/frontend/src/app/modules/bim/ifc_models/toolbar/view-toggle/bim-view-toggle-dropdown.directive.ts b/frontend/src/app/modules/bim/ifc_models/toolbar/view-toggle/bim-view-toggle-dropdown.directive.ts index 6d04d61f3c..8c38815abb 100644 --- a/frontend/src/app/modules/bim/ifc_models/toolbar/view-toggle/bim-view-toggle-dropdown.directive.ts +++ b/frontend/src/app/modules/bim/ifc_models/toolbar/view-toggle/bim-view-toggle-dropdown.directive.ts @@ -34,23 +34,30 @@ import {StateService} from "@uirouter/core"; import {WorkPackageFiltersService} from "core-components/filters/wp-filters/wp-filters.service"; import { - bimListViewIdentifier, bimSplitViewIdentifier, + bimListViewIdentifier, bimSplitViewIdentifier, bimTableViewIdentifier, bimViewerViewIdentifier, BimViewService } from "core-app/modules/bim/ifc_models/pages/viewer/bim-view.service"; import {ViewerBridgeService} from "core-app/modules/bim/bcf/bcf-viewer-bridge/viewer-bridge.service"; +import { + WorkPackageViewDisplayRepresentationService, + wpDisplayCardRepresentation, + wpDisplayListRepresentation, +} from "core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-display-representation.service"; @Directive({ selector: '[bimViewDropdown]' }) export class BimViewToggleDropdownDirective extends OpContextMenuTrigger { + constructor(readonly elementRef:ElementRef, readonly opContextMenu:OPContextMenuService, readonly bimView:BimViewService, readonly I18n:I18nService, readonly state:StateService, readonly wpFiltersService:WorkPackageFiltersService, - readonly viewerBridgeService:ViewerBridgeService) { + readonly viewerBridgeService:ViewerBridgeService, + readonly wpDisplayRepresentation:WorkPackageViewDisplayRepresentationService) { super(elementRef, opContextMenu); } @@ -72,7 +79,7 @@ export class BimViewToggleDropdownDirective extends OpContextMenuTrigger { const viewRoute = this.state.current.data.viewRoute; let items = this.viewerBridgeService.shouldShowViewer ? [bimViewerViewIdentifier, bimListViewIdentifier, bimSplitViewIdentifier] : - [bimListViewIdentifier]; + [bimListViewIdentifier, bimTableViewIdentifier]; this.items = items .map(key => { @@ -88,7 +95,18 @@ export class BimViewToggleDropdownDirective extends OpContextMenuTrigger { switch (key) { case bimListViewIdentifier: - this.state.go('bim.partitioned.list'); + console.log('this.state.current: ', this.state.current); + this.wpDisplayRepresentation.setDisplayRepresentation(wpDisplayCardRepresentation); + if (this.state.current.name !== 'bim.partitioned.list') { + this.state.go('bim.partitioned.list'); + } + break; + case bimTableViewIdentifier: + console.log('this.state.current 2: ', this.state.current); + this.wpDisplayRepresentation.setDisplayRepresentation(wpDisplayListRepresentation); + if (this.state.current.name !== 'bim.partitioned.list') { + this.state.go('bim.partitioned.list'); + } break; case bimViewerViewIdentifier: this.state.go('bim.partitioned.model'); diff --git a/frontend/src/app/modules/work_packages/routing/wp-list-view/wp-list-view.component.ts b/frontend/src/app/modules/work_packages/routing/wp-list-view/wp-list-view.component.ts index c8a99ffb3f..7fad70b9c7 100644 --- a/frontend/src/app/modules/work_packages/routing/wp-list-view/wp-list-view.component.ts +++ b/frontend/src/app/modules/work_packages/routing/wp-list-view/wp-list-view.component.ts @@ -26,7 +26,7 @@ // See docs/COPYRIGHT.rdoc for more details. // ++ -import {ChangeDetectionStrategy, ChangeDetectorRef, Component, Injector, OnInit} from "@angular/core"; +import {ChangeDetectionStrategy, ChangeDetectorRef, Component, Injector, OnInit, OnChanges, SimpleChanges} from "@angular/core"; import {take} from "rxjs/operators"; import {CausedUpdatesService} from "core-app/modules/boards/board/caused-updates/caused-updates.service"; import {DragAndDropService} from "core-app/modules/common/drag-and-drop/drag-and-drop.service"; @@ -44,6 +44,9 @@ import {CurrentProjectService} from "core-components/projects/current-project.se import {WorkPackageViewFiltersService} from "core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-filters.service"; import {UntilDestroyedMixin} from "core-app/helpers/angular/until-destroyed.mixin"; import {QueryResource} from "core-app/modules/hal/resources/query-resource"; +import {WorkPackageViewColumnsService} from 'core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-columns.service'; +import {InjectField} from "core-app/helpers/angular/inject-field.decorator"; + @Component({ selector: 'wp-list-view', @@ -57,7 +60,8 @@ import {QueryResource} from "core-app/modules/hal/resources/query-resource"; CausedUpdatesService ] }) -export class WorkPackageListViewComponent extends UntilDestroyedMixin implements OnInit { +export class WorkPackageListViewComponent extends UntilDestroyedMixin implements OnInit, OnChanges { + @InjectField() wpTableColumns:WorkPackageViewColumnsService; text = { 'jump_to_pagination': this.I18n.t('js.work_packages.jump_marks.pagination'), @@ -100,6 +104,7 @@ export class WorkPackageListViewComponent extends UntilDestroyedMixin implements this.querySpace.query.values$().pipe( this.untilDestroyed() ).subscribe((query) => { + console.log('this.querySpace: ', query, this.wpTableColumns.getColumns()); // Update the visible representation this.updateViewRepresentation(query); this.noResults = query.results.total === 0; @@ -107,6 +112,10 @@ export class WorkPackageListViewComponent extends UntilDestroyedMixin implements }); } + ngOnChanges(changes: SimpleChanges) { + console.log('changes: ', changes); + } + protected setupInformationLoadedListener() { this .querySpace @@ -114,6 +123,7 @@ export class WorkPackageListViewComponent extends UntilDestroyedMixin implements .values$() .pipe(take(1)) .subscribe(() => { + // console.log('this.querySpace 2: ', this.wpTableColumns.getColumns()); this.tableInformationLoaded = true; this.cdRef.detectChanges(); }); diff --git a/frontend/src/app/modules/work_packages/routing/wp-view-base/view-services/wp-view-base.service.ts b/frontend/src/app/modules/work_packages/routing/wp-view-base/view-services/wp-view-base.service.ts index c4289ce482..043e9575a4 100644 --- a/frontend/src/app/modules/work_packages/routing/wp-view-base/view-services/wp-view-base.service.ts +++ b/frontend/src/app/modules/work_packages/routing/wp-view-base/view-services/wp-view-base.service.ts @@ -37,6 +37,7 @@ import {Injectable} from "@angular/core"; @Injectable() export abstract class WorkPackageViewBaseService { + id = Math.random(); /** Internal state to push non-persisted updates */ protected updatesState = input(); @@ -64,10 +65,13 @@ export abstract class WorkPackageViewBaseService { */ public initialize(query:QueryResource, results:WorkPackageCollectionResource, schema?:QuerySchemaResource) { const initial = this.valueFromQuery(query, results)!; + // console.log('WorkPackageViewBaseService initialize: ', this.id, query, results); this.pristineState.putValue(initial); } public update(value:T) { + console.log('WorkPackageViewBaseService update: ', value); + this.updatesState.putValue(value); } diff --git a/frontend/src/app/modules/work_packages/routing/wp-view-base/view-services/wp-view-columns.service.ts b/frontend/src/app/modules/work_packages/routing/wp-view-base/view-services/wp-view-columns.service.ts index 6765ac15d5..5de27e869a 100644 --- a/frontend/src/app/modules/work_packages/routing/wp-view-base/view-services/wp-view-columns.service.ts +++ b/frontend/src/app/modules/work_packages/routing/wp-view-base/view-services/wp-view-columns.service.ts @@ -39,6 +39,12 @@ export class WorkPackageViewColumnsService extends WorkPackageQueryStateService< public constructor(readonly states:States, readonly querySpace:IsolatedQuerySpace) { super(querySpace); + console.log('WorkPackageViewColumnsService: ', states, querySpace); + } + + public initialize(query:any, results:any, schema?:any) { + super.initialize(query, results, schema); + console.log('--WorkPackageViewColumnsService initialize: ', this.lastUpdatedState.getValueOr([]), query, results); } public valueFromQuery(query:QueryResource):QueryColumn[] { @@ -149,6 +155,7 @@ export class WorkPackageViewColumnsService extends WorkPackageQueryStateService< * Update the selected columns to a new set of columns. */ public setColumns(columns:QueryColumn[]) { + // console.log('setColumns: ', columns); // Don't publish if this is the same content if (this.isCurrentlyEqualTo(columns)) { return; @@ -203,6 +210,7 @@ export class WorkPackageViewColumnsService extends WorkPackageQueryStateService< */ public addColumn(id:string, position?:number) { let columns = this.getColumns(); + // console.log('addColumn: ', columns, this.all); if (position === undefined) { position = columns.length; @@ -240,6 +248,7 @@ export class WorkPackageViewColumnsService extends WorkPackageQueryStateService< // Get the available state protected get availableState() { + // console.log('availableState: ', this.states.queries.columns, this.states.queries.columns.getValueOr([])); return this.states.queries.columns; } From 59479a6b6e6d982707fde6946b9280773f168538 Mon Sep 17 00:00:00 2001 From: Aleix Suau Date: Mon, 29 Jun 2020 14:00:15 +0200 Subject: [PATCH 02/11] Table display mode working with failing test --- .../app/components/wp-list/wp-list.service.ts | 1 - .../wp-states-initialization.service.ts | 2 - .../bcf-list-container.component.ts | 44 ++++++++++++++----- .../ifc-viewer/ifc-viewer.service.ts | 2 +- .../openproject-ifc-models.routes.ts | 3 ++ .../pages/viewer/bim-view.service.ts | 4 +- .../bim-view-toggle-dropdown.directive.ts | 25 ++++++----- .../wp-list-view/wp-list-view.component.html | 6 +-- .../wp-list-view/wp-list-view.component.ts | 18 ++------ .../view-services/wp-view-base.service.ts | 3 -- .../view-services/wp-view-columns.service.ts | 20 ++++++--- frontend/src/typings.d.ts | 4 +- .../bim_revit_addin_navigation_spec.rb | 17 +++++-- 13 files changed, 94 insertions(+), 55 deletions(-) diff --git a/frontend/src/app/components/wp-list/wp-list.service.ts b/frontend/src/app/components/wp-list/wp-list.service.ts index ae5f2db8ce..708b96dce3 100644 --- a/frontend/src/app/components/wp-list/wp-list.service.ts +++ b/frontend/src/app/components/wp-list/wp-list.service.ts @@ -204,7 +204,6 @@ export class WorkPackagesListService { * Load the query from the given state params */ public loadCurrentQueryFromParams(projectIdentifier?:string) { - console.log('loadCurrentQueryFromParams: ', projectIdentifier); return this .fromQueryParams(this.$state.params as any, projectIdentifier) .toPromise(); diff --git a/frontend/src/app/components/wp-list/wp-states-initialization.service.ts b/frontend/src/app/components/wp-list/wp-states-initialization.service.ts index daf0dec00d..c029c1e927 100644 --- a/frontend/src/app/components/wp-list/wp-states-initialization.service.ts +++ b/frontend/src/app/components/wp-list/wp-states-initialization.service.ts @@ -54,7 +54,6 @@ export class WorkPackageStatesInitializationService { * @param results */ public initialize(query:QueryResource, results:WorkPackageCollectionResource) { - console.log('WorkPackageStatesInitializationService initialize: ', query, results); this.clearStates(); // Update the (global) wp query states @@ -133,7 +132,6 @@ export class WorkPackageStatesInitializationService { } public initializeFromQuery(query:QueryResource, results:WorkPackageCollectionResource) { - // console.log('WorkPackageStatesInitializationService initializeFromQuery: ', JSON.stringify(query.columns), results); this.querySpace.query.putValue(query); this.wpTableSum.initialize(query); diff --git a/frontend/src/app/modules/bim/ifc_models/bcf/list-container/bcf-list-container.component.ts b/frontend/src/app/modules/bim/ifc_models/bcf/list-container/bcf-list-container.component.ts index 06275a6eaa..c092748423 100644 --- a/frontend/src/app/modules/bim/ifc_models/bcf/list-container/bcf-list-container.component.ts +++ b/frontend/src/app/modules/bim/ifc_models/bcf/list-container/bcf-list-container.component.ts @@ -1,4 +1,4 @@ -import {ChangeDetectionStrategy, Component, OnInit, AfterViewChecked} from "@angular/core"; +import {ChangeDetectionStrategy, Component, OnInit} from "@angular/core"; import {WorkPackageViewHandlerToken} from "core-app/modules/work_packages/routing/wp-view-base/event-handling/event-handler-registry"; import {BcfCardViewHandlerRegistry} from "core-app/modules/bim/ifc_models/ifc-base-view/event-handler/bcf-card-view-handler-registry"; import {WorkPackageListViewComponent} from "core-app/modules/work_packages/routing/wp-list-view/wp-list-view.component"; @@ -12,6 +12,8 @@ import {InjectField} from "core-app/helpers/angular/inject-field.decorator"; import {wpDisplayCardRepresentation, wpDisplayListRepresentation} from "core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-display-representation.service"; import {IfcModelsDataService} from "core-app/modules/bim/ifc_models/pages/viewer/ifc-models-data.service"; import {WorkPackageViewColumnsService} from 'core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-columns.service'; +import {UIRouterGlobals, UIRouter, TransitionService} from '@uirouter/core'; +import {pluck, distinctUntilChanged, filter} from "rxjs/operators"; @Component({ templateUrl: '/app/modules/work_packages/routing/wp-list-view/wp-list-view.component.html', @@ -24,19 +26,46 @@ import {WorkPackageViewColumnsService} from 'core-app/modules/work_packages/rout ], changeDetection: ChangeDetectionStrategy.OnPush }) -export class BcfListContainerComponent extends WorkPackageListViewComponent implements OnInit, AfterViewChecked { +export class BcfListContainerComponent extends WorkPackageListViewComponent implements OnInit { @InjectField() bimView:BimViewService; @InjectField() ifcModelsService:IfcModelsDataService; @InjectField() wpTableColumns:WorkPackageViewColumnsService; + @InjectField() uIRouterGlobals:UIRouterGlobals public wpTableConfiguration = { dragAndDropEnabled: false }; + + ngOnInit() { + super.ngOnInit(); + + // Ensure we add a bcf thumbnail column + // until we can load the initial query + this.wpTableColumns + .onReady() + .then(() => { + this.wpTableColumns.addColumn('bcfThumbnail', 2); + }); + + this.uIRouterGlobals + .params$! + .pipe( + this.untilDestroyed(), + pluck('cards'), + distinctUntilChanged(), + ) + .subscribe((cards:boolean) => { + if (cards || cards == null) { + this.wpDisplayRepresentation.setDisplayRepresentation(wpDisplayCardRepresentation); + } else { + this.wpDisplayRepresentation.setDisplayRepresentation(wpDisplayListRepresentation); + } + + this.cdRef.detectChanges(); + }); + } protected updateViewRepresentation(query:QueryResource) { - console.log('updateViewRepresentation: ', this.wpTableColumns.id, this.wpTableColumns.getColumns(), query); - this.wpTableColumns.addColumn('bcfThumbnail', 2); - if (this.wpDisplayRepresentation.current === null) { this.wpDisplayRepresentation.setDisplayRepresentation(wpDisplayCardRepresentation); } @@ -51,9 +80,4 @@ export class BcfListContainerComponent extends WorkPackageListViewComponent impl return this.bimView.currentViewerState() === bimSplitViewIdentifier; } } - - ngAfterViewChecked() { - console.log('COLUMNS: ', this.wpTableColumns.getColumns()); - // this.wpTableColumns.addColumn('bcfThumbnail', 2); - } } diff --git a/frontend/src/app/modules/bim/ifc_models/ifc-viewer/ifc-viewer.service.ts b/frontend/src/app/modules/bim/ifc_models/ifc-viewer/ifc-viewer.service.ts index d5f1bbebfd..aa08c950c0 100644 --- a/frontend/src/app/modules/bim/ifc_models/ifc-viewer/ifc-viewer.service.ts +++ b/frontend/src/app/modules/bim/ifc_models/ifc-viewer/ifc-viewer.service.ts @@ -33,7 +33,7 @@ export interface BCFLoadOptions { @Injectable() export class IFCViewerService extends ViewerBridgeService { - public shouldShowViewer = false; + public shouldShowViewer = true; private _viewer:any; private $loaded = new Subject(); diff --git a/frontend/src/app/modules/bim/ifc_models/openproject-ifc-models.routes.ts b/frontend/src/app/modules/bim/ifc_models/openproject-ifc-models.routes.ts index bb4d4edd5a..a574c648d4 100644 --- a/frontend/src/app/modules/bim/ifc_models/openproject-ifc-models.routes.ts +++ b/frontend/src/app/modules/bim/ifc_models/openproject-ifc-models.routes.ts @@ -67,6 +67,9 @@ export const IFC_ROUTES:Ng2StateDeclaration[] = [ { name: 'bim.partitioned.list', url: '/list', + params: { + cards: true, + }, data: { baseRoute: 'bim.partitioned.list', newRoute: 'bim.partitioned.list.new', diff --git a/frontend/src/app/modules/bim/ifc_models/pages/viewer/bim-view.service.ts b/frontend/src/app/modules/bim/ifc_models/pages/viewer/bim-view.service.ts index a54ac1c733..762fe2c85c 100644 --- a/frontend/src/app/modules/bim/ifc_models/pages/viewer/bim-view.service.ts +++ b/frontend/src/app/modules/bim/ifc_models/pages/viewer/bim-view.service.ts @@ -86,7 +86,9 @@ export class BimViewService implements OnDestroy { public currentViewerState():BimViewState { if (this.state.includes('bim.partitioned.list')) { - return bimListViewIdentifier; + return this.state.params?.cards ? + bimListViewIdentifier : + bimTableViewIdentifier; } else if (this.state.includes('bim.**.model')) { return bimViewerViewIdentifier; } else { diff --git a/frontend/src/app/modules/bim/ifc_models/toolbar/view-toggle/bim-view-toggle-dropdown.directive.ts b/frontend/src/app/modules/bim/ifc_models/toolbar/view-toggle/bim-view-toggle-dropdown.directive.ts index 8c38815abb..d8d8dbfde5 100644 --- a/frontend/src/app/modules/bim/ifc_models/toolbar/view-toggle/bim-view-toggle-dropdown.directive.ts +++ b/frontend/src/app/modules/bim/ifc_models/toolbar/view-toggle/bim-view-toggle-dropdown.directive.ts @@ -78,7 +78,7 @@ export class BimViewToggleDropdownDirective extends OpContextMenuTrigger { const current = this.bimView.current; const viewRoute = this.state.current.data.viewRoute; let items = this.viewerBridgeService.shouldShowViewer ? - [bimViewerViewIdentifier, bimListViewIdentifier, bimSplitViewIdentifier] : + [bimViewerViewIdentifier, bimListViewIdentifier, bimSplitViewIdentifier, bimTableViewIdentifier] : [bimListViewIdentifier, bimTableViewIdentifier]; this.items = items @@ -94,19 +94,22 @@ export class BimViewToggleDropdownDirective extends OpContextMenuTrigger { } switch (key) { + // This project controls the view representation of the data through + // the wpDisplayRepresentation service that modifies the QuerySpace + // to inform the component about which display mode is active + // (this.querySpace.query.live$). + // Under the hood it is done by modifying the params of actual route. + // Because of that, it is no possible to call this.state.go and + // this.wpDisplayRepresentation.setDisplayRepresentation at the same + // time, it raises a route error (The transition has been superseded by + // a different transition...). Is this why we are passing a cards params + // to inform the view about the display representation mode it has to + // show (cards or list). case bimListViewIdentifier: - console.log('this.state.current: ', this.state.current); - this.wpDisplayRepresentation.setDisplayRepresentation(wpDisplayCardRepresentation); - if (this.state.current.name !== 'bim.partitioned.list') { - this.state.go('bim.partitioned.list'); - } + this.state.go('bim.partitioned.list', {cards: true}); break; case bimTableViewIdentifier: - console.log('this.state.current 2: ', this.state.current); - this.wpDisplayRepresentation.setDisplayRepresentation(wpDisplayListRepresentation); - if (this.state.current.name !== 'bim.partitioned.list') { - this.state.go('bim.partitioned.list'); - } + this.state.go('bim.partitioned.list', {cards: false}); break; case bimViewerViewIdentifier: this.state.go('bim.partitioned.model'); diff --git a/frontend/src/app/modules/work_packages/routing/wp-list-view/wp-list-view.component.html b/frontend/src/app/modules/work_packages/routing/wp-list-view/wp-list-view.component.html index f4c83cc780..4785cb7379 100644 --- a/frontend/src/app/modules/work_packages/routing/wp-list-view/wp-list-view.component.html +++ b/frontend/src/app/modules/work_packages/routing/wp-list-view/wp-list-view.component.html @@ -1,14 +1,14 @@
+ *ngIf="(showResultOverlay$ | async) && showTableView"> - -
{ - console.log('this.querySpace: ', query, this.wpTableColumns.getColumns()); // Update the visible representation this.updateViewRepresentation(query); this.noResults = query.results.total === 0; @@ -112,10 +107,6 @@ export class WorkPackageListViewComponent extends UntilDestroyedMixin implements }); } - ngOnChanges(changes: SimpleChanges) { - console.log('changes: ', changes); - } - protected setupInformationLoadedListener() { this .querySpace @@ -123,7 +114,6 @@ export class WorkPackageListViewComponent extends UntilDestroyedMixin implements .values$() .pipe(take(1)) .subscribe(() => { - // console.log('this.querySpace 2: ', this.wpTableColumns.getColumns()); this.tableInformationLoaded = true; this.cdRef.detectChanges(); }); @@ -134,7 +124,7 @@ export class WorkPackageListViewComponent extends UntilDestroyedMixin implements } protected updateViewRepresentation(query:QueryResource) { - this.showListView = !(this.deviceService.isMobile || + this.showTableView = !(this.deviceService.isMobile || this.wpDisplayRepresentation.valueFromQuery(query) === wpDisplayCardRepresentation); } } diff --git a/frontend/src/app/modules/work_packages/routing/wp-view-base/view-services/wp-view-base.service.ts b/frontend/src/app/modules/work_packages/routing/wp-view-base/view-services/wp-view-base.service.ts index 043e9575a4..2dabbcad48 100644 --- a/frontend/src/app/modules/work_packages/routing/wp-view-base/view-services/wp-view-base.service.ts +++ b/frontend/src/app/modules/work_packages/routing/wp-view-base/view-services/wp-view-base.service.ts @@ -65,13 +65,10 @@ export abstract class WorkPackageViewBaseService { */ public initialize(query:QueryResource, results:WorkPackageCollectionResource, schema?:QuerySchemaResource) { const initial = this.valueFromQuery(query, results)!; - // console.log('WorkPackageViewBaseService initialize: ', this.id, query, results); this.pristineState.putValue(initial); } public update(value:T) { - console.log('WorkPackageViewBaseService update: ', value); - this.updatesState.putValue(value); } diff --git a/frontend/src/app/modules/work_packages/routing/wp-view-base/view-services/wp-view-columns.service.ts b/frontend/src/app/modules/work_packages/routing/wp-view-base/view-services/wp-view-columns.service.ts index 5de27e869a..b98c0ed371 100644 --- a/frontend/src/app/modules/work_packages/routing/wp-view-base/view-services/wp-view-columns.service.ts +++ b/frontend/src/app/modules/work_packages/routing/wp-view-base/view-services/wp-view-columns.service.ts @@ -33,18 +33,18 @@ import {States} from 'core-components/states.service'; import {Injectable} from '@angular/core'; import {cloneHalResourceCollection} from 'core-app/modules/hal/helpers/hal-resource-builder'; import {QueryColumn, queryColumnTypes} from "core-components/wp-query/query-column"; +import {combine} from "reactivestates"; +import {mapTo, take} from "rxjs/operators"; @Injectable() export class WorkPackageViewColumnsService extends WorkPackageQueryStateService { public constructor(readonly states:States, readonly querySpace:IsolatedQuerySpace) { super(querySpace); - console.log('WorkPackageViewColumnsService: ', states, querySpace); } public initialize(query:any, results:any, schema?:any) { super.initialize(query, results, schema); - console.log('--WorkPackageViewColumnsService initialize: ', this.lastUpdatedState.getValueOr([]), query, results); } public valueFromQuery(query:QueryResource):QueryColumn[] { @@ -155,7 +155,6 @@ export class WorkPackageViewColumnsService extends WorkPackageQueryStateService< * Update the selected columns to a new set of columns. */ public setColumns(columns:QueryColumn[]) { - // console.log('setColumns: ', columns); // Don't publish if this is the same content if (this.isCurrentlyEqualTo(columns)) { return; @@ -210,7 +209,6 @@ export class WorkPackageViewColumnsService extends WorkPackageQueryStateService< */ public addColumn(id:string, position?:number) { let columns = this.getColumns(); - // console.log('addColumn: ', columns, this.all); if (position === undefined) { position = columns.length; @@ -248,7 +246,6 @@ export class WorkPackageViewColumnsService extends WorkPackageQueryStateService< // Get the available state protected get availableState() { - // console.log('availableState: ', this.states.queries.columns, this.states.queries.columns.getValueOr([])); return this.states.queries.columns; } @@ -278,4 +275,17 @@ export class WorkPackageViewColumnsService extends WorkPackageQueryStateService< public get unused():QueryColumn[] { return _.differenceBy(this.all, this.getColumns(), '$href'); } + + /** + * Columns service depends on two states + */ + public onReady() { + return combine(this.pristineState, this.availableState) + .values$() + .pipe( + take(1), + mapTo(null) + ) + .toPromise(); + } } diff --git a/frontend/src/typings.d.ts b/frontend/src/typings.d.ts index bf3a323bef..5a0a30bcc1 100644 --- a/frontend/src/typings.d.ts +++ b/frontend/src/typings.d.ts @@ -1,5 +1,7 @@ /// - +// Explicitly add UiRouterRx typings (in order to use params$ type) +// https://github.com/ui-router/angular/issues/166 +/// /* SystemJS module definition */ declare var module:NodeModule; declare module 'dom-plane' { diff --git a/modules/bim/spec/features/bim_revit_addin_navigation_spec.rb b/modules/bim/spec/features/bim_revit_addin_navigation_spec.rb index e3d61f4e4a..6b666b6fb3 100644 --- a/modules/bim/spec/features/bim_revit_addin_navigation_spec.rb +++ b/modules/bim/spec/features/bim_revit_addin_navigation_spec.rb @@ -33,9 +33,10 @@ describe 'BIM Revit Add-in navigation spec', with_config: { edition: 'bim' }, js: true, driver: :chrome_headless_revit_addin do - let(:project) { FactoryBot.create :project, enabled_module_names: %i[bim work_package_tracking] } + let(:project) { FactoryBot.create :project, enabled_module_names: [:bim, :work_package_tracking] } let!(:work_package) { FactoryBot.create(:work_package, project: project) } let(:role) { FactoryBot.create(:role, permissions: %i[view_ifc_models manage_ifc_models view_work_packages]) } + let(:wp_table) { ::Pages::WorkPackagesTable.new(project) } let(:user) do FactoryBot.create :user, @@ -59,7 +60,17 @@ describe 'BIM Revit Add-in navigation spec', model_page.model_viewer_visible false end - it 'has no viewer options' do - model_page.has_no_menu_item_with_text? 'Viewer' + it 'shows a toolbar' do + model_page.page_shows_a_toolbar true + end + + it 'menu has no viewer options' do + model_page.has_no_menu_item_with_text 'Viewer' + end + + it 'can switch to the Table view mode' do + model_page.switch_view 'Table' + expect(page).to have_selector('.work-package-table') + wp_table.expect_work_package_listed work_package end end From d29a2c6179243c47fc060e8008c3c733882e764d Mon Sep 17 00:00:00 2001 From: Wieland Lindenthal Date: Tue, 9 Jun 2020 15:49:58 +0200 Subject: [PATCH 03/11] Added Revit test configuration and some tests --- config/middleware.rb | 5 ++++ lib/request_headers.rb | 23 +++++++++++++++++++ .../bim_revit_addin_navigation_spec.rb | 2 +- spec/support/capybara_headers.rb | 17 ++++++++++++++ 4 files changed, 46 insertions(+), 1 deletion(-) create mode 100644 config/middleware.rb create mode 100644 lib/request_headers.rb create mode 100644 spec/support/capybara_headers.rb diff --git a/config/middleware.rb b/config/middleware.rb new file mode 100644 index 0000000000..050edcafe9 --- /dev/null +++ b/config/middleware.rb @@ -0,0 +1,5 @@ +require 'request_headers' + +if %w(test).include?(Rails.env) + Rails.application.config.middleware.insert_before Rack::Lock, "RequestHeaders", CustomHeadersHelper +end \ No newline at end of file diff --git a/lib/request_headers.rb b/lib/request_headers.rb new file mode 100644 index 0000000000..b30215ae37 --- /dev/null +++ b/lib/request_headers.rb @@ -0,0 +1,23 @@ +class CustomHeadersHelper + cattr_accessor :headers +end + +class RequestHeaders + def initialize(app, helper = nil) + @app, @helper = app, helper + end + + def call(env) + if @helper + headers = @helper.headers + + if headers.is_a?(Hash) + headers.each do |k,v| + env["HTTP_#{k.upcase.gsub("-", "_")}"] = v + end + end + end + + @app.call(env) + end +end \ No newline at end of file diff --git a/modules/bim/spec/features/bim_revit_addin_navigation_spec.rb b/modules/bim/spec/features/bim_revit_addin_navigation_spec.rb index 6b666b6fb3..7bd3bfbe34 100644 --- a/modules/bim/spec/features/bim_revit_addin_navigation_spec.rb +++ b/modules/bim/spec/features/bim_revit_addin_navigation_spec.rb @@ -65,7 +65,7 @@ describe 'BIM Revit Add-in navigation spec', end it 'menu has no viewer options' do - model_page.has_no_menu_item_with_text 'Viewer' + model_page.has_no_menu_item_with_text? 'Viewer' end it 'can switch to the Table view mode' do diff --git a/spec/support/capybara_headers.rb b/spec/support/capybara_headers.rb new file mode 100644 index 0000000000..64d5918957 --- /dev/null +++ b/spec/support/capybara_headers.rb @@ -0,0 +1,17 @@ +require 'request_headers' + +module CapybaraHeaderHelpers + shared_context 'in Revit' do + before(:each) { add_headers('User-Agent' => 'foo bar Revit') } + end + + def add_headers(custom_headers) + if Capybara.current_driver == :rack_test + custom_headers.each do |name, value| + page.driver.browser.header(name, value) + end + else + CustomHeadersHelper.headers = custom_headers + end + end +end \ No newline at end of file From 44e54cafc95bf322914f67e0b4bb2751e7932316 Mon Sep 17 00:00:00 2001 From: Aleix Suau Date: Mon, 29 Jun 2020 16:51:36 +0200 Subject: [PATCH 04/11] Remove unnecessary variable + improve comments --- .../bim-view-toggle-dropdown.directive.ts | 12 ++++++------ .../view-services/wp-view-base.service.ts | 2 -- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/frontend/src/app/modules/bim/ifc_models/toolbar/view-toggle/bim-view-toggle-dropdown.directive.ts b/frontend/src/app/modules/bim/ifc_models/toolbar/view-toggle/bim-view-toggle-dropdown.directive.ts index d8d8dbfde5..fe352a6c0d 100644 --- a/frontend/src/app/modules/bim/ifc_models/toolbar/view-toggle/bim-view-toggle-dropdown.directive.ts +++ b/frontend/src/app/modules/bim/ifc_models/toolbar/view-toggle/bim-view-toggle-dropdown.directive.ts @@ -96,15 +96,15 @@ export class BimViewToggleDropdownDirective extends OpContextMenuTrigger { switch (key) { // This project controls the view representation of the data through // the wpDisplayRepresentation service that modifies the QuerySpace - // to inform the component about which display mode is active - // (this.querySpace.query.live$). + // to inform the rest of the app about which display mode is currently + // active (this.querySpace.query.live$). // Under the hood it is done by modifying the params of actual route. - // Because of that, it is no possible to call this.state.go and + // Because of that, it is not possible to call this.state.go and // this.wpDisplayRepresentation.setDisplayRepresentation at the same // time, it raises a route error (The transition has been superseded by - // a different transition...). Is this why we are passing a cards params - // to inform the view about the display representation mode it has to - // show (cards or list). + // a different transition...). To avoid this error, we are passing + // a cards params to inform the view about the display representation mode + // it has to show (cards or list). case bimListViewIdentifier: this.state.go('bim.partitioned.list', {cards: true}); break; diff --git a/frontend/src/app/modules/work_packages/routing/wp-view-base/view-services/wp-view-base.service.ts b/frontend/src/app/modules/work_packages/routing/wp-view-base/view-services/wp-view-base.service.ts index 2dabbcad48..76069d51c9 100644 --- a/frontend/src/app/modules/work_packages/routing/wp-view-base/view-services/wp-view-base.service.ts +++ b/frontend/src/app/modules/work_packages/routing/wp-view-base/view-services/wp-view-base.service.ts @@ -37,8 +37,6 @@ import {Injectable} from "@angular/core"; @Injectable() export abstract class WorkPackageViewBaseService { - id = Math.random(); - /** Internal state to push non-persisted updates */ protected updatesState = input(); From 56e9f1d086a600f8c32868a673763d52d0ff690b Mon Sep 17 00:00:00 2001 From: Aleix Suau Date: Tue, 30 Jun 2020 10:22:01 +0200 Subject: [PATCH 05/11] Code climate fixes --- config/middleware.rb | 2 +- .../bcf/list-container/bcf-list-container.component.ts | 10 ++++------ .../view-toggle/bim-view-toggle-dropdown.directive.ts | 2 +- lib/request_headers.rb | 9 +++++---- .../spec/features/bim_revit_addin_navigation_spec.rb | 4 ++-- 5 files changed, 13 insertions(+), 14 deletions(-) diff --git a/config/middleware.rb b/config/middleware.rb index 050edcafe9..e96062df33 100644 --- a/config/middleware.rb +++ b/config/middleware.rb @@ -2,4 +2,4 @@ require 'request_headers' if %w(test).include?(Rails.env) Rails.application.config.middleware.insert_before Rack::Lock, "RequestHeaders", CustomHeadersHelper -end \ No newline at end of file +end diff --git a/frontend/src/app/modules/bim/ifc_models/bcf/list-container/bcf-list-container.component.ts b/frontend/src/app/modules/bim/ifc_models/bcf/list-container/bcf-list-container.component.ts index c092748423..ba234a270b 100644 --- a/frontend/src/app/modules/bim/ifc_models/bcf/list-container/bcf-list-container.component.ts +++ b/frontend/src/app/modules/bim/ifc_models/bcf/list-container/bcf-list-container.component.ts @@ -26,11 +26,11 @@ import {pluck, distinctUntilChanged, filter} from "rxjs/operators"; ], changeDetection: ChangeDetectionStrategy.OnPush }) -export class BcfListContainerComponent extends WorkPackageListViewComponent implements OnInit { +export class BcfListContainerComponent extends WorkPackageListViewComponent implements OnInit { @InjectField() bimView:BimViewService; @InjectField() ifcModelsService:IfcModelsDataService; @InjectField() wpTableColumns:WorkPackageViewColumnsService; - @InjectField() uIRouterGlobals:UIRouterGlobals + @InjectField() uIRouterGlobals:UIRouterGlobals; public wpTableConfiguration = { dragAndDropEnabled: false @@ -43,9 +43,7 @@ export class BcfListContainerComponent extends WorkPackageListViewComponent impl // until we can load the initial query this.wpTableColumns .onReady() - .then(() => { - this.wpTableColumns.addColumn('bcfThumbnail', 2); - }); + .then(() => this.wpTableColumns.addColumn('bcfThumbnail', 2)); this.uIRouterGlobals .params$! @@ -64,7 +62,7 @@ export class BcfListContainerComponent extends WorkPackageListViewComponent impl this.cdRef.detectChanges(); }); } - + protected updateViewRepresentation(query:QueryResource) { if (this.wpDisplayRepresentation.current === null) { this.wpDisplayRepresentation.setDisplayRepresentation(wpDisplayCardRepresentation); diff --git a/frontend/src/app/modules/bim/ifc_models/toolbar/view-toggle/bim-view-toggle-dropdown.directive.ts b/frontend/src/app/modules/bim/ifc_models/toolbar/view-toggle/bim-view-toggle-dropdown.directive.ts index fe352a6c0d..b6a89f35cf 100644 --- a/frontend/src/app/modules/bim/ifc_models/toolbar/view-toggle/bim-view-toggle-dropdown.directive.ts +++ b/frontend/src/app/modules/bim/ifc_models/toolbar/view-toggle/bim-view-toggle-dropdown.directive.ts @@ -101,7 +101,7 @@ export class BimViewToggleDropdownDirective extends OpContextMenuTrigger { // Under the hood it is done by modifying the params of actual route. // Because of that, it is not possible to call this.state.go and // this.wpDisplayRepresentation.setDisplayRepresentation at the same - // time, it raises a route error (The transition has been superseded by + // time, it raises a route error (The transition has been superseded by // a different transition...). To avoid this error, we are passing // a cards params to inform the view about the display representation mode // it has to show (cards or list). diff --git a/lib/request_headers.rb b/lib/request_headers.rb index b30215ae37..8450450ac5 100644 --- a/lib/request_headers.rb +++ b/lib/request_headers.rb @@ -4,7 +4,8 @@ end class RequestHeaders def initialize(app, helper = nil) - @app, @helper = app, helper + @app = app + @helper = helper end def call(env) @@ -12,12 +13,12 @@ class RequestHeaders headers = @helper.headers if headers.is_a?(Hash) - headers.each do |k,v| - env["HTTP_#{k.upcase.gsub("-", "_")}"] = v + headers.each do |k, v| + env["HTTP_#{k.upcase.gsub('-', '_')}"] = v end end end @app.call(env) end -end \ No newline at end of file +end diff --git a/modules/bim/spec/features/bim_revit_addin_navigation_spec.rb b/modules/bim/spec/features/bim_revit_addin_navigation_spec.rb index 7bd3bfbe34..261a068d64 100644 --- a/modules/bim/spec/features/bim_revit_addin_navigation_spec.rb +++ b/modules/bim/spec/features/bim_revit_addin_navigation_spec.rb @@ -33,7 +33,7 @@ describe 'BIM Revit Add-in navigation spec', with_config: { edition: 'bim' }, js: true, driver: :chrome_headless_revit_addin do - let(:project) { FactoryBot.create :project, enabled_module_names: [:bim, :work_package_tracking] } + let(:project) { FactoryBot.create :project, enabled_module_names: %i[bim work_package_tracking] } let!(:work_package) { FactoryBot.create(:work_package, project: project) } let(:role) { FactoryBot.create(:role, permissions: %i[view_ifc_models manage_ifc_models view_work_packages]) } let(:wp_table) { ::Pages::WorkPackagesTable.new(project) } @@ -63,7 +63,7 @@ describe 'BIM Revit Add-in navigation spec', it 'shows a toolbar' do model_page.page_shows_a_toolbar true end - + it 'menu has no viewer options' do model_page.has_no_menu_item_with_text? 'Viewer' end From 31f2a4213f92a3cb0a6db8e40ae2c9a9f2587e82 Mon Sep 17 00:00:00 2001 From: Aleix Suau Date: Tue, 7 Jul 2020 18:04:12 +0200 Subject: [PATCH 06/11] Viewer and Table display mode without icon --- .../bcf-list-container.component.ts | 18 ++++++++---------- .../openproject-ifc-models.routes.ts | 7 ++----- .../pages/viewer/bim-view.service.ts | 17 +++++++++++------ .../bim-view-toggle-dropdown.directive.ts | 11 +++++++---- modules/bim/config/locales/js-en.yml | 3 ++- 5 files changed, 30 insertions(+), 26 deletions(-) diff --git a/frontend/src/app/modules/bim/ifc_models/bcf/list-container/bcf-list-container.component.ts b/frontend/src/app/modules/bim/ifc_models/bcf/list-container/bcf-list-container.component.ts index ba234a270b..84f740b581 100644 --- a/frontend/src/app/modules/bim/ifc_models/bcf/list-container/bcf-list-container.component.ts +++ b/frontend/src/app/modules/bim/ifc_models/bcf/list-container/bcf-list-container.component.ts @@ -7,7 +7,7 @@ import {HalResourceNotificationService} from "core-app/modules/hal/services/hal- import {WorkPackageNotificationService} from "core-app/modules/work_packages/notifications/work-package-notification.service"; import {DragAndDropService} from "core-app/modules/common/drag-and-drop/drag-and-drop.service"; import {CausedUpdatesService} from "core-app/modules/boards/board/caused-updates/caused-updates.service"; -import {bimSplitViewIdentifier, BimViewService} from "core-app/modules/bim/ifc_models/pages/viewer/bim-view.service"; +import {bimSplitViewCardsIdentifier, bimSplitViewListIdentifier, BimViewService} from "core-app/modules/bim/ifc_models/pages/viewer/bim-view.service"; import {InjectField} from "core-app/helpers/angular/inject-field.decorator"; import {wpDisplayCardRepresentation, wpDisplayListRepresentation} from "core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-display-representation.service"; import {IfcModelsDataService} from "core-app/modules/bim/ifc_models/pages/viewer/ifc-models-data.service"; @@ -53,10 +53,10 @@ export class BcfListContainerComponent extends WorkPackageListViewComponent impl distinctUntilChanged(), ) .subscribe((cards:boolean) => { - if (cards || cards == null) { - this.wpDisplayRepresentation.setDisplayRepresentation(wpDisplayCardRepresentation); + if (cards == null || cards || this.deviceService.isMobile) { + this.showTableView = false; } else { - this.wpDisplayRepresentation.setDisplayRepresentation(wpDisplayListRepresentation); + this.showTableView = true; } this.cdRef.detectChanges(); @@ -64,18 +64,16 @@ export class BcfListContainerComponent extends WorkPackageListViewComponent impl } protected updateViewRepresentation(query:QueryResource) { - if (this.wpDisplayRepresentation.current === null) { - this.wpDisplayRepresentation.setDisplayRepresentation(wpDisplayCardRepresentation); - } - - super.updateViewRepresentation(query); + // Overwrite the parent method because we are setting the view + // above through the cards parameter (showTableView) } protected showResizerInCardView():boolean { if (this.noResults && this.ifcModelsService.models.length === 0) { return false; } else { - return this.bimView.currentViewerState() === bimSplitViewIdentifier; + return this.bimView.currentViewerState() === bimSplitViewCardsIdentifier || + this.bimView.currentViewerState() === bimSplitViewListIdentifier; } } } diff --git a/frontend/src/app/modules/bim/ifc_models/openproject-ifc-models.routes.ts b/frontend/src/app/modules/bim/ifc_models/openproject-ifc-models.routes.ts index a574c648d4..4a9e5a7d88 100644 --- a/frontend/src/app/modules/bim/ifc_models/openproject-ifc-models.routes.ts +++ b/frontend/src/app/modules/bim/ifc_models/openproject-ifc-models.routes.ts @@ -66,10 +66,7 @@ export const IFC_ROUTES:Ng2StateDeclaration[] = [ }, { name: 'bim.partitioned.list', - url: '/list', - params: { - cards: true, - }, + url: '/list?{cards:bool}', data: { baseRoute: 'bim.partitioned.list', newRoute: 'bim.partitioned.list.new', @@ -82,7 +79,7 @@ export const IFC_ROUTES:Ng2StateDeclaration[] = [ }, { name: 'bim.partitioned.split', - url: '/split', + url: '/split?{cards:bool}', data: { baseRoute: 'bim.partitioned.split', partition: '-split', diff --git a/frontend/src/app/modules/bim/ifc_models/pages/viewer/bim-view.service.ts b/frontend/src/app/modules/bim/ifc_models/pages/viewer/bim-view.service.ts index 762fe2c85c..80c5ed9cc0 100644 --- a/frontend/src/app/modules/bim/ifc_models/pages/viewer/bim-view.service.ts +++ b/frontend/src/app/modules/bim/ifc_models/pages/viewer/bim-view.service.ts @@ -36,10 +36,11 @@ import {takeUntil} from "rxjs/operators"; export const bimListViewIdentifier = 'list'; export const bimTableViewIdentifier = 'table'; -export const bimSplitViewIdentifier = 'split'; +export const bimSplitViewCardsIdentifier = 'splitCards'; +export const bimSplitViewListIdentifier = 'splitList'; export const bimViewerViewIdentifier = 'viewer'; -export type BimViewState = 'list'|'viewer'|'split'|'table'; +export type BimViewState = 'list'|'viewer'|'splitList'|'splitCards'|'table'; @Injectable() export class BimViewService implements OnDestroy { @@ -48,14 +49,16 @@ export class BimViewService implements OnDestroy { public text:any = { list: this.I18n.t('js.views.card'), viewer: this.I18n.t('js.ifc_models.views.viewer'), - split: this.I18n.t('js.ifc_models.views.split'), + splitList: this.I18n.t('js.ifc_models.views.split'), + splitCards: this.I18n.t('js.ifc_models.views.split-cards'), table: this.I18n.t('js.views.list'), }; public icon:any = { list: 'icon-view-card', viewer: 'icon-view-model', - split: 'icon-view-split2', + splitList: 'icon-view-split2', + splitCards: 'icon-view-split2', table: 'icon-view-list', }; @@ -81,7 +84,7 @@ export class BimViewService implements OnDestroy { } get current():BimViewState { - return this._state.getValueOr(bimSplitViewIdentifier); + return this._state.getValueOr(bimSplitViewCardsIdentifier); } public currentViewerState():BimViewState { @@ -92,7 +95,9 @@ export class BimViewService implements OnDestroy { } else if (this.state.includes('bim.**.model')) { return bimViewerViewIdentifier; } else { - return bimSplitViewIdentifier; + return this.state.params?.cards || this.state.params?.cards == null ? + bimSplitViewCardsIdentifier : + bimSplitViewListIdentifier; } } diff --git a/frontend/src/app/modules/bim/ifc_models/toolbar/view-toggle/bim-view-toggle-dropdown.directive.ts b/frontend/src/app/modules/bim/ifc_models/toolbar/view-toggle/bim-view-toggle-dropdown.directive.ts index b6a89f35cf..7a5e8442ec 100644 --- a/frontend/src/app/modules/bim/ifc_models/toolbar/view-toggle/bim-view-toggle-dropdown.directive.ts +++ b/frontend/src/app/modules/bim/ifc_models/toolbar/view-toggle/bim-view-toggle-dropdown.directive.ts @@ -34,7 +34,7 @@ import {StateService} from "@uirouter/core"; import {WorkPackageFiltersService} from "core-components/filters/wp-filters/wp-filters.service"; import { - bimListViewIdentifier, bimSplitViewIdentifier, bimTableViewIdentifier, + bimListViewIdentifier, bimSplitViewListIdentifier, bimSplitViewCardsIdentifier, bimTableViewIdentifier, bimViewerViewIdentifier, BimViewService } from "core-app/modules/bim/ifc_models/pages/viewer/bim-view.service"; @@ -78,7 +78,7 @@ export class BimViewToggleDropdownDirective extends OpContextMenuTrigger { const current = this.bimView.current; const viewRoute = this.state.current.data.viewRoute; let items = this.viewerBridgeService.shouldShowViewer ? - [bimViewerViewIdentifier, bimListViewIdentifier, bimSplitViewIdentifier, bimTableViewIdentifier] : + [bimViewerViewIdentifier, bimListViewIdentifier, bimSplitViewCardsIdentifier, bimSplitViewListIdentifier, bimTableViewIdentifier] : [bimListViewIdentifier, bimTableViewIdentifier]; this.items = items @@ -114,8 +114,11 @@ export class BimViewToggleDropdownDirective extends OpContextMenuTrigger { case bimViewerViewIdentifier: this.state.go('bim.partitioned.model'); break; - case bimSplitViewIdentifier: - this.state.go('bim.partitioned.split'); + case bimSplitViewCardsIdentifier: + this.state.go('bim.partitioned.split', {cards: true}); + break; + case bimSplitViewListIdentifier: + this.state.go('bim.partitioned.split', {cards: false}); break; } diff --git a/modules/bim/config/locales/js-en.yml b/modules/bim/config/locales/js-en.yml index d49e07780b..fc3e7a1bfa 100644 --- a/modules/bim/config/locales/js-en.yml +++ b/modules/bim/config/locales/js-en.yml @@ -18,4 +18,5 @@ en: manage: 'Manage models' views: viewer: 'Viewer' - split: 'Viewer and cards' + split: 'Viewer and table' + split-cards: 'Viewer and cards' From 6871f39db00a7f53e4e8de163cd680cbf5b9ba3e Mon Sep 17 00:00:00 2001 From: Aleix Suau Date: Mon, 13 Jul 2020 13:59:45 +0200 Subject: [PATCH 07/11] Showing proper 'Viewer and Table' icon + removed spanish translation --- .../app/modules/bim/ifc_models/pages/viewer/bim-view.service.ts | 2 +- .../routing/wp-list-view/wp-list-view.component.html | 2 +- modules/bim/config/locales/crowdin/js-es.yml | 1 - 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/frontend/src/app/modules/bim/ifc_models/pages/viewer/bim-view.service.ts b/frontend/src/app/modules/bim/ifc_models/pages/viewer/bim-view.service.ts index 80c5ed9cc0..28e391e521 100644 --- a/frontend/src/app/modules/bim/ifc_models/pages/viewer/bim-view.service.ts +++ b/frontend/src/app/modules/bim/ifc_models/pages/viewer/bim-view.service.ts @@ -57,7 +57,7 @@ export class BimViewService implements OnDestroy { public icon:any = { list: 'icon-view-card', viewer: 'icon-view-model', - splitList: 'icon-view-split2', + splitList: 'icon-view-split-viewer-table', splitCards: 'icon-view-split2', table: 'icon-view-list', }; diff --git a/frontend/src/app/modules/work_packages/routing/wp-list-view/wp-list-view.component.html b/frontend/src/app/modules/work_packages/routing/wp-list-view/wp-list-view.component.html index 4785cb7379..b75b8c2cb9 100644 --- a/frontend/src/app/modules/work_packages/routing/wp-list-view/wp-list-view.component.html +++ b/frontend/src/app/modules/work_packages/routing/wp-list-view/wp-list-view.component.html @@ -5,7 +5,7 @@ + class="work-packages-split-view--tabletimeline-content">commit
Date: Mon, 13 Jul 2020 18:57:58 +0200 Subject: [PATCH 08/11] BcfListContainer with own template + Viewer and Table display mode working with resizer --- .../bcf-list-container.component.sass | 35 +++++++++++++++++++ .../bcf-list-container.component.ts | 6 ++-- .../bfc-list-container.component.html | 33 +++++++++++++++++ .../wp-list-view/wp-list-view.component.html | 3 +- .../wp-list-view/wp-list-view.component.sass | 14 ++++++++ .../wp-list-view/wp-list-view.component.ts | 2 +- 6 files changed, 88 insertions(+), 5 deletions(-) create mode 100644 frontend/src/app/modules/bim/ifc_models/bcf/list-container/bcf-list-container.component.sass create mode 100644 frontend/src/app/modules/bim/ifc_models/bcf/list-container/bfc-list-container.component.html diff --git a/frontend/src/app/modules/bim/ifc_models/bcf/list-container/bcf-list-container.component.sass b/frontend/src/app/modules/bim/ifc_models/bcf/list-container/bcf-list-container.component.sass new file mode 100644 index 0000000000..acfc13077f --- /dev/null +++ b/frontend/src/app/modules/bim/ifc_models/bcf/list-container/bcf-list-container.component.sass @@ -0,0 +1,35 @@ +@import "helpers" + +.result-overlay + @include overlay-background + background-color: #FFFFFF + opacity: 0.5 + +.work-packages--card-view-container + width: 100% + overflow: auto + padding-bottom: 5px + @include styled-scroll-bar + + @media screen and (min-width: 679px) + &.-with-resizer + padding-left: 10px + + @media screen and (max-width: 679px) + // Ensure the WP cards span the complete width on mobile + // --> Move scrollbar out of visible area + min-width: calc(100vw + 10px) + +.work-packages-split-view--tabletimeline-container + display: flex + flex: 1 1 auto + @include styled-scroll-bar + + @media screen and (min-width: 679px) + &.-with-resizer + padding-left: 10px + + @media screen and (max-width: 679px) + // Ensure the WP cards span the complete width on mobile + // --> Move scrollbar out of visible area + min-width: calc(100vw + 10px) \ No newline at end of file diff --git a/frontend/src/app/modules/bim/ifc_models/bcf/list-container/bcf-list-container.component.ts b/frontend/src/app/modules/bim/ifc_models/bcf/list-container/bcf-list-container.component.ts index 84f740b581..84e2e1fbb8 100644 --- a/frontend/src/app/modules/bim/ifc_models/bcf/list-container/bcf-list-container.component.ts +++ b/frontend/src/app/modules/bim/ifc_models/bcf/list-container/bcf-list-container.component.ts @@ -16,8 +16,8 @@ import {UIRouterGlobals, UIRouter, TransitionService} from '@uirouter/core'; import {pluck, distinctUntilChanged, filter} from "rxjs/operators"; @Component({ - templateUrl: '/app/modules/work_packages/routing/wp-list-view/wp-list-view.component.html', - styleUrls: ['/app/modules/work_packages/routing/wp-list-view/wp-list-view.component.sass'], + templateUrl: '/app/modules/bim/ifc_models/bcf/list-container/bfc-list-container.component.html', + styleUrls: ['/app/modules/bim/ifc_models/bcf/list-container/bcf-list-container.component.sass'], providers: [ { provide: WorkPackageViewHandlerToken, useValue: BcfCardViewHandlerRegistry }, { provide: HalResourceNotificationService, useClass: WorkPackageNotificationService }, @@ -68,7 +68,7 @@ export class BcfListContainerComponent extends WorkPackageListViewComponent impl // above through the cards parameter (showTableView) } - protected showResizerInCardView():boolean { + public showResizerInCardView():boolean { if (this.noResults && this.ifcModelsService.models.length === 0) { return false; } else { diff --git a/frontend/src/app/modules/bim/ifc_models/bcf/list-container/bfc-list-container.component.html b/frontend/src/app/modules/bim/ifc_models/bcf/list-container/bfc-list-container.component.html new file mode 100644 index 0000000000..d749711216 --- /dev/null +++ b/frontend/src/app/modules/bim/ifc_models/bcf/list-container/bfc-list-container.component.html @@ -0,0 +1,33 @@ +
+ + +
+ + + + + +
+ + +
+ + +
+ + + diff --git a/frontend/src/app/modules/work_packages/routing/wp-list-view/wp-list-view.component.html b/frontend/src/app/modules/work_packages/routing/wp-list-view/wp-list-view.component.html index b75b8c2cb9..d65af3c53a 100644 --- a/frontend/src/app/modules/work_packages/routing/wp-list-view/wp-list-view.component.html +++ b/frontend/src/app/modules/work_packages/routing/wp-list-view/wp-list-view.component.html @@ -5,7 +5,8 @@ commit + class="work-packages-split-view--tabletimeline-content"> +
Move scrollbar out of visible area min-width: calc(100vw + 10px) + +.work-packages-split-view--tabletimeline-container + display: flex + flex: 1 1 100% + @include styled-scroll-bar + + @media screen and (min-width: 679px) + &.-with-resizer + padding-left: 10px + + @media screen and (max-width: 679px) + // Ensure the WP cards span the complete width on mobile + // --> Move scrollbar out of visible area + min-width: calc(100vw + 10px) diff --git a/frontend/src/app/modules/work_packages/routing/wp-list-view/wp-list-view.component.ts b/frontend/src/app/modules/work_packages/routing/wp-list-view/wp-list-view.component.ts index 663f53674d..be357034bf 100644 --- a/frontend/src/app/modules/work_packages/routing/wp-list-view/wp-list-view.component.ts +++ b/frontend/src/app/modules/work_packages/routing/wp-list-view/wp-list-view.component.ts @@ -119,7 +119,7 @@ export class WorkPackageListViewComponent extends UntilDestroyedMixin implements }); } - protected showResizerInCardView():boolean { + public showResizerInCardView():boolean { return false; } From d0f389e40809b2c9bfe1042d144eb0e272b17e80 Mon Sep 17 00:00:00 2001 From: Aleix Suau Date: Mon, 13 Jul 2020 19:16:11 +0200 Subject: [PATCH 09/11] Added english translations --- .../openproject-icon-font.woff2 | Bin 0 -> 22136 bytes .../ifc_models/pages/viewer/bim-view.service.ts | 2 +- modules/bim/config/locales/js-en.yml | 2 +- 3 files changed, 2 insertions(+), 2 deletions(-) create mode 100644 app/assets/fonts/openproject_icon/openproject-icon-font.woff2 diff --git a/app/assets/fonts/openproject_icon/openproject-icon-font.woff2 b/app/assets/fonts/openproject_icon/openproject-icon-font.woff2 new file mode 100644 index 0000000000000000000000000000000000000000..8f1317164e63ce5a5c61cbf4aa1df38f8c0b2963 GIT binary patch literal 22136 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 literal 0 HcmV?d00001 diff --git a/frontend/src/app/modules/bim/ifc_models/pages/viewer/bim-view.service.ts b/frontend/src/app/modules/bim/ifc_models/pages/viewer/bim-view.service.ts index 28e391e521..7389322529 100644 --- a/frontend/src/app/modules/bim/ifc_models/pages/viewer/bim-view.service.ts +++ b/frontend/src/app/modules/bim/ifc_models/pages/viewer/bim-view.service.ts @@ -50,7 +50,7 @@ export class BimViewService implements OnDestroy { list: this.I18n.t('js.views.card'), viewer: this.I18n.t('js.ifc_models.views.viewer'), splitList: this.I18n.t('js.ifc_models.views.split'), - splitCards: this.I18n.t('js.ifc_models.views.split-cards'), + splitCards: this.I18n.t('js.ifc_models.views.split_cards'), table: this.I18n.t('js.views.list'), }; diff --git a/modules/bim/config/locales/js-en.yml b/modules/bim/config/locales/js-en.yml index fc3e7a1bfa..f456511886 100644 --- a/modules/bim/config/locales/js-en.yml +++ b/modules/bim/config/locales/js-en.yml @@ -19,4 +19,4 @@ en: views: viewer: 'Viewer' split: 'Viewer and table' - split-cards: 'Viewer and cards' + split_cards: 'Viewer and cards' \ No newline at end of file From c453ecab093daae4878ecac9d1014115b0fa919d Mon Sep 17 00:00:00 2001 From: Aleix Suau Date: Tue, 14 Jul 2020 17:53:38 +0200 Subject: [PATCH 10/11] 'shows Cards view by default' fixed + Removed deprecated test files --- config/middleware.rb | 5 ----- .../ifc_models/openproject-ifc-models.routes.ts | 6 ++++++ spec/support/capybara_headers.rb | 17 ----------------- 3 files changed, 6 insertions(+), 22 deletions(-) delete mode 100644 config/middleware.rb delete mode 100644 spec/support/capybara_headers.rb diff --git a/config/middleware.rb b/config/middleware.rb deleted file mode 100644 index e96062df33..0000000000 --- a/config/middleware.rb +++ /dev/null @@ -1,5 +0,0 @@ -require 'request_headers' - -if %w(test).include?(Rails.env) - Rails.application.config.middleware.insert_before Rack::Lock, "RequestHeaders", CustomHeadersHelper -end diff --git a/frontend/src/app/modules/bim/ifc_models/openproject-ifc-models.routes.ts b/frontend/src/app/modules/bim/ifc_models/openproject-ifc-models.routes.ts index c89998c304..7441ab608a 100644 --- a/frontend/src/app/modules/bim/ifc_models/openproject-ifc-models.routes.ts +++ b/frontend/src/app/modules/bim/ifc_models/openproject-ifc-models.routes.ts @@ -65,6 +65,9 @@ export const IFC_ROUTES:Ng2StateDeclaration[] = [ { name: 'bim.partitioned.list', url: '/list?{cards:bool}', + params: { + cards: true + }, data: { baseRoute: 'bim.partitioned.list', newRoute: 'bim.partitioned.list.new', @@ -78,6 +81,9 @@ export const IFC_ROUTES:Ng2StateDeclaration[] = [ { name: 'bim.partitioned.split', url: '/split?{cards:bool}', + params: { + cards: true + }, data: { baseRoute: 'bim.partitioned.split', partition: '-split', diff --git a/spec/support/capybara_headers.rb b/spec/support/capybara_headers.rb deleted file mode 100644 index 64d5918957..0000000000 --- a/spec/support/capybara_headers.rb +++ /dev/null @@ -1,17 +0,0 @@ -require 'request_headers' - -module CapybaraHeaderHelpers - shared_context 'in Revit' do - before(:each) { add_headers('User-Agent' => 'foo bar Revit') } - end - - def add_headers(custom_headers) - if Capybara.current_driver == :rack_test - custom_headers.each do |name, value| - page.driver.browser.header(name, value) - end - else - CustomHeadersHelper.headers = custom_headers - end - end -end \ No newline at end of file From fa3bc2962cfca8119d903431df7361ef65359101 Mon Sep 17 00:00:00 2001 From: Aleix Suau Date: Tue, 14 Jul 2020 17:55:45 +0200 Subject: [PATCH 11/11] Align viewer and table on split view mode --- .../modules/bim/ifc_models/ifc-viewer/ifc-viewer.component.sass | 1 + 1 file changed, 1 insertion(+) diff --git a/frontend/src/app/modules/bim/ifc_models/ifc-viewer/ifc-viewer.component.sass b/frontend/src/app/modules/bim/ifc_models/ifc-viewer/ifc-viewer.component.sass index 690ff0fd56..fb0ab50f4a 100644 --- a/frontend/src/app/modules/bim/ifc_models/ifc-viewer/ifc-viewer.component.sass +++ b/frontend/src/app/modules/bim/ifc_models/ifc-viewer/ifc-viewer.component.sass @@ -27,6 +27,7 @@ position: relative width: 100% height: 100% + padding-top: 10px padding-bottom: 10px overflow: hidden min-width: 420px