Options
All
  • Public
  • Public/Protected
  • All
Menu

Trimble Connect Workspace API

Trimble Connect Workspace API Documentation

Jump to Quick starts

The Trimble Connect Workspace API allows the client applications to interact with the Trimble Connect Web. It utilizes window.postMessage() to facilitate the communication. There are two methods to utilize the Trimble Connect Workspace API:

  • The client application embeds the Trimble Connect Web Modules or Trimble Connect 3D Viewer in an iframe.
  • The client application is embedded inside the Trimble Connect Web or 3D Viewer as extensions.

Installation

For Typescript use, add the Trimble Connect Workspace API component as a dependency to your project. The component bundles TypeScript v2 definition files for use in TypeScript projects and to support tools that can read .d.ts files. For ES6-module-friendly consumers, you can also import the modules directly, or import them from the root module.

install trimble-connect-workspace-api npm package.

npm i trimble-connect-workspace-api --save

Alternatively, it is also possible to directly import the IIFE module from the below URL.

<script src="https://components.connect.trimble.com/trimble-connect-workspace-api/index.js" />

Quick Start - Trimble Connect 3D viewer

  1. Put together the 3D Viewer and the client application:

    Page structure

    • Embed the 3D Viewer inside the application using an iframe

    HTML

     <iframe
    src="https://web.connect.trimble.com/?isEmbedded=true"
    id="viewer"
    sandbox="allow-scripts allow-modals allow-forms allow-same-origin"
    width="100%"
    height="700px" />

    Javascript

         const API = await TrimbleConnectWorkspace.connect(document.getElementById("viewer"), 
    (event, args) => {
    console.log(event, args);
    }
    );
    await API.embed.setTokens({accessToken: "accessToken_here"});
    // (or) await API.embed.setTokens({shareToken: "shareToken_here"});
    await API.embed.init3DViewer({projectId: "projectId_here"});
    // (or) await API.embed.init3DViewer({}); // if you want to select a project from the list

    • 3Dviewer can be embedded using the actual URL but which is not recommanded, we are simply keeping this as a legacy support.

    HTML

     <iframe
    src="https://web.connect.trimble.com/projects/:projectId/viewer/3d"
    id="viewer"
    sandbox="allow-scripts allow-modals allow-forms allow-same-origin"
    width="100%"
    height="700px" />
    • Note: projectId can be undefined if you want to select a project from the projects list.

    Javascript

         const API = await TrimbleConnectWorkspace.connect(document.getElementById("viewer"), 
    (event, args) => {
    console.log(event, args);
    }
    );
    await API.embed.setTokens({accessToken: "accessToken_here"});
    // (or) await API.embed.setTokens({shareToken: "shareToken_here"});
  2. Configuring the extension in 3D Viewer:

    • It is possible to configure extensions that are used for each Connect Project via 3D Viewer Extensions Settings. Basically, it is possible to define a new extension manually or through an extension definition (a manifest):

    • Manually: Specify all extension parameters manually

      • Click on Advanced text button
      • Specify the extension title, extension URL (and other metadata)
    • Extension URL: The URL to the extension manifest file, which is a JSON file that specifies all extension parameters (e.g. Extension title, Extension URL...). The data structure follows the ExtensionSetting interface. For example:

      {
      "url": "https://my.awesome.app/extension",
      "title": "This is my extension",
      "infoUrl": "https://my.awesome.app/extension/help.html"
      }
  3. All the APIs will be exposed through the return value of connect method.

    • The workflow of the Workspace API can be illustrated as below:

    Trimble Connect Workspace API Workflow

  4. Authentication:

    • When the client application embeds the 3D Viewer in an iframe, the valid accessToken should be passed to the 3D Viewer using embed.setTokens. It will also accept refreshToken optionally.

    If the refreshToken passed then the accessToken refresh responsibility is passed to the 3D Viewer. Keep in mind that the accessToken refresh responsibility cannot be shared between the client application and 3D Viewer, only one application should perform the refresh. If the accessToken is refreshed by 3D Viewer, 3D Viewer will emit an extension.accessToken event with the new accessToken.

    • If the refreshToken is not passed to the 3D Viewer, it is the client application's responsibility to handle the accessToken refresh. 3D Viewer will help in the process by emitting the extension.sessionInvalid event when the accessToken expired or was invalidated. After the accessToken is refreshed by the client application, it can be passed back to the 3D Viewer by calling the same embed.setTokens API with the new accessToken.

    • When the client application is embedded inside the 3D Viewer as an extension, the accessToken should be retrieved from 3D Viewer by calling the extension.requestPermission API. This call will initially display a message requesting for the user consent for the client application to use the accessToken. If the user consents, the call will return the accessToken which can then be used by the client application. In this case, the 3D Viewer application will handle the tokens, including the tokens refresh. When the accessToken is refreshed, the 3D Viewer will emit an extension.accessToken event with the new accessToken.

  5. Query parameters:

    • When using embed.init3DViewer, you can pass all the possible query params as a config argument to init3DViewer. No query params are needed.

    • Note: The following query params kept only for legacy support, we highly recommand the use of embed.init3DViewer.

      • embed: https://web.connect.trimble.com/projects/:projectId/viewer/3d/?embed=false Specifies if the application is embedded in a sandboxed environment. If true, the application will emulate the local storage.

      • projectId: https://web.connect.trimble.com/projects/:projectId/viewer/3d/?projectId=projectId The id of a project that will be automatically loaded by 3D Viewer application, if it exists.

      • modelId: https://web.connect.trimble.com/projects/:projectId/viewer/3d/?projectId=projectId&modelId=my_model_id1,my_model_id2 The id of a model that will be automatically loaded by 3D Viewer application, if it exists in the specified project. Used in conjuction with projectId. Accepts an array of values, separated by comma.

      • versionId: https://web.connect.trimble.com/projects/:projectId/viewer/3d/?projectId=project_id&modelId=model_id1,model_id2&versionId=model_version_id1,model_version_id2 The version id of a model that will be automatically loaded by 3D Viewer application, if it exists in the specified project. Used in conjuction with modelId and projectId. Accepts an array of values, separated by comma.

      • viewId: https://web.connect.trimble.com/projects/:projectId/viewer/3d/?projectId=projectId&viewId=my_view_id The id of a view that will be automatically loaded by 3D Viewer application, if it exists. Used in conjuction with projectId.

      • todoId: https://web.connect.trimble.com/projects/:projectId/viewer/3d/?projectId=projectId&todoId=my_todo_id The id of a to do that will be automatically loaded by 3D Viewer application, if it exists. Used in conjuction with projectId.

      • clashSetId: https://web.connect.trimble.com/projects/:projectId/viewer/3d/?projectId=projectId&clashSetId=my_clash_set_id The id of a clash set that will be automatically loaded by 3D Viewer application, if it exists. Used in conjuction with projectId.

  6. Examples: Initiate the connection between the client application and 3D Viewer

    • Embed the 3D Viewer inside the application using an iframe: This should be done after the iframe has been loaded. The connection initiation should be done in an async function as the connection is only established once the user has selected a Trimble Connect project in the 3D Viewer.

        <script src="https://components.connect.trimble.com/trimble-connect-workspace-api/index.js"></script>
      <div>
      <button onclick="doConnect()">connect</button>
      <iframe hidden id="viewer" src="https://web.connect.trimble.com/?isEmbedded=true" width="100%" height="750px"/>
      <script>
      function doConnect(){
      var viewer = document.getElementById("viewer");
      viewer.hidden = false;
      var API = await TrimbleConnectWorkspace.connect(viewer, (event, data) => {
      console.log("Event: ", event, data);
      });
      API.embed.setTokens({accessToken: "accessToken_here"}); // or {shareToken: "shareToken_here"}
      API.embed.init3DViewer({projectId: "projectId_here"});
      }
      </script>
      </div>
    • Embed the application inside the 3D Viewer as an extension: Directly issue the connect request to the parent window (3D Viewer) that is hosting the application:

        <script src="https://components.connect.trimble.com/trimble-connect-workspace-api/index.js"></script>
      <script>
      var API = await TrimbleConnectWorkspace.connect(window.parent, (event, data) => {
      console.log("Event: ", event, data);
      });

      API.project.getProject().then(project => {
      console.log(project); // Trimble Connect project details
      });
      </script>
    • Check out the example client application for more details!

