Merge pull request #8063 from opf/bim/fix/ifc_full_page_angular

render ifc default models within angular page

[ci skip]
pull/8067/head
Oliver Günther 5 years ago committed by GitHub
commit 316856820f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 1
      config/routes.rb
  2. 2
      frontend/src/app/components/modals/wp-destroy-modal/wp-destroy.modal.ts
  3. 4
      frontend/src/app/modules/common/path-helper/path-helper.service.ts
  4. 12
      frontend/src/app/modules/ifc_models/ifc-base-view/ifc-base-view.component.html
  5. 12
      frontend/src/app/modules/ifc_models/ifc-base-view/ifc-base-view.component.sass
  6. 71
      frontend/src/app/modules/ifc_models/ifc-base-view/ifc-base-view.component.ts
  7. 3
      frontend/src/app/modules/ifc_models/ifc-viewer/ifc-viewer.component.ts
  8. 52
      frontend/src/app/modules/ifc_models/openproject-ifc-models.module.ts
  9. 34
      frontend/src/app/modules/ifc_models/pages/index/ifc-index-page.component.html
  10. 19
      frontend/src/app/modules/ifc_models/pages/index/ifc-index-page.component.sass
  11. 83
      frontend/src/app/modules/ifc_models/pages/index/ifc-index-page.component.ts
  12. 3
      frontend/src/app/modules/work_packages/openproject-work-packages.module.ts
  13. 48
      modules/ifc_models/app/assets/stylesheets/ifc_viewer/generic.sass
  14. 6
      modules/ifc_models/app/controllers/ifc_models/ifc_models_controller.rb
  15. 5
      modules/ifc_models/app/helpers/ifc_models_helper.rb
  16. 14
      modules/ifc_models/app/views/ifc_models/ifc_models/defaults.html.erb
  17. 2
      modules/ifc_models/app/views/ifc_models/ifc_models/index.html.erb
  18. 27
      modules/ifc_models/app/views/ifc_models/ifc_models/show.html.erb
  19. 1
      modules/ifc_models/config/locales/en.yml
  20. 6
      modules/ifc_models/config/locales/js-en.yml
  21. 26
      modules/ifc_models/config/routes.rb
  22. 6
      modules/ifc_models/lib/open_project/ifc_models/engine.rb
  23. 6
      modules/ifc_models/spec/support/pages/ifc_models/index.rb
  24. 4
      modules/ifc_models/spec/support/pages/ifc_models/show.rb
  25. 2
      modules/ifc_models/spec/support/pages/ifc_models/show_default.rb

@ -1,4 +1,5 @@
#-- encoding: UTF-8
#-- copyright
# OpenProject is an open source project management software.
# Copyright (C) 2012-2020 the OpenProject GmbH

@ -98,7 +98,7 @@ export class WpDestroyModal extends OpModalComponent implements OnInit {
this.text.text = this.I18n.t('js.modals.destroy_work_package.text', {
label: this.workPackageLabel,
count: this.workPackages.length
}),
});
this.text.childCount = (wp:WorkPackageResource) => {
const count = this.children(wp).length;

@ -54,6 +54,10 @@ export class PathHelperService {
}
}
public ifcModelsPath(projectIdentifier:string) {
return this.staticBase + `/projects/${projectIdentifier}/ifc_models`;
}
public highlightingCssPath() {
return this.staticBase + '/highlighting/styles';
}

@ -1,12 +0,0 @@
<div class="ifc-base-view--container">
<div class="ifc-view--viewer-container">
<ifc-viewer></ifc-viewer>
</div>
<div class="ifc-view--table-container" wp-isolated-query-space>
<wp-embedded-table [queryProps]="queryProps"
[configuration]="configuration"
[externalHeight]="true">
</wp-embedded-table>
</div>
</div>

@ -1,12 +0,0 @@
*:host
height: calc(100% - 60px)
.ifc-base-view--container
display: flex
height: 100%
.ifc-view--table-container
height: 100%
margin-left: 15px
// Cancel out space for scroll bar and align with toolbar and header
margin-right: -15px

