magicad/magicad.js
- import base64 from '../base64/base64';
- import {
- _addAuthToken,
- _extendQModelOptions,
- _setDiagramImages,
- _getResourceQueryUrl,
- _replaceOptionsFromBase64EncodedUrl
- } from './magicad-fn';
- import OidcAuthService from '../auth/oidcauth';
- import UserManagerSettingsFactory from '../auth/oidc-clientsettings-factory';
- import SigninService from '../auth/signin';
- import X3DViewService from '../x3dviewservice/X3DViewService.js';
- import axios from 'axios';
- import utils from '../utils';
-
- export default class MagiCAD {
- /**
- * @private
- * @param {*} fingerprintService
- * @param {*} diagramService
- * @param {*} ahuCalculationService
- * @param {*} signinService (optional) Could be created also with init() function
- * @param {*} x3dViewService (optional) Could be created also with init() function
- */
- constructor(fingerprintService, diagramService, ahuCalculationService, signinService, x3dViewService) {
- /**
- * @private
- */
- this.fingerprintService = fingerprintService;
- /**
- * @private
- */
- this.diagramService = diagramService;
- /**
- * @private
- */
- this.ahuCalculationService = ahuCalculationService;
- /**
- * @private
- */
- this.signinService = signinService;
- /**
- * @private
- */
- this.x3dViewService = x3dViewService;
- /**
- * @private
- */
- this.onFindOptimalSpeed = undefined;
- /**
- * @private
- */
- this.onGetDpTot = undefined;
- /**
- * @private
- */
- this.onLoad = undefined;
- /**
- * @private
- */
- this.onLoadError = undefined;
- /**
- * @private
- */
- this.onRenderX3D = undefined;
- }
-
- /**
- * Initialize MagiCAD Widget SDK
- *
- * @param {object} options <pre>Example object:
- * {
- * client_id: 'your_client_id',
- * popup_redirect_uri: 'callback file url when using popup signin method'
- * redirect_uri: 'callback file url when using redirect signin method' // if given, popup_redirect_uri will be ignored browser redirection is being used instead of popup
- * post_logout_redirect_uri: 'callback file url to direct the user to after successful sign-out'
- * enableX3D: true, // default value is true and x3dom library will be loaded
- * onLoadUser: function(user) { console.log(user.username); }, // Set event handler to get signed in user if any exists e.g. case when page refreshed
- * onSignin: function(user) { console.log(user.username); }, // Set event handler to perform some action on user signin
- * onSignout: function() { console.log('user signed out'); }, // Set event handler to perform some action on user signout
- * onRenderX3D: function() { console.log('x3d rendered'); }, // Set event handler to perform some action after rendering x3d image
- * onGetDpTot function(result) { console.log(result); }, // Set event handler to perform some action with calculation result
- * onFindOptimalSpeed: function(result) { console.log(result); } // Set event handler to perform some action with calculation result
- * }
- * </pre>
- * @param {object} context (optional)
- */
- init(options, context) {
- // If not given already in constructor
- if (!this.signinService) {
- let factory = new UserManagerSettingsFactory(options);
- let oidcAuthService = new OidcAuthService(factory);
- this.signinService = new SigninService(oidcAuthService);
- }
- if (!this.signinService)
- throw "MagiCAD Widget SDK initialization failed!";
-
- // Set X3DViewService
- if (options.enableX3D === undefined || options.enableX3D === null) {
- options.enableX3D = true; // default value if not given
- }
- // If not given already in contructor
- if (!this.x3dViewService)
- this.x3dViewService = options.enableX3D ? new X3DViewService() : undefined;
-
- if (this.signinService) {
- if (typeof options.onLoadUser === 'function') {
- this.signinService && this.signinService.getUser()
- .then(user => {
- options.onLoadUser(user.profile);
- })
- .catch(err => {
- options.onLoadUser(null);
- });
- }
- if (typeof options.onSignin === 'function') {
- this.signinService.onSignin(options.onSignin);
- }
- if (typeof options.onSignout === 'function') {
- this.signinService.onSignout(options.onSignout);
- }
- }
-
- if (typeof options.onLoad === 'function') {
- this.onLoad = options.onLoad;
- }
-
- if (typeof options.onLoadError === 'function') {
- this.onLoadError = options.onLoadError;
- }
- if (typeof options.onRenderX3D === 'function') {
- this.onRenderX3D = options.onRenderX3D;
- }
- if (typeof options.onGetDpTot === 'function') {
- this.onGetDpTot = options.onGetDpTot;
- }
- if (typeof options.onFindOptimalSpeed === 'function') {
- this.onFindOptimalSpeed = options.onFindOptimalSpeed;
- }
-
- if (typeof context === 'object') {
- context.MagiCAD = Object.assign(context.MagiCAD, this);
- context.MagiCAD.__proto__ = this.__proto__;
- }
- }
-
- /**
- * Return information is user logged in.
- *
- * @return boolean value is used logged in
- */
- isLoggedIn() {
- return this.signinService && this.signinService.isLoggedIn();
- }
-
- /**
- * Signin. Will open MagiCAD login popup.
- *
- * @return {Promise<void>}
- */
- signin() {
- return this.signinService && this.signinService.signin();
- }
-
- /**
- * Signout current logged in user
- *
- * @return {Promise<void>}
- */
- signout() {
- return this.signinService && this.signinService.signout();
- }
-
- /**
- * Return release info of MagiCAD Widget SDK in example Production 2.35.0
- */
- getReleaseInfo() {
- return `${systemconfig.ENVIRONMENT} ${systemconfig.RELEASENUMBER}`;
- }
-
- /**
- * Load and initialize MagiCAD Cloud Javascript Library
- *
- * @param {object} options <pre>
- * {
- * productId: string,
- * variantQpdId: string,
- * articleNumber: string,
- * manufacturerId: string
- * }
- *
- * where manufacturerId and either:
- *
- * productId and variantQpdId, or
- * articleNumber
- *
- * is defined.
- * </pre>
- * @return {Promise<ProductData>} Successful response will contain product/variant data
- */
- load(options) {
- let userRequest = this.signinService && this.signinService.getUser(),
- fingerprintRequest = this.fingerprintService.getFingerprint();
- let promise = Promise.all([userRequest, fingerprintRequest]).then(([user, sessionId]) => {
- let baseProductUrl = systemconfig.APIURL + systemconfig.PRODUCTPATH;
- let productUrl;
- if (options.productId)
- productUrl = baseProductUrl + options.productId;
- else if (options.articleNumber && options.manufacturerId)
- productUrl = baseProductUrl + options.manufacturerId + '/' + encodeURI(options.articleNumber);
- if (options.logoContainerId)
- this.renderMagiCADLogo(options.logoContainerId);
-
- return axios.get(productUrl).then((response) => {
- if (!response || response.status !== 200 || !response.data)
- return null;
-
- // Finalize Attachments with auth tokens
- response.data.Attachments.forEach((val) => {
- val.Uri = _addAuthToken(user, sessionId, val.Uri, options.applicationId);
- });
- // Finalize DXF resources with auth tokens
- response.data.DxfUrl = _addAuthToken(user, sessionId, response.data.DxfUrl, options.applicationId);
- return response.data;
- }, (err) => {
- if (this.onLoadError)
- this.onLoadError(err);
- });
- });
- if (this.onLoad) {
- promise.then(this.onLoad, this.onLoadError);
- }
- return promise;
- }
-
- /**
- * Return DXF query url
- *
- * @param {object} product The product object returned from MagiCAD.load() function
- * @param {object} options <pre>
- * {
- * QModelParameters: Optional QModelParameters of model, in format "L=100;D=25;W1=130...",
- * Filename: Optional file name and extension for the object to download, in format "example.dxf"
- * }
- * </pre>
- * @returns DXF url customized with given options. If invalid options object is provided, returns default DXF url, or null if no DXF URL exists
- */
- getCustomizedDxfQueryUrl(product, options){
- try{
- return _replaceOptionsFromBase64EncodedUrl(options, new URL(product.DxfUrl));
- }
- catch (e) {
- return null;
- }
- }
-
- /**
- * Return dimension image query url
- *
- * @param {object} options <pre>
- * {
- * QModelId: Optional QModelId of model,
- * QModelParameters: Optional QModelParameters of model,
- * ViewMode: one value of { 0=Rendered, 1=DimensionLabels, 2=DimensionValues },
- * ViewPosition: one value of { 0=Default, 1=Front, 2=Right, 3=Left, 4=Top, 5=Bottom, 6=IsometricLeft, 7=IsometricRight }
- * }
- * @returns Dimension image url
- */
- getDimensionImageQueryUrl(options) {
- return _getResourceQueryUrl(options, systemconfig.DIMENSIONSIMAGEQUERYPATH);
- }
-
- /**
- *
- * Return image query url
- *
- * @param {object} options <pre>
- * {
- * QModelId: Optional QModelId of model,
- * QModelParameters: Optional QModelParameters of model,
- * ViewPosition: one value of { 0=Default, 1=Front, 2=Right, 3=Left, 4=Top, 5=Bottom, 6=IsometricLeft, 7=IsometricRight }
- * }
- * @returns Image url
- */
- getImageQueryUrl(options) {
- return _getResourceQueryUrl(options, systemconfig.IMAGEQUERYPATH);
- }
-
- /**
- *
- * Renders X3D Image container to given container
- *
- * @param {object} options <pre>
- * Basic example:
- *
- * {
- * x3dUri: location of x3d,
- * imageUri: location of image
- * containerId: identifier of the container for x3d,
- * }
- *
- * Or, to get 3D view with custom model parameters:
- * {
- * QModelId: the identifier of the 3D geometry (GUID format),
- * QModelParameters: Optional QModelParameters of model,
- * ViewMode: one value of { 0=Rendered, 1=DimensionLabels, 2=DimensionValues,
- * containerId: identifier of the container for x3d,
- * }
- *
- * Or, to get 3D view with product external reference and variant qpd id:
- * {
- * productId: the external reference of the product (GUID format)
- * variantQpdId: the qpd id of the specific variant,
- * containerId: identifier of the container for x3d
- * }
- *
- * Or, to get 3D view with custom level of detail (LOD):
- * {
- * QModelId: the identifier of the 3D geometry (GUID format),
- * QModelParameters: Optional QModelParameters of model,
- * LodLevel: one value of { 0=Preview, 1=MC LOD 200, 2=MC LOD 300, 3=MC LOD 350 },
- * containerId: identifier of the container for x3d,
- * }
- *
- * @param {boolean} update Update existing container with new image url
- * @return {Promise<void>} result as promise
- */
- renderX3D(options, update) {
- if (!this.x3dViewService) {
- return new Promise((resolve, reject) => {
- reject("Enable X3D in MagiCAD.init() function");
- });
- }
- let queryOptions = {
- containerId : (options || {}).containerId,
- imageUri : (options ||{}).imageUri,
- x3dUri : (options || {}).x3dUri
- };
-
- let queryObject = _extendQModelOptions(options);
-
- if (queryObject.QModelId) { // QModelId is set, override image and x3d
- queryOptions.x3dUri = systemconfig.APIURL + systemconfig.X3DQUERYPATH + base64.b64EncodeUnicode(JSON.stringify(queryObject));
- queryOptions.imageUri = systemconfig.APIURL + systemconfig.IMAGEQUERYPATH + base64.b64EncodeUnicode(JSON.stringify(queryObject));
- }
-
- else if (queryObject.variantQpdId && queryObject.productId) { // Product external reference and variant QpdId is set, override image and x3d
- queryOptions.x3dUri = systemconfig.APIURL +
- systemconfig.X3DBYQPDIDPATH
- .replace('{productId}', queryObject.productId)
- .replace('{encodedVariantQpdId}', base64.b64EncodeUnicode(queryObject.variantQpdId));
-
- queryOptions.imageUri = systemconfig.APIURL +
- systemconfig.IMAGEBYQPDIDPATH
- .replace('{productId}', queryObject.productId)
- .replace('{encodedVariantQpdId}', base64.b64EncodeUnicode(queryObject.variantQpdId));
- }
-
- return this.x3dViewService.loadX3D(queryOptions, update).then(result => {
- if (this.onRenderX3D) this.onRenderX3D();
- return result;
- });
-
- }
-
- /**
- * Render MagiCAD logo to container with specified identified
- *
- * @param {string} containerId Container identifier
- * @param {boolean} transparent Boolean value should transparent image be used
- */
- renderMagiCADLogo(containerId, transparent) {
- let container = document.getElementById(containerId);
- if (!container)
- return;
- let data = {
- ImageUrl: transparent ?
- systemconfig.MAGICLOUDLOGOTRANSPARENT : systemconfig.MAGICLOUDLOGO,
- Alt: 'Powered by MagiCAD',
- Title: 'Powered by MagiCAD'
- };
- container.innerHTML = `<img src="${data.ImageUrl}" alt="${data.Alt}" title="${data.Title}" />`;
- }
-
- /**
- * Render MagiCAD logo to container with specified identified
- * @param {*} containerId Container identifier
- * @param {*} transparent Boolean value whether transparent image should be used
- * @deprecated Use renderMagiCADLogo instead
- */
- renderMagiCloudLogo(containerId, transparent) {
- this.renderMagiCADLogo(containerId, transparent);
- }
-
- /**
- * Set specified diagram and bind click event to given elementId. Click event will add possible data to given dataElementId
- * @param {object} data Product data
- * @param {object} options <pre>Example:
- * {
- * type: diagramType,
- * elementId: 'el',
- * dataElementId: 'dataEl'
- * }
- * where diagramType is one of { Ventilation, Heating, Cooling, SupplyAir, ExtractAir, Radiator, Pump }
- * </pre>
- */
- setDiagram(data, options) {
- if (!options || !options.elementId || !options.type ||
- !data.Diagrams || !data.Diagrams[options.type])
- return;
-
- let element = document.getElementById(options.elementId);
- if (!element)
- return;
-
- element.innerHTML = '';
- let img = utils.createElement('img', {
- src: data.Diagrams[options.type].BaseUrl,
- alt: options.type
- });
- element.appendChild(img);
-
- // Set diagram data if exists
- let hasData = data.Diagrams[options.type].HasData;
- if (hasData) {
- let baseUrl = data.Diagrams[options.type].BaseUrl;
- let dataElement = document.getElementById(options.dataElementId);
- if (!dataElement)
- return;
- if (options.operationPoint && options.operationPoint.x && options.operationPoint.y &&
- options.operationPoint.x >= 0 && options.operationPoint.y >= 0) {
-
- let diagram = {
- URL: baseUrl,
- DataURL: hasData ? baseUrl + '/data' : null,
- operationPoint: options.operationPoint,
- HasData: hasData
- };
- _setDiagramImages(this.diagramService, img, dataElement, diagram, options.type);
- }
- let that = this;
- img.addEventListener('click', (event) => {
- let diagram = that.diagramService.getDiagram({
- target: img,
- data: {
- BaseURL: baseUrl,
- HasData: hasData
- },
- pageX: event.pageX,
- pageY: event.pageY
- });
- that.diagramService.getOperatingPoint(diagram).then(() => {
- _setDiagramImages(that.diagramService, img, dataElement, diagram, options.type);
- }, () => {
- // Failure when performing getOperatingPoint
- });
- });
- }
- }
-
- /**
- * Get pressure drop of curve at specific flow.
- * @return Example {Succeed: true, Value: 27.870676}
- * @param {string} productId Product identifier (GUID)
- * @param {string} systemTypeId Value = {Unknown, AnyFluid, SupplyFluid, ReturnFluid, ColdWater, HotWater, FireHydrant, HotSupplyFluid, Sprinkler, Sewer, AnyAir, SupplyAir, ExtractAir, OutdoorSupply, OutdoorExhau}
- * @param {number} qv Specified flow
- * @param {number} fanSpeed Specified Fan Speed
- */
- getDpTot(productId, systemTypeId, qv, fanSpeed) {
- let promise = this.ahuCalculationService.getDpTot(productId, systemTypeId, qv, fanSpeed);
- if (this.onGetDpTot) {
- promise.then(this.onGetDpTot);
- }
- return promise;
- }
-
- /**
- * Find suitable fanSpeed for given operation point.
- * @private
- * @return Example {PressureDrop: 107.4791, Succeed: true, Value: 6}
- * @param {string} productId Product identifier (GUID)
- * @param {string} systemTypeId Value = {Unknown, AnyFluid, SupplyFluid, ReturnFluid, ColdWater, HotWater, FireHydrant, HotSupplyFluid, Sprinkler, Sewer, AnyAir, SupplyAir, ExtractAir, OutdoorSupply, OutdoorExhau}
- * @param {number} qv Specified flow
- * @param {number} dpTot Pressure drop value
- */
- findOptimalSpeed(productId, systemTypeId, qv, dpTot) {
- let promise = this.ahuCalculationService.findOptimalSpeed(productId, systemTypeId, qv, dpTot);
- if (this.onFindOptimalSpeed) {
- promise.then(this.onFindOptimalSpeed);
- }
- return promise;
- }
- }