From 4b720c0abb66403933bdaf8463b146a263f03b00 Mon Sep 17 00:00:00 2001 From: Markus Kahl Date: Mon, 16 Nov 2020 08:21:21 +0000 Subject: [PATCH] fixed URL xeokit tries to download attachments from with subdirectory (#8837) * fixed URL xeokit tries to download attachments from with subdirectory * DRYing up path to IFC model attachment files in XeokitServer Also finally typing XeokitServer in TypeScript. * Cleanup after review: - Remove unnecessary imports - Use string interpolation in PathHelper Co-authored-by: Wieland Lindenthal --- .../ifc-viewer/ifc-viewer.service.ts | 2 +- .../bim/ifc_models/xeokit/xeokit-server.d.ts | 1 - .../bim/ifc_models/xeokit/xeokit-server.js | 78 ---------------- .../bim/ifc_models/xeokit/xeokit-server.ts | 76 ++++++++++++++++ .../src/app/modules/common/gon/gon.service.ts | 2 + .../common/path-helper/path-helper.service.ts | 89 ++++++++++--------- 6 files changed, 125 insertions(+), 123 deletions(-) delete mode 100644 frontend/src/app/modules/bim/ifc_models/xeokit/xeokit-server.d.ts delete mode 100644 frontend/src/app/modules/bim/ifc_models/xeokit/xeokit-server.js create mode 100644 frontend/src/app/modules/bim/ifc_models/xeokit/xeokit-server.ts 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 20d0668943..0241a21fba 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 @@ -47,7 +47,7 @@ export class IFCViewerService extends ViewerBridgeService { public newViewer(elements:XeokitElements, projects:any[]) { import('@xeokit/xeokit-bim-viewer/dist/main').then((XeokitViewerModule:any) => { - let server = new XeokitServer(); + let server = new XeokitServer(this.pathHelper); let viewerUI = new XeokitViewerModule.BIMViewer(server, elements); viewerUI.on("queryPicked", (event:any) => { diff --git a/frontend/src/app/modules/bim/ifc_models/xeokit/xeokit-server.d.ts b/frontend/src/app/modules/bim/ifc_models/xeokit/xeokit-server.d.ts deleted file mode 100644 index b2fc7ba970..0000000000 --- a/frontend/src/app/modules/bim/ifc_models/xeokit/xeokit-server.d.ts +++ /dev/null @@ -1 +0,0 @@ -export class XeokitServer {} \ No newline at end of file diff --git a/frontend/src/app/modules/bim/ifc_models/xeokit/xeokit-server.js b/frontend/src/app/modules/bim/ifc_models/xeokit/xeokit-server.js deleted file mode 100644 index 8bcc63f012..0000000000 --- a/frontend/src/app/modules/bim/ifc_models/xeokit/xeokit-server.js +++ /dev/null @@ -1,78 +0,0 @@ -import {utils} from "@xeokit/xeokit-sdk/src/viewer/scene/utils"; -/** - * Default server client which loads content via HTTP from the file system. - */ -class XeokitServer { - - /** - * - * @param cfg - * @param.cfg.dataDir Base directory for content. - */ - constructor(cfg = {}) { - this._dataDir = cfg.dataDir || ""; - } - - /** - * Gets the manifest of all projects. - * @param done - * @param error - */ - getProjects(done, _error) { - done({ projects: window.gon.ifc_models.projects }); - } - - /** - * Gets a manifest for a project. - * @param projectId - * @param done - * @param error - */ - getProject(projectData, done, _error) { - var manifestData = { - id: projectData[0].id, - name: projectData[0].name, - models: window.gon.ifc_models.models, - viewerContent: { - modelsLoaded: window.gon.ifc_models.shown_models - }, - viewerConfigs: { - saoEnabled: true // Needs to be enabled by default if we want to use it selectively on the available models. - } - }; - - done(manifestData); - } - - /** - * Gets metadata for a model within a project. - * @param projectId - * @param modelId - * @param done - * @param error - */ - getMetadata(_projectId, modelId, done, error) { - const attachmentId = window.gon.ifc_models.metadata_attachment_ids[modelId]; - console.log(`Loading model metadata for: ${attachmentId}`); - utils.loadJSON(this.attachmentUrl(attachmentId), done, error); - } - - /** - * Gets geometry for a model within a project. - * @param projectId - * @param modelId - * @param done - * @param error - */ - getGeometry(projectId, modelId, done, error) { - const attachmentId = window.gon.ifc_models.xkt_attachment_ids[modelId]; - console.log(`Loading model geometry for: ${attachmentId}`); - utils.loadArraybuffer(this.attachmentUrl(attachmentId), done, error); - } - - attachmentUrl(attachmentId) { - return "/api/v3/attachments/" + attachmentId + "/content"; - } -} - -export {XeokitServer}; \ No newline at end of file diff --git a/frontend/src/app/modules/bim/ifc_models/xeokit/xeokit-server.ts b/frontend/src/app/modules/bim/ifc_models/xeokit/xeokit-server.ts new file mode 100644 index 0000000000..77b5066e78 --- /dev/null +++ b/frontend/src/app/modules/bim/ifc_models/xeokit/xeokit-server.ts @@ -0,0 +1,76 @@ +// @ts-ignore +import {utils} from "@xeokit/xeokit-sdk/src/viewer/scene/utils"; +import {PathHelperService} from "../../../common/path-helper/path-helper.service"; +import {IFCGonDefinition} from "../pages/viewer/ifc-models-data.service"; + +/** + * Default server client which loads content via HTTP from the file system. + */ +export class XeokitServer { + private ifcModels:IFCGonDefinition; + /** + * + * @param config + * @param.config.pathHelper instance of PathHelperService. + */ + constructor(private pathHelper:PathHelperService) { + this.ifcModels = window.gon.ifc_models; + } + + /** + * Gets the manifest of all projects. + * @param done + * @param error + */ + getProjects(done:Function, _error:Function) { + done({ projects: this.ifcModels.projects }); + } + + /** + * Gets a manifest for a project. + * @param projectId + * @param done + * @param error + */ + getProject(projectData:any, done:Function, _error:Function) { + var manifestData = { + id: projectData[0].id, + name: projectData[0].name, + models: this.ifcModels.models, + viewerContent: { + modelsLoaded: this.ifcModels.shown_models + }, + viewerConfigs: { + saoEnabled: true // Needs to be enabled by default if we want to use it selectively on the available models. + } + }; + + done(manifestData); + } + + /** + * Gets metadata for a model within a project. + * @param projectId + * @param modelId + * @param done + * @param error + */ + getMetadata(_projectId:string, modelId:number, done:Function, error:Function) { + const attachmentId = this.ifcModels.metadata_attachment_ids[modelId]; + console.log(`Loading model metadata for: ${attachmentId}`); + utils.loadJSON(this.pathHelper.attachmentContentPath(attachmentId), done, error); + } + + /** + * Gets geometry for a model within a project. + * @param projectId + * @param modelId + * @param done + * @param error + */ + getGeometry(projectId:string, modelId:number, done:Function, error:Function) { + const attachmentId = this.ifcModels.xkt_attachment_ids[modelId]; + console.log(`Loading model geometry for: ${attachmentId}`); + utils.loadArraybuffer(this.pathHelper.attachmentContentPath(attachmentId), done, error); + } +} diff --git a/frontend/src/app/modules/common/gon/gon.service.ts b/frontend/src/app/modules/common/gon/gon.service.ts index c2d02661c4..2c046150e7 100644 --- a/frontend/src/app/modules/common/gon/gon.service.ts +++ b/frontend/src/app/modules/common/gon/gon.service.ts @@ -27,6 +27,7 @@ // ++ import {Injectable} from "@angular/core"; +import {IFCGonDefinition} from "../../bim/ifc_models/pages/viewer/ifc-models-data.service"; declare global { interface Window { @@ -36,6 +37,7 @@ declare global { export interface GonType { [key:string]:unknown; + ifc_models:IFCGonDefinition; } @Injectable({ providedIn: 'root' }) diff --git a/frontend/src/app/modules/common/path-helper/path-helper.service.ts b/frontend/src/app/modules/common/path-helper/path-helper.service.ts index 10e2e553cf..d999b8cb3d 100644 --- a/frontend/src/app/modules/common/path-helper/path-helper.service.ts +++ b/frontend/src/app/modules/common/path-helper/path-helper.service.ts @@ -45,10 +45,10 @@ class Apiv3Paths { * @param context */ public previewMarkup(context:string) { - let base = this.apiV3Base + '/render/markdown'; + let base = `${this.apiV3Base}/render/markdown`; if (context) { - return base + `?context=${context}`; + return `${base}?context=${context}`; } else { return base; } @@ -85,7 +85,7 @@ class Apiv3Paths { @Injectable({ providedIn: 'root' }) export class PathHelperService { - public readonly appBasePath = window.appBasePath ? window.appBasePath : ''; + public readonly appBasePath = window.appBasePath || ''; public readonly api = { v3: new Apiv3Paths(this.appBasePath) }; @@ -95,21 +95,25 @@ export class PathHelperService { } public attachmentDownloadPath(attachmentIdentifier:string, slug:string|undefined) { - let path = this.staticBase + '/attachments/' + attachmentIdentifier; + let path = `${this.staticBase}/attachments/${attachmentIdentifier}`; if (slug) { - return path + "/" + slug; + return `${path}/${slug}`; } else { return path; } } + public attachmentContentPath(attachmentIdentifier:number|string) { + return `${this.staticBase}/attachments/${attachmentIdentifier}/content`; + } + public ifcModelsPath(projectIdentifier:string) { - return this.staticBase + `/projects/${projectIdentifier}/ifc_models`; + return `${this.staticBase}/projects/${projectIdentifier}/ifc_models`; } public bimDetailsPath(projectIdentifier:string, workPackageId:string, viewpoint:number|string|null = null) { - let path = this.projectPath(projectIdentifier) + `/bcf/split/details/${workPackageId}`; + let path = `${this.projectPath(projectIdentifier)}/bcf/split/details/${workPackageId}`; if (viewpoint !== null) { path += `?viewpoint=${viewpoint}`; @@ -119,95 +123,95 @@ export class PathHelperService { } public highlightingCssPath() { - return this.staticBase + '/highlighting/styles'; + return `${this.staticBase}/highlighting/styles`; } public forumPath(projectIdentifier:string, forumIdentifier:string) { - return this.projectForumPath(projectIdentifier) + '/' + forumIdentifier; + return `${this.projectForumPath(projectIdentifier)}/${forumIdentifier}`; } public keyboardShortcutsHelpPath() { - return this.staticBase + '/help/keyboard_shortcuts'; + return `${this.staticBase}/help/keyboard_shortcuts`; } public messagePath(messageIdentifier:string) { - return this.staticBase + '/topics/' + messageIdentifier; + return `${this.staticBase}/topics/${messageIdentifier}`; } public myPagePath() { - return this.staticBase + '/my/page'; + return `${this.staticBase}/my/page`; } public newsPath(newsId:string) { - return this.staticBase + '/news/' + newsId; + return `${this.staticBase}/news/${newsId}`; } public loginPath() { - return this.staticBase + '/login'; + return `${this.staticBase}/login`; } public projectsPath() { - return this.staticBase + '/projects'; + return `${this.staticBase}/projects`; } public projectPath(projectIdentifier:string) { - return this.projectsPath() + '/' + projectIdentifier; + return `${this.projectsPath()}/${projectIdentifier}`; } public projectActivityPath(projectIdentifier:string) { - return this.projectPath(projectIdentifier) + '/activity'; + return `${this.projectPath(projectIdentifier)}/activity`; } public projectForumPath(projectIdentifier:string) { - return this.projectPath(projectIdentifier) + '/forums'; + return `${this.projectPath(projectIdentifier)}/forums`; } public projectCalendarPath(projectId:string) { - return this.projectPath(projectId) + '/work_packages/calendar'; + return `${this.projectPath(projectId)}/work_packages/calendar`; } public projectMembershipsPath(projectId:string) { - return this.projectPath(projectId) + '/members'; + return `${this.projectPath(projectId)}/members`; } public projectNewsPath(projectId:string) { - return this.projectPath(projectId) + '/news'; + return `${this.projectPath(projectId)}/news`; } public projectTimeEntriesPath(projectIdentifier:string) { - return this.projectPath(projectIdentifier) + '/cost_reports'; + return `${this.projectPath(projectIdentifier)}/cost_reports`; } public projectWikiPath(projectId:string) { - return this.projectPath(projectId) + '/wiki'; + return `${this.projectPath(projectId)}/wiki`; } public projectWorkPackagePath(projectId:string, wpId:string|number) { - return this.projectWorkPackagesPath(projectId) + '/' + wpId; + return `${this.projectWorkPackagesPath(projectId)}/${wpId}`; } public projectWorkPackagesPath(projectId:string) { - return this.projectPath(projectId) + '/work_packages'; + return `${this.projectPath(projectId)}/work_packages`; } public projectWorkPackageNewPath(projectId:string) { - return this.projectWorkPackagesPath(projectId) + '/new'; + return `${this.projectWorkPackagesPath(projectId)}/new`; } public projectBoardsPath(projectIdentifier:string|null) { if (projectIdentifier) { - return this.projectPath(projectIdentifier) + '/boards'; + return `${this.projectPath(projectIdentifier)}/boards`; } else { - return this.staticBase + '/boards'; + return `${this.staticBase}/boards`; } } public projectDashboardsPath(projectIdentifier:string) { - return this.projectPath(projectIdentifier) + '/dashboards'; + return `${this.projectPath(projectIdentifier)}/dashboards`; } public timeEntriesPath(workPackageId:string|number) { - var suffix = '/time_entries'; + let suffix = '/time_entries'; if (workPackageId) { return this.workPackagePath(workPackageId) + suffix; @@ -217,51 +221,50 @@ export class PathHelperService { } public usersPath() { - return this.staticBase + '/users'; + return `${this.staticBase}/users`; } public userPath(id:string|number) { - return this.usersPath() + '/' + id; + return `${this.usersPath()}/${id}`; } public versionsPath() { - return this.staticBase + '/versions'; + return `${this.staticBase}/versions`; } public versionEditPath(id:string|number) { - return this.staticBase + '/versions/' + id + '/edit'; + return `${this.staticBase}/versions/${id}/edit`; } public versionShowPath(id:string|number) { - return this.staticBase + '/versions/' + id; + return `${this.staticBase}/versions/${id}`; } public workPackagesPath() { - return this.staticBase + '/work_packages'; + return `${this.staticBase}/work_packages`; } public workPackagePath(id:string|number) { - return this.staticBase + '/work_packages/' + id; + return `${this.staticBase}/work_packages/${id}`; } public workPackageCopyPath(workPackageId:string|number) { - return this.workPackagePath(workPackageId) + '/copy'; + return `${this.workPackagePath(workPackageId)}/copy`; } public workPackageDetailsCopyPath(projectIdentifier:string, workPackageId:string|number) { - return this.projectWorkPackagesPath(projectIdentifier) + '/details/' + workPackageId + '/copy'; + return `${this.projectWorkPackagesPath(projectIdentifier)}/details/${workPackageId}/copy`; } public workPackagesBulkDeletePath() { - return this.workPackagesPath() + '/bulk'; + return `${this.workPackagesPath()}/bulk`; } public projectLevelListPath() { - return this.projectsPath() + '/level_list.json'; + return `${this.projectsPath()}/level_list.json`; } public textFormattingHelp() { - return this.staticBase + '/help/text_formatting'; + return `${this.staticBase}/help/text_formatting`; } - }