@ -1,71 +0,0 @@
// -- copyright
// OpenProject is an open source project management software.
// Copyright (C) 2012-2020 the OpenProject GmbH
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License version 3.
//
// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
// Copyright (C) 2006-2013 Jean-Philippe Lang
// Copyright (C) 2010-2013 the ChiliProject Team
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//
// See docs/COPYRIGHT.rdoc for more details.
// ++
import {ChangeDetectionStrategy, Component} from "@angular/core";
import {DynamicBootstrapper} from "core-app/globals/dynamic-bootstrapper";
import {WorkPackageTableConfigurationObject} from "core-components/wp-table/wp-table-configuration";
@Component({
templateUrl: './ifc-base-view.component.html',
changeDetection: ChangeDetectionStrategy.OnPush,
selector: 'ifc-base-view',
styleUrls: ['./ifc-base-view.component.sass']
})
export class IfcBaseViewComponent {
public queryProps:{ [key:string]:any };
public configuration:WorkPackageTableConfigurationObject;
private filters:any[] = [];
constructor() {
this.configuration = {
actionsColumnEnabled: false,
columnMenuEnabled: false,
contextMenuEnabled: false,
inlineCreateEnabled: false,
withFilters: true,
showFilterButton: false,
isCardView: true
};
this.filters.push({ status: {
operator: 'o',
values: [] }});
this.queryProps = {
'columns[]': ['id', 'subject'],
filters: JSON.stringify(this.filters),
sortBy: JSON.stringify([['updatedAt', 'desc']]),
showHierarchies: false
};
}
}
DynamicBootstrapper.register({
selector: 'ifc-base-view', cls: IfcBaseViewComponent
});

@ -73,6 +73,3 @@ export class IFCViewerComponent implements OnInit {
});
}
}
DynamicBootstrapper.register({
selector: 'ifc-viewer', cls: IFCViewerComponent
});