Quick Start - Trimble Connect Project Extensions

  • Trimble Connect Web extension framework to enable extension owners (or integrator applications) to expose additional capabilities / functionalities through Trimble Connect Web application within the Trimble Connect project context.

  • This framework allows creation of new extensions through manifest files and displays the menu provided by the extension in TCWEB left panel navigation. It also allows additional configuration for the extensions if needed (through configCommand property).

  1. Example Implementation

    import * as WorkspaceAPI from "trimble-connect-workspace-api";

    ....
    ....

    /** Instantiate extension .
    * @param window - Parent window object.
    * @param callback - Listen the events with args from the parent.
    * @param timeout - Connect timeout in milliseconds.
    * @returns TCExtensionAPI - Object with the interaction methods.
    */
    this.API = await WorkspaceAPI.connect(
    window.parent,
    (event, args) => {
    switch (event) {
    case "extension.command":
    //"Command executed by the user: args.data"
    break;
    case "extension.accessToken":
    //"Accestoken or status: args.data"
    break;
    case "extension.userSettingsChanged":
    //"User settings changed!"
    break;
    default:
    }
    },
    30000
    );

    ....
    ....

    // Updating the menu object.
    this.API.ui.setMenu("<mainMenuObject>:ExtensionMainMenu")
    // Where <mainMenuObject> is the menu object and ExtensionMainMenu is the object type which you can find it in the documentation.

    // Updating the active submenu.
    this.API.ui.setActiveMenuItem("<submenuCommand>:string");

    // Get the current project info
    this.API.project.getCurrentProject().then((projectInfo: ConnectProject) => {
    //Current project info: projectInfo.
    });

    //Get the current user language info.
    this.API.user.getUserSettings().then((userSettings: UserSettings) => {
    //Current user language: userSettings.language
    });

    //Updating the status message.
    this.API.extension.setStatusMessage("<statusMessage>:string");

    //Request for the access token.
    this.API.extension.getPermission("accesstoken").then((accessToken: string) => {
    //Current user access token or status: accessToken
    });
  2. Example manifest JSON

    {
    "icon": "http://example.com/app_icon.png",
    "title": "React example",
    "url": "http://example.com/index.html",
    "description": "Test extension",
    "configCommand": "do_config",
    "enabled": false
    }
    • Example manifest JSON link.

    • While adding new custom extensions, please ensure your manifest file url is CORS enabled to avoid any issues in the extension creation. As the TCWEB application will try to download the extension manifest file to read it's contents before creating the extension, it is important that the manifest file url (example: https://foo.example.manifestfile.com/manifest.json) is CORS enabled to allow access from Trimble Connect Web. For example, when Trimble Connect Web tries to fetch the file, the server should respond with proper CORS response headers (Example: Access-Control-Allow-Origin, Access-Control-Allow-Methods etc.,). Please refer to Cross-Origin Resource Sharing (CORS) - HTTP | MDN for details.

  3. Example menu object

    const mainMenuObject = {
    title: "Test extension app",
    icon: "http://example.com/main_menu_icon.png",
    command: "main_nav_menu_cliked",
    subMenus: [
    {
    title: "Sub menu 1",
    icon: "http://example.com/sub_menu_icon.png",
    command: "submenu_1_clicked",
    },
    {
    title: "Sub menu 2",
    icon: "http://example.com/sub_menu_icon.png",
    command: "submenu_2_clicked",
    },
    ],
    };
  4. Example

    • Example extension manifest url - here