@ -25,29 +25,63 @@
//
// See doc/COPYRIGHT.rdoc for more details.
// ++
import {NgModule} from "@angular/core";
import {IFCViewerComponent} from "core-app/modules/ifc_models/ifc-viewer/ifc-viewer.component";
import {IfcBaseViewComponent} from "core-app/modules/ifc_models/ifc-base-view/ifc-base-view.component";
import {OpenprojectWorkPackagesModule} from "core-app/modules/work_packages/openproject-work-packages.module";
import { Ng2StateDeclaration, UIRouterModule, UIRouter } from '@uirouter/angular';
import {IFCIndexPageComponent} from "core-app/modules/ifc_models/pages/index/ifc-index-page.component";
import {OpenprojectCommonModule} from "core-app/modules/common/openproject-common.module";
import { IFCViewerComponent } from './ifc-viewer/ifc-viewer.component';
export const IFC_ROUTES:Ng2StateDeclaration[] = [
// TODO: properly namespace the routes e.g. bim.something
{
name: 'bim_defaults',
parent: 'root',
url: '/ifc_models/defaults/',
component: IFCIndexPageComponent
},
{
name: 'bim_show',
parent: 'root',
url: '/ifc_models/{model_id:[0-9]+}/',
component: IFCIndexPageComponent,
}
];
export function uiRouterIFCConfiguration(uiRouter:UIRouter) {
uiRouter.urlService.rules
.when(
new RegExp("^/projects/(.*)/ifc_models/defaults$"),
match => `/projects/${match[1]}/ifc_models/defaults/`
);
uiRouter.urlService.rules
.when(
new RegExp("^/projects/(.*)/ifc_models/([0-9]+)$"),
match => `/projects/${match[1]}/ifc_models/${match[2]}/`
);
}
@NgModule({
imports: [
OpenprojectWorkPackagesModule
OpenprojectCommonModule,
OpenprojectWorkPackagesModule,
UIRouterModule.forChild({
states: IFC_ROUTES,
config: uiRouterIFCConfiguration
})
],
providers: [
],
declarations: [
IfcBaseViewComponent,
// Pages
IFCIndexPageComponent,
IFCViewerComponent
],
exports: [
IfcBaseViewComponent,
IFCViewerComponent
],
entryComponents: [
IfcBaseViewComponent,
IFCViewerComponent
]
})
export class OpenprojectIFCModelsModule {

@ -0,0 +1,34 @@
<div class="toolbar-container">
<div class="toolbar">
<div class="title-container">
<h2 [textContent]="title">
</h2>
</div>
<ul class="toolbar-items">
<li class="toolbar-item"
*ngIf="manageAllowed">
<a class="button"
[href]="manageIFCPath">
<op-icon icon-classes="button--icon icon-settings2"></op-icon>
<span class="button--text"
[textContent]="text.manage"
aria-hidden="true"></span>
</a>
</li>
<li class="toolbar-item hidden-for-mobile">
<zen-mode-toggle-button></zen-mode-toggle-button>
</li>
</ul>
</div>
</div>
<div class="ifc-view--viewer-container">
<ifc-viewer></ifc-viewer>
</div>
<div class="ifc-view--table-container" wp-isolated-query-space>
<wp-embedded-table [queryProps]="queryProps"
[configuration]="configuration"
[externalHeight]="true">
</wp-embedded-table>
</div>

@ -0,0 +1,19 @@
*:host
height: 100%
overflow: hidden
display: grid
grid-template-columns: 1fr 500px
grid-template-rows: 60px calc(100% - 60px)
grid-template-areas: "header header" "ifc-model wp-list"
grid-column-gap: 10px
.toolbar-container
grid-area: header
.ifc-view--view-table-container
grid-area: wp-list
.ifc-view--viewer-container
grid-area: ifc-model
position: relative
overflow: hidden

@ -0,0 +1,83 @@
import {Component} from "@angular/core";
import {I18nService} from "core-app/modules/common/i18n/i18n.service";
import {PathHelperService} from "core-app/modules/common/path-helper/path-helper.service";
import {CurrentProjectService} from "core-components/projects/current-project.service";
import {WorkPackageTableConfigurationObject} from "core-components/wp-table/wp-table-configuration";
import { StateService } from '@uirouter/core';
import {GonService} from "core-app/modules/common/gon/gon.service";
@Component({
templateUrl: './ifc-index-page.component.html',
styleUrls: ['./ifc-index-page.component.sass']
})
export class IFCIndexPageComponent {
public text = {
title: this.i18n.t('js.ifc_models.models.default'),
manage: this.i18n.t('js.ifc_models.models.manage'),
delete: this.i18n.t('js.button_delete'),
edit: this.i18n.t('js.button_edit'),
areYouSure: this.i18n.t('js.text_are_you_sure')
};
public queryProps:{ [key:string]:any };
public configuration:WorkPackageTableConfigurationObject = {
actionsColumnEnabled: false,
columnMenuEnabled: false,
contextMenuEnabled: false,
inlineCreateEnabled: false,
withFilters: true,
showFilterButton: false,
isCardView: true
};
private filters:any[] = [];
constructor(readonly state:StateService,
readonly i18n:I18nService,
readonly paths:PathHelperService,
readonly currentProject:CurrentProjectService,
readonly gon:GonService) {
this.applyFilters();
}
public get title() {
if (this.state.current.name === 'bim_defaults') {
return this.i18n.t('js.ifc_models.models.default');
} else {
return this.gonIFC['models'][0]['name'];
}
}
public get projectIdentifier() {
return this.currentProject.identifier!;
}
public get manageIFCPath() {
return this.paths.ifcModelsPath(this.projectIdentifier);
}
public get manageAllowed() {
return this.gonIFC.permissions.manage;
}
private applyFilters() {
// TODO: Limit to project
this.filters.push({
status: {
operator: 'o',
values: []
}
});
this.queryProps = {
'columns[]': ['id', 'subject'],
filters: JSON.stringify(this.filters),
sortBy: JSON.stringify([['updatedAt', 'desc']]),
showHierarchies: false
};
}
private get gonIFC() {
return (this.gon.get('ifc_models') as any)
}
}

@ -180,9 +180,6 @@ import { TimeEntryChangeset } from 'core-app/components/time-entries/time-entry-
OpenprojectBcfModule,
OpenprojectProjectsModule,
// Work package custom actions
//WpCustomActionsModule,
],
providers: [
{

@ -16,12 +16,11 @@
overflow: hidden
&.action-show,
&.action-show_defaults
&.action-defaults
#content-wrapper
padding: 10px 20px 20px 20px
#content
display: flex
flex-direction: column
height: 100%
// Override default behavior to let the viewer span the whole height
@ -32,38 +31,31 @@
[data-name="ifc_models"] .main-menu--children
overflow-x: hidden !important
.ifc-view--viewer-container
flex-grow: 1
position: relative
width: 100%
height: 100%
overflow: hidden
.ifc-model-viewer--nav-cube-canvas
position: absolute
width: 200px
height: 200px
bottom: 0
right: 0
z-index: 10
.ifc-model-viewer--nav-cube-canvas
position: absolute
width: 200px
height: 200px
bottom: 0
right: 0
z-index: 10
.ifc-model-viewer--section-planes-overview-canvas
position: absolute
width: 250px
height: 250px
top: 50px
right: 50px
z-index: 2000
.ifc-model-viewer--section-planes-overview-canvas
position: absolute
width: 250px
height: 250px
top: 50px
right: 50px
z-index: 2000
.ifc-model-viewer--container
position: relative
width: 100%
height: 100%
.ifc-model-viewer--model-canvas
width: 100%
height: 100%
background: $gray-lighter
.ifc-model-viewer--model-canvas
width: 100%
height: 100%
background: $gray-lighter
// -------------------------- XEOKIT specific rules for BUTTONS --------------------------

@ -32,9 +32,9 @@ module ::IFCModels
class IFCModelsController < BaseController
helper_method :gon
before_action :find_project_by_project_id, only: %i[index new create show show_defaults edit update destroy]
before_action :find_project_by_project_id, only: %i[index new create show defaults edit update destroy]
before_action :find_ifc_model_object, except: %i[index new create]
before_action :find_all_ifc_models, only: %i[show show_defaults index]
before_action :find_all_ifc_models, only: %i[show defaults index]
before_action :authorize
@ -53,7 +53,7 @@ module ::IFCModels
def show; end
def show_defaults
def defaults
@default_ifc_models = @ifc_models.defaults
if @default_ifc_models.empty?

@ -7,7 +7,10 @@ module IFCModelsHelper
default_models: gon_ifc_default_models(all_converted_models, models_to_load),
projects: [{ id: @project.identifier, name: @project.name }],
xkt_attachment_ids: gon_ifc_model_xkt_attachment_ids(all_converted_models),
metadata_attachment_ids: gon_ifc_model_metadata_attachment_ids(all_converted_models)
metadata_attachment_ids: gon_ifc_model_metadata_attachment_ids(all_converted_models),
permissions: {
manage: User.current.allowed_to?(:manage_ifc_models, @project)
}
}
end

@ -34,17 +34,6 @@ See doc/COPYRIGHT.rdoc for more details.
<%= render partial: 'show_headers', locals: { all_models: @ifc_models, selected_models: @default_ifc_models } %>
<%= toolbar title: t('ifc_models.label_default_ifc_models') do %>
<li class="toolbar-item">
<%= link_to(ifc_models_project_ifc_models_path(@project), class: 'button', accesskey: accesskey(:edit)) do %>
<%= op_icon('button--icon icon-settings2') %> <%= t('ifc_models.label_manage_models') %>
<% end %>
</li>
<li class="toolbar-item">
<zen-mode-toggle-button></zen-mode-toggle-button>
</li>
<% end %>
<% if @default_ifc_models.empty? %>
<%= render partial: 'no_default_notice', locals: { project: @project } %>
<% else %>
@ -54,5 +43,6 @@ See doc/COPYRIGHT.rdoc for more details.
<%= render partial: 'unconverted_notice', locals: { unconverted: unconverted } %>
<% end %>
<ifc-base-view></ifc-base-view>
<openproject-base></openproject-base>
<% end %>

@ -42,7 +42,7 @@ See docs/COPYRIGHT.rdoc for more details.
<% end %>
<% if @ifc_models.defaults.any? %>
<li class="toolbar-item">
<%= link_to show_defaults_ifc_models_project_ifc_models_path,
<%= link_to defaults_ifc_models_project_ifc_models_path,
{ class: 'button',
aria: { label: t('ifc_models.label_show_defaults') },
title: t('ifc_models.label_show_defaults') } do %>

@ -34,31 +34,6 @@ See doc/COPYRIGHT.rdoc for more details.
<%= render partial: 'show_headers', locals: { all_models: @ifc_models, selected_models: [@ifc_model] } %>
<%= toolbar title: @ifc_model.title do %>
<% if authorize_for('ifc_models/ifc_models', :edit) %>
<li class="toolbar-item">
<%= link_to(edit_ifc_models_project_ifc_model_path(@project, @ifc_model), class: 'button', accesskey: accesskey(:edit)) do %>
<%= op_icon('button--icon icon-edit') %> <%= t(:button_edit) %>
<% end %>
</li>
<% end %>
<% if authorize_for('ifc_models/ifc_models', :destroy) %>
<li class="toolbar-item">
<%= link_to(ifc_models_project_ifc_model_path(@project, @ifc_model), class: 'button', data: { confirm: t(:text_are_you_sure) }, method: :delete) do %>
<%= op_icon('button--icon icon-delete') %> <%= t(:button_delete) %>
<% end %>
</li>
<% end %>
<li class="toolbar-item">
<%= link_to(ifc_models_project_ifc_models_path(@project), class: 'button', accesskey: accesskey(:edit)) do %>
<%= op_icon('button--icon icon-settings2') %> <%= t('ifc_models.label_manage_models') %>
<% end %>
</li>
<li class="toolbar-item">
<zen-mode-toggle-button></zen-mode-toggle-button>
</li>
<% end %>
<% if @ifc_model.converted? %>
<ifc-base-view></ifc-base-view>
<openproject-base></openproject-base>
<% end %>

@ -6,7 +6,6 @@ en:
label_show_defaults: 'Show defaults'
label_default_ifc_models: 'Default IFC models'
label_edit_defaults: 'Edit defaults'
label_manage_models: 'Manage models'
no_defaults_warning:
title: 'No IFC model was set as default for this project.'
check_1: 'Check that you have uploaded at least one IFC model.'

@ -0,0 +1,6 @@
en:
js:
ifc_models:
models:
default: 'Default IFC models'
manage: 'Manage models'

@ -1,20 +1,15 @@
#-- encoding: UTF-8
#-- copyright
# OpenProject Backlogs Plugin
#
# Copyright (C)2013-2014 the OpenProject Foundation (OPF)
# Copyright (C)2011 Stephan Eckardt, Tim Felgentreff, Marnen Laibow-Koser, Sandro Munda
# Copyright (C)2010-2011 friflaj
# Copyright (C)2010 Maxime Guilbot, Andrew Vit, Joakim Kolsjö, ibussieres, Daniel Passos, Jason Vasquez, jpic, Emiliano Heyns
# Copyright (C)2009-2010 Mark Maglana
# Copyright (C)2009 Joe Heck, Nate Lowrie
# OpenProject is a project management system.
# Copyright (C) 2012-2020 the OpenProject Foundation (OPF)
#
# This program is free software; you can redistribute it and/or modify it under
# the terms of the GNU General Public License version 3.
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License version 3.
#
# OpenProject Backlogs is a derivative work based on ChiliProject Backlogs.
# The copyright follows:
# Copyright (C) 2010-2011 - Emiliano Heyns, Mark Maglana, friflaj
# Copyright (C) 2011 - Jens Ulferts, Gregor Schmidt - Finn GmbH - Berlin, Germany
# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
# Copyright (C) 2006-2017 Jean-Philippe Lang
# Copyright (C) 2010-2013 the ChiliProject Team
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
@ -34,12 +29,11 @@
#++
OpenProject::Application.routes.draw do
# get '/projects/:project_id/ifc_models', to: 'ifc_models/ifc_models#index'
scope '', as: 'ifc_models' do
scope 'projects/:project_id', as: 'project' do
resources :ifc_models, controller: 'ifc_models/ifc_models' do
collection do
get 'show_defaults'
get 'defaults'
end
end
end

@ -45,7 +45,7 @@ module OpenProject::IFCModels
project_module :ifc_models do
permission :view_ifc_models,
{ 'ifc_models/ifc_models': %i[index show show_defaults] }
{ 'ifc_models/ifc_models': %i[index show defaults] }
permission :manage_ifc_models,
{ 'ifc_models/ifc_models': %i[index show destroy edit update create new] },
dependencies: %i[view_ifc_models]
@ -59,7 +59,7 @@ module OpenProject::IFCModels
initializer 'ifc_models.menu' do
::Redmine::MenuManager.map(:project_menu) do |menu|
menu.push(:ifc_models,
{ controller: '/ifc_models/ifc_models', action: 'show_defaults' },
{ controller: '/ifc_models/ifc_models', action: 'defaults' },
caption: :'ifc_models.label_ifc_models',
param: :project_id,
after: :work_packages,
@ -67,7 +67,7 @@ module OpenProject::IFCModels
badge: :label_new)
menu.push :ifc_viewer_panels,
{ controller: '/ifc_models/ifc_models', action: 'show_defaults' },
{ controller: '/ifc_models/ifc_models', action: 'defaults' },
param: :project_id,
parent: :ifc_models,
partial: '/ifc_models/ifc_models/panels'

@ -96,8 +96,9 @@ module Pages
def show_model(model)
click_model_link model.title
# The extra slash is required for angular
expect_correct_page_loaded '.ifc-model-viewer--container',
ifc_models_project_ifc_model_path(project, model)
ifc_models_project_ifc_model_path(project, model) + '/'
visit!
end
@ -105,8 +106,9 @@ module Pages
def show_defaults
click_toolbar_button 'Show defaults'
# The extra slash is required for angular
expect_correct_page_loaded '.ifc-model-viewer--container',
show_defaults_ifc_models_project_ifc_models_path(project)
defaults_ifc_models_project_ifc_models_path(project) + '/'
visit!
end

@ -43,10 +43,6 @@ module Pages
def path
ifc_models_project_ifc_model_path(project, id)
end
def toolbar_items
%w(Edit Delete)
end
end
end
end

@ -38,7 +38,7 @@ module Pages
end
def path
show_defaults_ifc_models_project_ifc_models_path(project)
defaults_ifc_models_project_ifc_models_path(project)
end
def finished_loading

Loading…
Cancel
Save