FAQ

Project Extensions

  • How to create an extension in TCWEB?

    • Extension is created based on the manifest file shared by the extension owner. This can be done through TCWEB -> Project Settings -> Extensions page by providing the url of the manifest file.
      This manifest will be a JSON file with the below fields
      title - Type: string - Title of the extension to be displayed within TCWEB -> Project Settings -> Extensions page. This field is mandatory.
      icon - Type: string - Icon URL of the extension to be displayed within TCWEB -> Project Settings -> Extensions page. As per current UX, this field is not used but might be used at a later point in time. This field is optional.
      url - Type: string - URL for extension (that is the integrator application) application. This is expected to contain the web application that knows how to interact with TCWEB through trimble-connect-project-workspace-api - provides the menu to be displayed for the extension, provides configuration UI (optional) and other interactions. This field is mandatory.
      description - Type: string - Description of the extension to be displayed within TCWEB -> Project Settings -> Extensions page. This field is optional.
      configCommand - Type: string - This will be passed to the extension through the command event when the gear icon(configuration icon) is clicked in the TCWEB -> Project Settings -> Extensions page. This field is optional.
      enabled - Type: Boolean - This will set the extension as visible on creation. This field is optional. Default is false.
  • How to enable / disable extension?

    • It can be turned on or turned off through the toggle button by visiting TCWEB -> Project Settings -> Extensions page.
  • Who can configure the extensions?

    • Extensions are set up at the project level by the Project Administrator.
  • Who decides on the main navigation menu for the extension? What is the structure of the menu?

    • The navigation menu object is passed by the extension application (refers to the url mentioned in the extension manifest) to TCWEB and TCWEB renders it in it’s left panel navigation. The menu object should conform to the below structure. As of now the menu object can contain just two levels - one parent menu item and one/more submenu items. Please note that the values in the sample below are given for illustration purposes only and hence they need to be updated to reflect your extension’s need.
      Dynamic Menu Structure: (received from extension while loading the extension. extension creator should be aware of this):

      {
      "title": "Quadri shared Model",
      "icon": "https://abcd.com/images/q.svg",
      "command": "QUADRI_TOP_MENU", /*This will be passed to the extension when the menu is clicked*/
      "subMenus": [
      {
      "title": "Quadri shared Modelsubmenu1",
      "icon": "https://abcd.com/images/q1.svg",
      "command": "QUADRI_SUB_MENU1", /*This will be passed to the extension when the menu is clicked*/
      },
      {
      "title": "Quadri shared Model submenu2",
      "icon": "https://abcd.com/images/q2.svg",
      "command": "QUADRI_SUB_MENU2", /*This will be passed to the extension when the menu is clicked*/
      },
      ]
      }
  • Where the extensions will be displayed?

    • The extension application will be embedded inside Trimble Connect Web application and it will occupy the middle & right panel within the Project page and the extension menu will appear in the left panel along with other navigation.
  • What is the mechanism used to enable interaction between the extension application and the TCWEB application?

    • This is enabled through methods & events provided by trimble-connect-project-workspace-api. Under the hood, it utilizes window.postMessage() to facilitate the communication.
  • Are extension manifest url and the extension url the same?

    • No.
      Extension manifest url - It contains the basic configuration for the extension including extension url, title, description, icon etc. This what you will need to enter in the TCWEB -> project settings -> extensions page.
      Extension url - It is the actual url of the extension application which includes trimble-connect-project-workspace-api to interact with TCWEB including menu object setting, requesting the access token from TCWEB etc. This is mentioned within the manifest file.
  • Can I pass query params along with submenu command while calling setActiveMenuItem?

    • Yes.
      This may be useful for some extensions if they want use the same submenu for different states/routes (identified through query parameters) which are dynamic in nature.
      Example scenario - Let's assume the submenu command is task. If the setActiveMenu API is called with the command task?id=7, TCWEB UI will make the 'task' submenu active and the extension will receive what (command with query parameters - task?id=7) it has passed to the TCWEB application.

Embeddable Components

  • After an access token has been expired for a few hours, may API.embed.setTokens still be used to wake up the connection?

    • The embed.setTokens must be called with a new accessToken before the current token become expired in order to maintain the seamless user experience.
  • What is the difference between the error messages received during the integrations with the trimble-connect-workspace-api - “Please refresh the user session. The user session is invalid” and “Access Denied. You don’t have access to the trimble connect web modules"

    • The 1st error will appear when the given accessToken is expired, and the 2nd error will appear when the embed.setTokens is called without an accessToken.
  • Will the same event "embed.session.invalid" be sent for both cases mentioned above?

    • accessToken is a required property for the embed.setTokens API param, the Access denied is just a fallback screen for that (in case it's empty). So no event will be passed, But in this case, the boolean promise returned by embed.setTokens will resolve with false. The embed.session.invalid event will be passed only when the accessToken is expired

Questions