Pilot-Web-SDK

Pilot-Web-SDK предназначен для создания frontend и backend модулей расширений к Pilot-Web-Server.

Содержание

Описание настройки сборки расширений

Инжектирование зависимостей

Описание интерфейсов и методов Pilot-Web-Server

1. Интерфейсы поведения

2. Интерфейсы для встраивания в UI

3. Интерфейсы для перехвата событий клиентского приложения

4. Интерфейсы управления данными

5. Интерфейсы контекста визуального представления документа

6. Интерфейсы контекста визуального представления пространства модели

7. Дополнительные интерфейсы и утилиты

Описание настройки сборки расширений

Общая информация

Расширения для Pilot-Web-Server могут состоять из следующих компонентов:

Настройка и запуск проекта frontend-расширения

TypeScript расширение

Настройка TypeScript-расширения

Чтобы создать новое TypeScript-расширение для Pilot-Web-Server выполните следующие действия:

npm init

Можно пользоваться и другими пакетными менеджерами (например, yarn), однако примеры будут приведены для npm.

npm i @pilotdev/pilot-web-sdk
npm i --save-dev typescript ts-loader webpack webpack-cli copy-webpack-plugin
  {
    "scripts": {
      ...,
+     "build": "webpack",
+     "build-prod": "webpack --config webpack.prod.config.js"
    },
    "dependencies": {
      ...
    },
    ...
  }
{
  "manifestVersion": 1,
  "author": "",
  "license": "",
  "title": "",
  "version": "",
  "extension": {
    "name": "ext_name",
    "entry": "ext_name.js",
    "modules": []
  }
}

и заполните поля author, license, title, version, name, a так же поле entry по шаблону [name].js, где [name] - значение поля name. Например: ext_name.js.

Интерактивные подсказки и валидация в IDE

В начале файла добавьте поле $schema со значением пути, указывающим на схему extensions.config.schema.json из пакета @pilotdev/pilot-web-sdk

{
  "$schema": "../../../node_modules/@pilotdev/pilot-web-sdk/extensions.config.schema.json",
  ...
}
npx tsc --init
const ModuleFederationPlugin = require('webpack/lib/container/ModuleFederationPlugin');
const CopyPlugin = require("copy-webpack-plugin");
module.exports = [{ 
  mode: "development",
  entry: {main: './src/index.ts'},
  module: {
    rules: [{
        test: /\.tsx?$/,
        use: 'ts-loader',
        exclude: /node_modules/ 
    }]
  },
  resolve: {
    extensions: [".tsx", ".ts", ".jsx", ".js", ".json"],
  },
  output: {
    publicPath: 'auto',
    uniqueName: 'ext_name',
    scriptType: 'text/javascript',
    filename: '[name].js',
    clean: true
  },
  optimization: {
    // fix a temporary bug
    runtimeChunk: false
  },
  plugins: [
    new ModuleFederationPlugin({
      name: 'ext_name',
      library: { type: 'var', name: '[name]' },
      filename: '[name].js',
      exposes: [],
      shared: {
        '@pilotdev/pilot-web-sdk': {
          singleton: true,
        }
      }
    }),

    new CopyPlugin({
      patterns: [
        { from: "./src/assets/extensions.config.json", to: "extensions.config.json" }
      ],
    }),
  ]
}]

и заполните поле uniqueName в блоке output и поле name в параметре конструктора ModuleFederationPlugin. Значения должны совпадать со значением name из extensions.config.json.

const { merge } = require("webpack-merge");
const dev = require("./webpack.config.js");

module.exports = merge(dev, {
  mode: "production",
});
import { IMenu, IMenuBuilder, ObjectsViewContext } from "@pilotdev/pilot-web-sdk";
export class ExtensionSample extends IMenu<ObjectsViewContext> {
  build(builder: IMenuBuilder, context: ObjectsViewContext): void {
  }

  onMenuItemClick(name: string, context: ObjectsViewContext): void {
  }
}
const ModuleFederationPlugin = require('webpack/lib/container/ModuleFederationPlugin');
const CopyPlugin = require("copy-webpack-plugin");
module.exports = [{ 
  mode: "development",
  entry: {main: './src/index.ts'},
  module: {
    rules: [{
        test: /\.tsx?$/,
        use: 'ts-loader',
        exclude: /node_modules/ 
    }]
  },
  resolve: {
    extensions: [".tsx", ".ts", ".jsx", ".js", ".json"],
  },
  output: {
    publicPath: 'auto',
    uniqueName: 'ext_name',
    scriptType: 'text/javascript',
    filename: '[name].js',
    clean: true
  },
  optimization: {
    // fix a temporary bug
    runtimeChunk: false
  },
  plugins: [
    new ModuleFederationPlugin({
      name: 'ext_name',
      library: { type: 'var', name: '[name]' },
      filename: '[name].js',
-     exposes: [],
+     exposes: [
+       {'IMenu<ObjectsViewContext>': './src/app/extensionSample.ts'}
+     ],
      shared: {
        '@pilotdev/pilot-web-sdk': {
          singleton: true,
        }
      }
    }),

    new CopyPlugin({
      patterns: [
        { from: "./src/assets/extensions.config.json", to: "extensions.config.json" }
      ],
    }),
  ]
}]
  {
    "manifestVersion": 1,
    "author": "",
    "license": "",
    "title": "",
    "version": "",
    "extension": {
      "name": "ext_name",
      "entry": "ext_name.js",
-     "modules": [],
+     "modules": [
+       { "ngModuleName":"ExtensionSample", "exposedInterface":"IMenu<ObjectsViewContext>" }
+     ]
    }
  }

Запуск TypeScript-расширения

Debug

Для того чтобы собрать расширение в отладочном режиме, запустите скрипт build:

npm run build

Затем запустите контейнер с Pilot-Web-Server с ключом -e AppSettings:Mode=Development

docker run -d -p 80:80 -e PilotServer:Url=http://0.1.5.100:5545 -e PilotServer:Database=demo -e AppSettings:Mode=Development --name pilot-web-server pilotdev/pilot-web-server:latest

Далее предоставьте доступ к папке dist по порту 4300 - это можно сделать, например, запустив плагин Live Server для Visual Studio Code с конфигурационным файлом \.vscode\settings.json

{
  "liveServer.settings.root": "./dist",
  "liveServer.settings.port": 4300
}

Production

Для того чтобы собрать и запустить production-расширение, запустите скрипт build-prod:

npm run build-prod

Затем в папке dist создайте zip архив с папкой frontend (сама папка должна попасть в архив). В клиентском приложении Pilot создайте объект с типом Веб-расширение (WebExtension) и прикрепите архив. Подробнее на help.pilotems.com

Angular-расширение

Настройка angular-расширения

Чтобы создать angular-расширение, выполните следующие действия:

ng new angular-ext
npm install @pilotdev/pilot-web-sdk
npm install @angular-architects/module-federation --save-dev

если произошла ошибка несовпадения версий зависимостей, то выполните команду:

npm config set legacy-peer-deps true
const ModuleFederationPlugin = require('webpack/lib/container/ModuleFederationPlugin');
module.exports = {
  output: {
    publicPath: 'auto',
    uniqueName: 'angular_ext',
    scriptType: 'text/javascript',
  },
  optimization: {
    // fix a temporary bug
    runtimeChunk: false
  },
  plugins: [
    new ModuleFederationPlugin({
      name: 'angular_ext',
      library: { type: 'var', name: 'angular-ext' },
      filename: '[name].js',
      exposes: {
      },
      shared: {
        '@angular/core': {
          singleton: true,
        },
        '@angular/common': {
          singleton: true,
        },
        '@angular/forms': {
          singleton: true,
        },
        '@pilotdev/pilot-web-sdk': {
          singleton: true,
        }
      }
    })
  ]
};

и заполните поля uniqueName, name и library.name. Добавьте в секцию shared используемые библиотеки, чтобы их переиспользовать в хост-приложении. Подробнее: https://webpack.js.org/plugins/module-federation-plugin

npm install @angular-builders/custom-webpack --save-dev
  {
      ...
        "sourceRoot": "src",
        "prefix": "app",
        "architect": {
          "build": {
+           "builder": "@angular-builders/custom-webpack:browser",
            "options": {
              "outputPath": "dist/angular-ext",
              "index": "src/index.html",
              "polyfills": [
                "zone.js"
              ],
      ...
  }	  
  {
    "$schema": "./node_modules/@angular/cli/lib/config/schema.json",
    "version": 1,
    "newProjectRoot": "projects",
    "projects": {
      "angular-ext": {
      ...
        "architect": {
          "build": {
            "builder": "@angular-builders/custom-webpack:browser",
            "options": {
              "outputPath": "dist/frontend",
              "index": "src/index.html",
+             "customWebpackConfig": {
+               "path": "webpack.config.js"
+              },
+             "main": "src/main.ts",
              "polyfills": [
                "zone.js"
              ],
    ...
  }
  {
      ...
            "defaultConfiguration": "production"
          },
          "serve": {
+           "builder": "@angular-builders/custom-webpack:dev-server",
            "configurations": {
              "production": {
                "buildTarget": "angular-ext:build:production"
              },
              "development": {
                "buildTarget": "angular-ext:build:development"
              }
            },
            "defaultConfiguration": "development"
      ...
  }
  {
    ...
            "options": {
              "buildTarget": "angular.sample:build"
            }
          },
          "test": {
+           "builder": "@angular-builders/custom-webpack:karma",
            "options": {
              "polyfills": [
                "zone.js",
                "zone.js/testing"
              ],
              "tsConfig": "tsconfig.spec.json",
              "assets": [
                "src/favicon.ico",
                "src/assets"
              ],
              "styles": [
                "src/styles.css"
              ],
              "scripts": []
            }
      ...
  }

Подробнее инструкцию настройки angular-builders/custom-webpack можно прочитать на https://www.npmjs.com/package/@angular-builders/custom-webpack

  {
      ...
      "build": {
        "builder": "@angular-builders/custom-webpack:browser",
        "options": {
+       "outputPath": "dist/frontend",
        "index": "src/index.html",
        "customWebpackConfig": {
          "path": "webpack.config.js"
        },
        "main": "src/main.ts",
        "polyfills": [
          "zone.js"
        ],
      ...
  }
{
  "manifestVersion": 1,
  "author": "",
  "license": "",
  "title": "",
  "version": "",
  "extension": {
    "name": "angular_ext",
    "entry": "angular_ext.js",
    "modules": []
  }
}

и заполните поля author, license, title, version, name, a так же поле entry по шаблону [name].js, где [name] - значение поля name (например: angular_ext.js). Значение поля name должно совпадать со значением name из webpack.config.js.

Интерактивные подсказки и валидация в IDE

В начале файла добавьте поле $schema со значением пути, указывающим на схему extensions.config.schema.json из пакета @pilotdev/pilot-web-sdk

{
  "$schema": "../../../node_modules/@pilotdev/pilot-web-sdk/extensions.config.schema.json",
  ...
}
  {
    ...
      "customWebpackConfig": {
        "path": "webpack.config.js"
      },
      "main": "src/main.ts",
      "polyfills": [
        "zone.js"
      ],
      "tsConfig": "tsconfig.app.json",
      "inlineStyleLanguage": "scss",
      "assets": [
+       { 
+         "glob": "extensions.config.json",
+         "input": "src/config",
+         "output": "./"
+       }
      ],	
    ...
  }
Пример настроенного файла angular.json:

{
  "$schema": "./node_modules/@angular/cli/lib/config/schema.json",
  "version": 1,
  "newProjectRoot": "projects",
  "projects": {
    "angular-ext": {
      "projectType": "application",
      "schematics": {
        "@schematics/angular:component": {
          "style": "scss"
        }
      },
      "root": "",
      "sourceRoot": "src",
      "prefix": "app",
      "architect": {
        "build": {
          "builder": "@angular-builders/custom-webpack:browser",
          "options": {
            "outputPath": "dist/frontend",
            "index": "src/index.html",
            "customWebpackConfig": {
              "path": "webpack.config.js"
            },
            "main": "src/main.ts",
            "polyfills": [
              "zone.js"
            ],
            "tsConfig": "tsconfig.app.json",
            "inlineStyleLanguage": "scss",
            "assets": [
              {
                "glob": "extensions.config.json",
                "input": "src/config",
                "output": "./"
              }
            ],
            "styles": [
              "src/styles.scss"
            ],
            "scripts": []
          },
          "configurations": {
            "production": {
              "budgets": [
                {
                  "type": "initial",
                  "maximumWarning": "500kb",
                  "maximumError": "1mb"
                },
                {
                  "type": "anyComponentStyle",
                  "maximumWarning": "2kb",
                  "maximumError": "4kb"
                }
              ],
              "outputHashing": "all"
            },
            "development": {
              "optimization": false,
              "extractLicenses": false,
              "sourceMap": true
            }
          },
          "defaultConfiguration": "production"
        },
        "serve": {
          "options": {
            "port": 4300,
            "publicHost": "http://localhost:4300"
          },
          "builder": "@angular-builders/custom-webpack:dev-server",
          "configurations": {
            "production": {
              "buildTarget": "angular-ext:build:production"
            },
            "development": {
              "buildTarget": "angular-ext:build:development"
            }
          },
          "defaultConfiguration": "development"
        },
        "extract-i18n": {
          "builder": "@angular-devkit/build-angular:extract-i18n",
          "options": {
            "buildTarget": "angular-ext:build"
          }
        },
        "test": {
          "builder": "@angular-builders/custom-webpack:karma",
          "options": {
            "polyfills": [
              "zone.js",
              "zone.js/testing"
            ],
            "tsConfig": "tsconfig.spec.json",
            "inlineStyleLanguage": "scss",
            "assets": [
              "src/favicon.ico",
              "src/assets"
            ],
            "styles": [
              "src/styles.scss"
            ],
            "scripts": []
          }
        }
      }
    }
  }
}

import { Inject, Injectable } from "@angular/core";
import { IMenu, IMenuBuilder, IObjectsRepository, ObjectsViewContext } from "@pilotdev/pilot-web-sdk"
@Injectable({providedIn: "root"})
export class ExtensionSample implements IMenu<ObjectsViewContext> {
  
  constructor(@Inject(`IObjectsRepository`)private _repository: IObjectsRepository) {
  }

  build(builder: IMenuBuilder, context: ObjectsViewContext): void {
    builder.addItem("SomeMenuItemName", 1)
      .withHeader("Hello from angular extension");
  }

  onMenuItemClick(name: string, context: ObjectsViewContext): void {
    alert(`Angular extension works!`);
  }
}
  const ModuleFederationPlugin = require('webpack/lib/container/ModuleFederationPlugin');
  module.exports = {
    output: {
      publicPath: 'auto',
      uniqueName: 'angular_ext',
      scriptType: 'text/javascript',
    },
    optimization: {
      // fix a temporary bug
      runtimeChunk: false
    },
    plugins: [
      new ModuleFederationPlugin({
        name: 'angular_ext',
        library: { type: 'var', name: 'angular_ext' },
        filename: '[name].js',
-       exposes: {},
+       exposes: {
+         'IMenu<ObjectsViewContext>': './src/app/extensionSample.ts' //added
+       },
        shared: {
          '@angular/core': {
            singleton: true,
          },
          '@angular/common': {
            singleton: true,
          },
          '@angular/forms': {
            singleton: true,
          },
          '@pilotdev/pilot-web-sdk': {
            singleton: true,
          }
        }
      })
    ]
  };
  {
    "manifestVersion": 1,
    "author": "",
    "license": "",
    "title": "",
    "version": "",
    "extension": {
      "name": "angular_ext",
      "entry": "angular_ext.js",
-     "modules": [],
+     "modules": [
+       { "ngModuleName":"ExtensionSample", "exposedInterface":"IMenu<ObjectsViewContext>" }
+     ]
    }
  }	
import { bootstrapApplication } from '@angular/platform-browser';
import { appConfig } from './app/app.config';
import { AppComponent } from './app/app.component';
import * as ext from "./app/extensionSample" 
bootstrapApplication(AppComponent, appConfig)
  .catch((err) => console.error(err));

Встраивание Angular в UI

Для встраивания Angular в приложение, реализуйте интерфейс IOpenspaceView с необходимым контекстом, например:

import { IOpenspaceView, PageContext } from "@pilotdev/pilot-web-sdk";

export class AngularView implements IOpenspaceView<PageContext> {
  getViewId(): string {
  }

  getView(): HTMLElement | undefined {
  }
}

Реализуйте метод getViewId() для идентификации отображения:

getViewId(): string {
  return "AngularViewId";
}

Реализуйте метод getView():

import { IOpenspaceView, PageContext } from "@pilotdev/pilot-web-sdk";
import { ApplicationRef, ComponentRef, createComponent, Injectable, NgZone } from '@angular/core';
import { createApplication } from '@angular/platform-browser';

import { AppComponent } from '../../app.component';

export class AngularView implements IOpenspaceView<PageContext> {
  private _rootElement: HTMLElement | undefined;
  private _appRef: ApplicationRef | undefined;
  private _componentRef: ComponentRef<AppComponent> | undefined;

  ...

  getView(): HTMLElement | undefined {
    if (!this._rootElement) {
      this._rootElement = document.createElement("div");
    }

    if (!this._appRef) {
      createApplication({
        providers: [],
      }).then((appRef: ApplicationRef) => {
        this._appRef = appRef;

        const zone = appRef.injector.get(NgZone);
        zone.run(() => {
          this._componentRef = createComponent(AppComponent, {
            environmentInjector: appRef.injector,
            hostElement: this._rootElement,
          });

          appRef.attachView(this._componentRef.hostView);
        });
      });
    }

    return this._rootElement;
  }
}

Для освобождения ресурсов, необходимо реализовать интерфейс поведения IDisposable и его метод IDisposable.dispose():

import { IOpenspaceView, PageContext } from "@pilotdev/pilot-web-sdk";
import { ApplicationRef, ComponentRef } from '@angular/core';

import { AppComponent } from '../../app.component';

export class AngularView implements IOpenspaceView<PageContext> {
  private _rootElement: HTMLElement | undefined;
  private _appRef: ApplicationRef | undefined;
  private _componentRef: ComponentRef<AppComponent> | undefined;

  ...

  dispose(): void {
    if (this._componentRef) {
      this._componentRef.destroy();
      this._componentRef = undefined;
    }

    if (this._appRef) {
      this._appRef.destroy();
      this._appRef = undefined;
    }

    if (this._rootElement) {
      this._rootElement = undefined;
    }
  }
}

Запуск angular-расширения

Debug

Для того чтобы собрать расширение в отладочном режиме, настройте запуск на порту 4300. Для этого добавьте в angular.json в projects.angular-ext.architect.serve поле options:

  {
            ...
            "defaultConfiguration": "production"
          },
          "serve": {
+           "options": {
+             "port": 4300,
+             "publicHost": "http://localhost:4300"
+           },
            "builder": "@angular-builders/custom-webpack:dev-server",
            "configurations": {
              "production": {
                "buildTarget": "angular-ext:build:production"
              },
              "development": {
                "buildTarget": "angular-ext:build:development"
              }
            ...
  }

После этого можно запустить скрипт start:

npm run start

Затем запустите запустите контейнер с Pilot-Web-Server с ключом -e AppSettings:Mode=Development

docker run -d -p 80:80 -e PilotServer:Url=http://0.1.5.100:5545 -e PilotServer:Database=demo -e AppSettings:Mode=Development --name pilot-web-server pilotdev/pilot-web-server:latest

Production

Для того чтобы собрать и запустить production-расширение, добавьте в файл package.json скрипт build-prod:

  {
    ...
    "scripts": {
      ...,
      "start": "ng serve",
      "build": "ng build",
+     "build-prod": "webpack --config webpack.prod.config.js",
      ...
    },
    "private": true,
    "dependencies": {
      ...
    },
    ...
  }

И запустите его:

npm run build-prod

Затем в папке dist создайте zip-архив с папкой frontend (сама папка должна попасть в архив). В клиентском приложении Pilot создайте объект с типом Веб-расширение (WebExtension) и прикрепите архив. Подробнее на help.pilotems.com

React-расширение

Настройка React-расширения

Чтобы создать новое React-расширение для Pilot-Web-Server выполните следующие действия:

npm init

Можно пользоваться и другими пакетными менеджерами (например, yarn), однако примеры будут приведены для npm.

npm i react react-dom @pilotdev/pilot-web-sdk
npm i --save-dev webpack webpack-cli copy-webpack-plugin html-webpack-plugin
npm i --save-dev ts-loader style-loader css-loader
npm i --save-dev typescript typescript-plugin-css-modules @types/copy-webpack-plugin @types/node @types/react @types/react-dom
npx tsc --init
{
  "compilerOptions": {
    "jsx": "react-jsx",
    "allowSyntheticDefaultImports": true,
    "baseUrl": ".",
    "outDir": "./dist/out-tsc",
    "sourceMap": true,
    "declaration": false,
    "downlevelIteration": true,
    "experimentalDecorators": true,
    "module": "esnext",
    "moduleResolution": "node",
    "importHelpers": true,
    "target": "ES2022",
    "typeRoots": ["node_modules/@types"],
    "lib": ["es2020", "dom"],
    "allowJs": true,
    "strict": true,
    "plugins": [{ "name": "typescript-plugin-css-modules" }]
  },
  "include": ["**/*.ts", "**/*.tsx"]
}
  {
    "scripts": {
      ...,
+     "dev": "webpack serve",
+     "build-prod": "webpack --config webpack.prod.config.js",
    },
    "dependencies": {
      ...
    },
    ...
  }
{
  "manifestVersion": 1,
  "author": "",
  "license": "",
  "title": "",
  "version": "",
  "extension": {
    "name": "react-ext",
    "entry": "react-ext.js",
    "modules": []
  }
}

и заполните поля author, license, title, version, name, a так же поле entry по шаблону [name].js, где [name] - значение поля name. Например: react-ext.js.

Интерактивные подсказки и валидация в IDE

В начале файла добавьте поле $schema со значением пути, указывающим на схему extensions.config.schema.json из пакета @pilotdev/pilot-web-sdk

{
  "$schema": "../../../node_modules/@pilotdev/pilot-web-sdk/extensions.config.schema.json",
  ...
}
const ModuleFederationPlugin = require('webpack/lib/container/ModuleFederationPlugin');
const CopyPlugin = require('copy-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports =
{
  mode: 'development',
  entry: { main: './src/index.tsx' },
  module: {
    rules: [
      {
        test: /\.tsx?$/,
        use: 'ts-loader',
        exclude: /node_modules/,
      },
      {
        test: /\.css$/i,
        use: [
          'style-loader',
          { loader: 'css-loader', options: { modules: true } },
        ],
      },
    ],
  },
  resolve: {
    extensions: ['.tsx', '.ts', '.jsx', '.js', '.json'],
  },
  output: {
    publicPath: 'auto',
    uniqueName: 'react-ext',
    scriptType: 'text/javascript',
    filename: '[name].js',
    clean: true,
  },
  optimization: {
    // fix a temporary bug
    runtimeChunk: false,
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: './src/index.html',
    }),
    new ModuleFederationPlugin({
      name: 'react-ext',
      library: {
        type: 'var',
        name: 'react-ext',
      },
      filename: '[name].js',
      exposes: [
      ],
      shared: {
        '@pilotdev/pilot-web-sdk': {
          singleton: true,
        },
      },
    }),
    new CopyPlugin({
      patterns: [
        {
          from: './src/extension/extensions.config.json',
          to: 'extensions.config.json',
        },
      ],
    }),
  ],
  devServer: {
    port: 4300,
    allowedHosts: 'auto',
    headers: {
      'Access-Control-Allow-Origin': '*',
    },
  },
};

и заполните поле uniqueName в блоке output и поле name в параметре конструктора ModuleFederationPlugin. Значения должны совпадать со значением name из extensions.config.json.

const { merge } = require("webpack-merge");
const dev = require("./webpack.config.js");

module.exports = merge(dev, {
  mode: "production",
});
import { IOpenspaceView, PageContext } from "@pilotdev/pilot-web-sdk";

export class ReactView implements IOpenspaceView<PageContext> {
  getViewId(): string {
  }

  getView(): HTMLElement | undefined {
  }
}
  const ModuleFederationPlugin = require('webpack/lib/container/ModuleFederationPlugin');
  const CopyPlugin = require('copy-webpack-plugin');
  const HtmlWebpackPlugin = require('html-webpack-plugin');

  module.exports =
  {
    mode: 'development',
    entry: { main: './src/index.tsx' },
    module: {
      rules: [
        {
          test: /\.tsx?$/,
          use: 'ts-loader',
          exclude: /node_modules/,
        },
        {
          test: /\.css$/i,
          use: [
            'style-loader',
            { loader: 'css-loader', options: { modules: true } },
          ],
        },
      ],
    },
    resolve: {
      extensions: ['.tsx', '.ts', '.jsx', '.js', '.json'],
    },
    output: {
      publicPath: 'auto',
      uniqueName: 'react-ext',
      scriptType: 'text/javascript',
      filename: '[name].js',
      clean: true,
    },
    optimization: {
      // fix a temporary bug
      runtimeChunk: false,
    },
    plugins: [
      new HtmlWebpackPlugin({
        template: './src/index.html',
      }),
      new ModuleFederationPlugin({
        name: 'react-ext',
        library: {
          type: 'var',
          name: 'react-ext',
        },
        filename: '[name].js',
-       exposes: [],
+       exposes: [
+         {'IOpenspaceView<PageContext>': './src/extension/reactView.ts'}
+       ],
        shared: {
          '@pilotdev/pilot-web-sdk': {
            singleton: true,
          },
        },
      }),
      new CopyPlugin({
        patterns: [
          {
            from: './src/extension/extensions.config.json',
            to: 'extensions.config.json',
          },
        ],
      }),
    ],
    devServer: {
      port: 4300,
      allowedHosts: 'auto',
      headers: {
        'Access-Control-Allow-Origin': '*',
      },
    },
  };
  {
    "manifestVersion": 1,
    "author": "",
    "license": "",
    "title": "",
    "version": "",
    "extension": {
      "name": "react-ext",
      "entry": "react-ext.js",
-     "modules": [],
+     "modules": [
+       { "ngModuleName":"ReactView", "exposedInterface":"IOpenspaceView<PageContext>" }
+     ]
    }
  }

Встраивание React в UI

Для встраивания React в приложение, реализуйте интерфейс IOpenspaceView с необходимым контекстом, например:

import { IOpenspaceView, PageContext } from "@pilotdev/pilot-web-sdk";

export class ReactView implements IOpenspaceView<PageContext> {
  getViewId(): string {
  }

  getView(): HTMLElement | undefined {
  }
}

Реализуйте метод getViewId() для идентификации отображения:

getViewId(): string {
  return "ReactViewId";
}

Реализуйте метод getView():

import { IOpenspaceView, PageContext } from "@pilotdev/pilot-web-sdk";
import { StrictMode, createElement } from 'react';
import { createRoot, Root } from 'react-dom/client';

import { ReactViewComponent } from '../../components/ReactView';

export class ReactView implements IOpenspaceView<PageContext> {
  private _rootElement: HTMLElement | undefined;
  private _reactRoot: Root | undefined;

  ...

  getView(): HTMLElement | undefined {
    if (!this._rootElement) {
      this._rootElement = document.createElement("div");
    }

    if (!this._reactRoot) {
      this._reactRoot = createRoot(this._rootElement);
    }

    const element = createElement(ReactViewComponent);

    const strictModeElement = createElement(StrictMode, { children: element });

    if (this._reactRoot) {
      this._reactRoot.render(strictModeElement);
    }

    return this._rootElement;
  }
}

Для освобождения ресурсов, необходимо реализовать интерфейс поведения IDisposable и его метод IDisposable.dispose():

import { IOpenspaceView, PageContext } from "@pilotdev/pilot-web-sdk";
import { StrictMode, createElement } from 'react';
import { createRoot, Root } from 'react-dom/client';

import { ReactViewComponent } from '../../components/ReactView';

export class ReactView implements IOpenspaceView<PageContext> {
  private _rootElement: HTMLElement | undefined;
  private _reactRoot: Root | undefined;

  ...

  dispose(): void {
    if (this._reactRoot) {
      this._reactRoot.unmount();
      this._reactRoot = undefined;
    }

    if (this._rootElement) {
      this._rootElement = undefined;
    }
  }
}

Запуск React-расширения

Debug

Для того чтобы собрать расширение в отладочном режиме, запустите скрипт dev:

npm run dev

Затем запустите контейнер с Pilot-Web-Server с ключом -e AppSettings:Mode=Development

docker run -d -p 80:80 -e PilotServer:Url=http://0.1.5.100:5545 -e PilotServer:Database=demo -e AppSettings:Mode=Development --name pilot-web-server pilotdev/pilot-web-server:latest

Production

Для того чтобы собрать и запустить production-расширение, запустите скрипт build-prod:

npm run build-prod

Затем в папке dist создайте zip архив с папкой frontend (сама папка должна попасть в архив). В клиентском приложении Pilot создайте объект с типом Веб-расширение (WebExtension) и прикрепите архив. Подробнее на help.pilotems.com

Vue-расширение

Настройка Vue-расширения

Чтобы создать Vue-расширение, выполните следующие действия:

npm install -g @vue/cli
vue create vue-ext
npm install @pilotdev/pilot-web-sdk

если произошла ошибка несовпадения версий зависимостей, то выполните команду:

npm config set legacy-peer-deps true
  {
    "scripts": {
      ...,
+     "serve": "vue-cli-service serve",
+     "build-prod": "vue-cli-service build",
      ...
    },
    "dependencies": {
      ...
    },
    ...
  }
{
  "manifestVersion": 1,
  "author": "",
  "license": "",
  "title": "",
  "version": "",
  "extension": {
    "name": "vue-ext",
    "entry": "vue-ext.js",
    "modules": []
  }
}

и заполните поля author, license, title, version, name, a так же поле entry по шаблону [name].js, где [name] - значение поля name. Например: vue-ext.js.

Интерактивные подсказки и валидация в IDE

В начале файла добавьте поле $schema со значением пути, указывающим на схему extensions.config.schema.json из пакета @pilotdev/pilot-web-sdk

{
  "$schema": "../../../node_modules/@pilotdev/pilot-web-sdk/extensions.config.schema.json",
  ...
}
const { defineConfig } = require("@vue/cli-service");

const ModuleFederationPlugin = require("webpack/lib/container/ModuleFederationPlugin");
const CopyPlugin = require("copy-webpack-plugin");

const isProduction = process.env.NODE_ENV === "production";

module.exports = defineConfig({
  transpileDependencies: true,
  publicPath: "auto",
  outputDir: isProduction ? "./dist/frontend" : undefined,
  configureWebpack: () => {
    return {
      entry: "./src/main.ts",
      output: {
        uniqueName: "vue-ext",
        scriptType: "text/javascript",
        filename: "[name].js",
        clean: true,
      },
      optimization: {
        // fix a temporary bug
        runtimeChunk: false,
        splitChunks: isProduction ? undefined : false,
      },
      plugins: [
        new ModuleFederationPlugin({
          name: "vue-ext",
          library: {
            type: "var",
            name: "vue-ext",
          },
          filename: "[name].js",
          exposes: [
          ],
          shared: {
            "@pilotdev/pilot-web-sdk": {
              singleton: true,
            },
          },
        }),
        new CopyPlugin({
          patterns: [
            {
              from: "./src/extension/extensions.config.json",
              to: `extensions.config.json`,
            },
          ],
        }),
      ],
      devServer: isProduction
        ? undefined
        : {
            port: 4300,
            allowedHosts: "auto",
            headers: { "Access-Control-Allow-Origin": "*" },
          },
    };
  },
});

и заполните поля uniqueName, name и library.name. Добавьте в секцию shared используемые библиотеки, чтобы их переиспользовать в хост-приложении. Подробнее: https://webpack.js.org/plugins/module-federation-plugin

import { IOpenspaceView, PageContext } from "@pilotdev/pilot-web-sdk";

export class VueView implements IOpenspaceView<PageContext> {
  getViewId(): string {
  }

  getView(): HTMLElement | undefined {
  }
}
  const { defineConfig } = require("@vue/cli-service");

  const ModuleFederationPlugin = require("webpack/lib/container/ModuleFederationPlugin");
  const CopyPlugin = require("copy-webpack-plugin");

  const isProduction = process.env.NODE_ENV === "production";

  module.exports = defineConfig({
    transpileDependencies: true,
    publicPath: "auto",
    outputDir: isProduction ? "./dist/frontend" : undefined,
    configureWebpack: () => {
      return {
        entry: "./src/main.ts",
        output: {
          uniqueName: "vue-ext",
          scriptType: "text/javascript",
          filename: "[name].js",
          clean: true,
        },
        optimization: {
          // fix a temporary bug
          runtimeChunk: false,
          splitChunks: isProduction ? undefined : false,
        },
        plugins: [
          new ModuleFederationPlugin({
            name: "vue-ext",
            library: {
              type: "var",
              name: "vue-ext",
            },
            filename: "[name].js",
-           exposes: [],
+           exposes: [
+             {'IOpenspaceView<PageContext>': './src/extension/vueView.ts'}
+           ],
            shared: {
              "@pilotdev/pilot-web-sdk": {
                singleton: true,
              },
            },
          }),
          new CopyPlugin({
            patterns: [
              {
                from: "./src/extension/extensions.config.json",
                to: `extensions.config.json`,
              },
            ],
          }),
        ],
        devServer: isProduction
          ? undefined
          : {
              port: 4300,
              allowedHosts: "auto",
              headers: { "Access-Control-Allow-Origin": "*" },
            },
      };
    },
  });
  {
    "manifestVersion": 1,
    "author": "",
    "license": "",
    "title": "",
    "version": "",
    "extension": {
      "name": "vue-ext",
      "entry": "vue-ext.js",
-     "modules": [],
+     "modules": [
+       { "ngModuleName":"VueView", "exposedInterface":"IOpenspaceView<PageContext>" }
+     ]
    }
  }

Встраивание Vue в UI

Для встраивания Vue в приложение, реализуйте интерфейс IOpenspaceView с необходимым контекстом, например:

import { IOpenspaceView, PageContext } from "@pilotdev/pilot-web-sdk";

export class VueView implements IOpenspaceView<PageContext> {
  getViewId(): string {
  }

  getView(): HTMLElement | undefined {
  }
}

Реализуйте метод getViewId() для идентификации отображения:

getViewId(): string {
  return "VueViewId";
}

Реализуйте метод getView():

import { IOpenspaceView, PageContext } from "@pilotdev/pilot-web-sdk";
import { createApp, type App as AppType } from "vue";
import App from "../../App.vue";

export class VueView implements IOpenspaceView<PageContext> {
  private _rootElement: HTMLElement | undefined;
  private _vueApp: AppType<Element> | undefined;

  ...

  getView(): HTMLElement | undefined {
    if (!this._rootElement) {
      this._rootElement = document.createElement("div");
      this._rootElement.setAttribute("id", "app");
    }

    if (!this._vueApp) {
      this._vueApp = createApp(App);
    }

    this._vueApp.mount(this._rootElement);

    return this._rootElement;
  }
}

Для освобождения ресурсов, необходимо реализовать интерфейс поведения IDisposable и его метод IDisposable.dispose():

import { IDisposable, IOpenspaceView, PageContext } from "@pilotdev/pilot-web-sdk";
import { createApp, type App as AppType } from "vue";

export class VueView implements IOpenspaceView<PageContext>, IDisposable {
  private _rootElement: HTMLElement | undefined;
  private _vueApp: AppType<Element> | undefined;

  ...

  dispose(): void {
    if (this._vueApp) {
      this._vueApp.unmount();
      this._vueApp = undefined;
    }

    if (this._rootElement) {
      this._rootElement = undefined;
    }
  }
}

Запуск Vue-расширения

Debug

Для того чтобы собрать расширение в отладочном режиме, запустите скрипт serve:

npm run serve

Затем запустите контейнер с Pilot-Web-Server с ключом -e AppSettings:Mode=Development

docker run -d -p 80:80 -e PilotServer:Url=http://0.1.5.100:5545 -e PilotServer:Database=demo -e AppSettings:Mode=Development --name pilot-web-server pilotdev/pilot-web-server:latest

Production

Для того чтобы собрать и запустить production-расширение, запустите скрипт build-prod:

npm run build-prod

Затем в папке dist создайте zip архив с папкой frontend (сама папка должна попасть в архив). В клиентском приложении Pilot создайте объект с типом Веб-расширение (WebExtension) и прикрепите архив. Подробнее на help.pilotems.com

Добавление в проект расширения к компонентам PilotWeb2D и PilotWeb3D

Чтобы добавить расширение к компонентам Pilot-ComponentKit, выполните следующие действия:

/// <reference types="@pilotdev/pilot-web-2d" />
export class Web2DExtension extends PilotWeb2D.Extension {
  static readonly EXTENSION_NAME = "ProductName.Web2DExtension";

  constructor(_viewer: PilotWeb2D.GuiViewer2D) {
    super(_viewer);
  }
  
  override getName() {
    return Web2DExtension.EXTENSION_NAME;
  }

  override load() : boolean | Promise<boolean> {
    super.activate();
    return super.load();
  }

  override unload(): boolean {
    super.deactivate();
	return super.unload();
  }
}
PilotWeb2D.theExtensionManager.registerExtensionType(Web2DExtension.EXTENSION_NAME, Web2DExtension);
  const ModuleFederationPlugin = require('webpack/lib/container/ModuleFederationPlugin');
  const CopyPlugin = require("copy-webpack-plugin");
  module.exports = [{ 
    mode: "development",
-   entry: './src/index.ts',
+   entry: {
+     main: './src/index.ts',
+	    web2d: './src/app/web2d.component.extension.ts',
+   },
    module: {
      rules: [{
          test: /\.tsx?$/,
          use: 'ts-loader',
          exclude: /node_modules/ 
      }]
    },
    resolve: {
      extensions: [".tsx", ".ts", ".jsx", ".js", ".json"],
    },
    output: {
      publicPath: 'auto',
      uniqueName: 'ext_name',
      scriptType: 'text/javascript',
      filename: '[name].js',
      clean: true
    },
    optimization: {
      // fix a temporary bug
      runtimeChunk: false
    },
    plugins: [
      new ModuleFederationPlugin({
        name: 'ext_name',
        library: { type: 'var', name: '[name]' },
        filename: '[name].js',
        exposes: [{'IMenu<ObjectsViewContext>': './src/app/extensionSample.ts'}],  //implemented interfaces
        shared: {
          '@pilotdev/pilot-web-sdk': {
            singleton: true,
          }
        }
      }),

      new CopyPlugin({
        patterns: [
          { from: "./src/assets/extensions.config.json", to: "extensions.config.json" }
        ],
      }),
    ]
  }]
 {
   "manifestVersion": 1,
   "author": "",
   "license": "",
   "title": "",
   "version": "",
   "extension": {
     "name": "ext_name",
     "description": "",
     "entry": "ext_name.js",
     "modules": [
       { "ngModuleName":"ExtensionSample", "exposedInterface":"IMenu<ObjectsViewContext>" } ]
   },
+   "pilotWeb2D": [
+     {
+       "name": "Web2DExtension",
+       "description": "",
+       "entry": "web2d.js"  
+     }
+   ],
+   "pilotWeb3D": [
+     {
+       "name": "Web3DExtension",
+       "description": "",
+       "entry": "web3d.js"  
+     }
+   ]
 }

и заполните поля name, description, a так же поле entry по шаблону [key].js, где [key] - ключ из предыдущего шага. Например, web2d.js. Значение поля name должно совпадать с именем расширения, указанного в файле с логикой расширения (EXTENSION_NAME):

PilotWeb2D.theExtensionManager.registerExtensionType(EXTENSION_NAME, Web2DExtension);

Пример настройки клиентского расширения и расширения к компоненту и их взаимодействия – annotation.page.changer

Инжектирование зависимостей

Список инжектируемых интерфейсов

Инжектирование зависимостей в typescript-расширение

Для инжектирования зависимостей имплементируйте интерфейс IInitializable: в метод initialize будет передан класс InjectionSource, позволяющий получить экземпляры IObjectsRepository, IRenderContextProvider, IModifierProvider, IRepositoryEvents.

import { IDataPlugin, IModifierProvider, IObjectsRepository, IRenderContextProvider, IRepositoryEvents, IInitializable, InjectionSource } from "@pilotdev/pilot-web-sdk";

export class InitializeSample extends IDataPlugin implements IInitializable {

  private _objectsRepository!: IObjectsRepository;
  private _renderContextProvider!: IRenderContextProvider;
  private _modifierProvider!: IModifierProvider;
  private _repositoryEvents!: IRepositoryEvents;

  initialize(injectionSource: InjectionSource) {
    this._objectsRepository = injectionSource.objectsRepository;
    this._renderContextProvider = injectionSource.renderContextProvider;
    this._modifierProvider = injectionSource.modifierProvider;
    this._repositoryEvents = injectionSource.repositoryEvents;
  }
}

Инжектирование зависимостей в angular-расширение

Для инжектирования зависимостей в angular-расширение укажите интерфейсы с использованием декоратора Inject в конструкторе класса, в котором содержится логика расширения, а также пометьте класс декоратором Injectable, например:

import { Inject, Injectable } from "@angular/core";
import { IMenu, IMenuBuilder, IModifierProvider, IObjectsRepository, IRenderContextProvider, IRepositoryEvents, ObjectsViewContext } from "@pilotdev/pilot-web-sdk"

@Injectable({providedIn: "root"})
export class ObjectsContextMenuExtension implements IMenu<ObjectsViewContext> {
  
  constructor(@Inject(`IObjectsRepository`)private _repository: IObjectsRepository,
              @Inject(`IRenderContextProvider`)private _renderContextProvider: IRenderContextProvider,
              @Inject(`IModifierProvider`)private _modifierProvider: IModifierProvider,
              @Inject(`IRepositoryEvents`)private _repositoryEvents: IRepositoryEvents) {
  }

  build(builder: IMenuBuilder, context: ObjectsViewContext): void {
    builder.addItem("SomeMenuItemName", 1)
      .withHeader("Hello from angular extension");
  }

  onMenuItemClick(name: string, context: ObjectsViewContext): void {
    alert(`Angular extension works!`);
  }
}

Описание интерфейсов и методов Pilot-Web-Server

1. Интерфейсы поведения

Интерфейс IInitializable

Интерфейс используется для инжектирования зависимостей в расширение.

import { IMenu, IMenuBuilder, ObjectsViewContext, IModifierProvider, IObjectsRepository, ObjectsViewContext, IInitializable, InjectionSource } from "@pilotdev/pilot-web-sdk";

export class InitializeSample extends IMenu<ObjectsViewContext> implements IInitializable {

  private _objectsRepository!: IObjectsRepository;
  private _modifierProvider!: IModifierProvider;

  initialize(injectionSource: InjectionSource) {
    this._objectsRepository = injectionSource.objectsRepository;
    this._modifierProvider = injectionSource.modifierProvider;
  }

  build(builder: IMenuBuilder, context: ObjectsViewContext): void {
    ...
  }

  onMenuItemClick(name: string, context: ObjectsViewContext): void {
    ...
  }
}

IInitializable.initialize

Метод вызывается для инжектирования зависимостей

initialize(injectionSource: InjectionSource): void

где:

InjectionSource

Класс, содержащий экземпляры инжектируемых интерфейсов. Подробнее: Инжектирование зависимостей в typescript-расширение.

Интерфейс IDisposable

Интерфейс используется для реализации поведения расширения при его выгрузке.

import { IMenu, IMenuBuilder, ObjectsViewContext, IDisposable } from "@pilotdev/pilot-web-sdk";

export class DisposeSample extends IMenu<ObjectsViewContext> implements IDisposable {
  dispose() {
    console.log("DisposeSample disposed!");
  }

  build(builder: IMenuBuilder, context: ObjectsViewContext): void {
    ...
  }

  onMenuItemClick(name: string, context: ObjectsViewContext): void {
    ...
  }
}

IDisposable.dispose

Метод будет вызван при выгрузке объекта расширения из рабочей области: например при выполнении выхода из профиля или переключения элемента в IOpenspaceView.

dispose(): void

2. Интерфейсы для встраивания в UI

Интерфейс IToolbar

Интерфейс встраивает новые команды в панель инструментов.

import { IToolbar, IToolbarBuilder, ObjectsViewContext } from "@pilotdev/pilot-web-sdk";

export class ToolbarSample extends IToolbar<ObjectsViewContext> {

  build(builder: IToolbarBuilder, context: ObjectsViewContext): void {
	...
  }

  onMenuItemClick(name: string, context: ObjectsViewContext): void {
	...
  }
}

IToolbar.build

Метод вызывается перед построением панели инструментов.

 build(builder: IToolbarBuilder, context: TToolbarContext): void

где:

IToolbar.onToolbarItemClick

Метод вызывается при нажатии на элемент панели инструментов.

 onToolbarItemClick(name: string, context: TToolbarContext): void

где:

IToolbarBuilder

Управляет элементами панели инструментов.

IToolbarBuilder.itemNames

Свойство возвращает список уникальных имен элементов панели инструментов.

get itemNames(): string[]

IToolbarBuilder.count

Свойство возвращает количество элементов панели инструментов.

get count(): number
IToolbarBuilder.addSeparator

Метод добавляет разделитель в панель инструментов.

addSeparator(index: number): void

где:

IToolbarBuilder.addButtonItem

Метод добавляет кнопку в панель инструментов.

addButtonItem(name: string, index: number): IToolbarButtonItemBuilder

где:

IToolbarBuilder.addMenuButtonItem

Метод добавляет кнопку с выпадающим меню в панель инструментов.

addButtonItem(name: string, index: number): IToolbarButtonItemBuilder

где:

IToolbarBuilder.addToggleButtonItem

Метод добавляет кнопку-переключатель в панель инструментов.

addToggleButtonItem(name: string, index: number): IToolbarToggleButtonItemBuilder

где:

IToolbarBuilder.replaceButtonItem

Метод заменяет любой элемент панели инструментов на кнопку.

replaceButtonItem(name: string): IToolbarButtonItemBuilder

где:

IToolbarBuilder.replaceMenuButtonItem

Метод заменяет любой элемент панели инструментов на кнопку с выпадающим меню.

replaceMenuButtonItem(name: string): IToolbarMenuButtonItemBuilder

где:

IToolbarBuilder.replaceToggleButtonItem

Метод заменяет любой элемент панели инструментов на кнопку-переключатель.

replaceToggleButtonItem(name: string): IToolbarToggleButtonItemBuilder

где:

IToolbarBuilder.handleMenuButtonItemSubmenu

Метод добавляет обработчик построения подменю. Прямой доступ к элементам подменю невозможно получить в произвольный момент времени, так как подменю строится "лениво" при его открытии.

handleMenuButtonItemSubmenu(name: string, itemSubmenuHandler: IToolbarItemSubmenuHandler): void

где:

IToolbarBuilder.removeItem

Метод удаляет элемент панели инструментов.

removeItem(itemName: string): void

где:

IToolbarButtonItemBuilder

Интерфейс добавляет свойства к элементу панели инструментов.

IToolbarButtonItemBuilder.withHeader

Метод добавляет отображаемое в UI название.

withHeader(header: string): IToolbarButtonItemBuilder

где:

IToolbarButtonItemBuilder.withIcon

Метод добавляет иконку в формате SVG. Входные данные: строка в формате base64 или url.

withIcon(name: string, svg: string): IToolbarButtonItemBuilder

где:

  build(builder: IToolbarBuilder, context: ObjectsViewContext): void {
    builder.addItem("new_item", 1)
      .withHeader("ext command")
	  .withIcon( `ext_icon`, `http://localhost:4300/icon.svg`); //url format
  }
  
  build2(builder: IToolbarBuilder, context: ObjectsViewContext): void {
    builder.addItem("new_item2", 2)
      .withHeader("ext command 2")
	  .withIcon( `ext_icon`, `PD94bWwgdmVyc2lvbj0iMS4wIiB...`); //base64 format
  }
IToolbarButtonItemBuilder.withIsEnabled

Метод задаёт значение доступности элемента.

withIsEnabled(value: boolean): IToolbarButtonItemBuilder

где:

IToolbarButtonItemBuilder.withHint

Метод добавляет подсказку к элементу панели инструментов.

withHint(hint: string): IToolbarButtonItemBuilder

где:

IToolbarToggleButtonItemBuilder

Добавляет свойства к кнопке-переключателю панели инструментов. Этот интерфейс является наследником IToolbarButtonItemBuilder.

IToolbarToggleButtonItemBuilder.withIsChecked

Метод задаёт состояние кнопки-переключателя.

withIsChecked(value: boolean): IToolbarToggleButtonItemBuilder

где:

IToolbarMenuButtonItemBuilder

Добавляет свойства к кнопке с выпадающим меню панели инструментов. Этот интерфейс является наследником IToolbarButtonItemBuilder.

IToolbarMenuButtonItemBuilder.withMenu

Метод добавляет контекстное меню к кнопке.

 withMenu(itemSubmenuHandler: IToolbarItemSubmenuHandler): IToolbarMenuButtonItemBuilder

где:

IToolbarItemSubmenuHandler

Интерфейс построения меню для кнопки панели инструментов. Для того, чтобы построить меню, необходимо реализовать этот интерфейс и передать экземпляр в IToolbarBuilder.handleMenuButtonItemSubmenu.

IToolbarItemSubmenuHandler.onSubmenuRequested

Метод вызывается перед тем, как появится меню у кнопки панели инструментов.

onSubmenuRequested(builder: IToolbarBuilder): void

где:

Интерфейс IMenu

Интерфейс встраивает новые команды в различные меню приложения в зависимости от контекста.

import { IMenu, IMenuBuilder, ObjectsViewContext } from "@pilotdev/pilot-web-sdk";

export class MenuSample extends IMenu<ObjectsViewContext> {

  build(builder: IMenuBuilder, context: ObjectsViewContext): void {
	...
  }

  onMenuItemClick(name: string, context: ObjectsViewContext): void {
	...
  }
}

IMenu<TMenuContext>.build

Метод вызывается перед построением контекстного меню.

build(builder: IMenuBuilder, context: TMenuContext): void

где:

IMenu<TMenuContext>.onMenuItemClick

Метод вызывается при нажатии на элемент меню.

onMenuItemClick(name: string, context: TMenuContext): void

где:

Интерфейс IMenuBuilder

Интерфейс управляет элементами меню.

IMenuBuilder.itemNames

Свойство возвращает список уникальных имен меню.

get itemNames(): string[]

IMenuBuilder.count

Свойство возвращает количество элементов меню.

get count(): number
IMenuBuilder.addSeparator

Метод добавляет разделитель в меню.

addSeparator(index: number): void

где:

IMenuBuilder.addItem

Метод добавляет пункт меню.

addItem(name: string, index: number): IMenuItemBuilder

где:

IMenuBuilder.addCheckableItem

Метод добавляет пункт меню типа кнопка-переключатель.

addCheckableItem(name: string, index: number): ICheckableMenuItemBuilder

где:

IMenuBuilder.replaceItem

Метод заменяет любой пункт меню.

replaceItem(name: string): IMenuItemBuilder

где:

IMenuBuilder.removeItem

Метод удаляет пункт меню.

removeItem(name: string): void

где:

IMenuBuilder.getItem

Метод получает конструктор пункта меню.

getItem(name: string): IMenuBuilder

где:

IMenuItemBuilder

Интерфейс добавляет свойства пункту меню.

IMenuItemBuilder.withHeader

Метод добавляет отображаемое в UI название.

withHeader(header: string): IMenuItemBuilder

где:

IMenuItemBuilder.withIcon

Метод добавляет иконку в формате SVG. Входные данные: строка в формате base64 или url.

withIcon(name: string, svg: string): IMenuItemBuilder

где:

  build(builder: IMenuBuilder, context: ObjectsViewContext): void {
    builder.addItem("new_item", 1)
      .withHeader("ext command")
	  .withIcon( `ext_icon`, `http://localhost:4300/icon.svg`); //url format
  }
  
  build2(builder: IMenuBuilder, context: ObjectsViewContext): void {
    builder.addItem("new_item2", 2)
      .withHeader("ext command 2")
	  .withIcon( `ext_icon`, `PD94bWwgdmVyc2lvbj0iMS4wIiB...`); //base64 format
  }
IMenuItemBuilder.withIsEnabled

Метод задаёт значение доступности элемента.

withIsEnabled(value: boolean): IMenuItemBuilder

где:

IMenuItemBuilder.withSubmenu

Метод добавляет подменю к текущему пункту меню.

withSubmenu(): IMenuBuilder

где:

Интерфейс ITabs

Интерфейс позволяет встраивать/изменять элементы в различных группах вкладок приложения в зависимости от контекста.

import { ITabs, ITabsBuilder, ObjectsViewContext } from "@pilotdev/pilot-web-sdk";

export class TabsSample extends ITabs<ObjectsViewContext> {

  build(builder: ITabsBuilder, context: ObjectsViewContext): void {
	...
  }
}

ITabs<TTabsContext>.build

Метод вызывается перед построением группы вкладок.

build(builder: ITabsBuilder, context: TTabsContext): void

где:

Интерфейс ITabsBuilder

Интерфейс управляет элементами группы вкладок.

ITabsBuilder.itemNames

Свойство возвращает список уникальных имен вкладок.

get itemNames(): string[]

ITabsBuilder.count

Свойство возвращает количество элементов группы вкладок.

get count(): number
ITabsBuilder.addItem

Метод добавляет вкладку в группу.

addItem(id: string, index: number): ITabItemBuilder

где:

ITabsBuilder.replaceItem

Метод заменяет любую вкладку в группе.

replaceItem(id: string): ITabItemBuilder

где:

ITabItemBuilder

Интерфейс добавляет свойства вкладке.

ITabItemBuilder.withTitle

Метод добавляет отображаемое в UI название.

withTitle(title: string): ITabItemBuilder

где:

ITabItemBuilder.withIcon

Метод добавляет иконку в формате SVG. Входные данные: строка в формате base64 или url.

withIcon(name: string, iconSvg: string): ITabItemBuilder

где:

  build(builder: ITabItemBuilder, context: ObjectsViewContext): void {
    builder.addItem("new_item", 1)
      .withTitle("ext command")
	  .withIcon( `ext_icon`, `http://localhost:4300/icon.svg`); //url format
  }
  
  build2(builder: ITabItemBuilder, context: ObjectsViewContext): void {
    builder.addItem("new_item2", 2)
      .withTitle("ext command 2")
	  .withIcon( `ext_icon`, `PD94bWwgdmVyc2lvbj0iMS4wIiB...`); //base64 format
  }
ITabItemBuilder.withViewId

Метод создает Openspace контейнер в теле вкладки с указанным id.

Id сопоставляется с соответствующим отображением IOpenspaceView.getViewId

withViewId(value: string): ITabItemBuilder

где:

Интерфейс IPageNavigation

Интерфейс управляет секциями и элементами Окна навигации пространств.

import { IPageNavigation, IPageNavigationBuilder } from "@pilotdev/pilot-web-sdk";

export class PageNavigationSample extends IPageNavigation {

  build(builder: IPageNavigationBuilder): void {
	...
  }
}

IPageNavigation.build

Метод вызывается перед построением окна навигации.

build(builder: IPageNavigationBuilder): void

где:

IPageNavigationBuilder

Интерфейс управляет секциями окна навигации.

IPageNavigationBuilder.sectionIds

Свойство возвращает список уникальных id секций.

get sectionIds(): string[]
IPageNavigationBuilder.count

Свойство возвращает количество секций окна навигации.

get count(): number
IPageNavigationBuilder.addSection

Метод добавляет секцию в окно навигации.

addItem(id: string, index: number): IPageNavigationSectionBuilder

где:

IPageNavigationBuilder.replaceSection

Метод заменяет любую секцию в окне навигации.

replaceItem(id: string): IPageNavigationSectionBuilder

где:

IPageNavigationSectionBuilder

Интерфейс добавляет свойства секции и управляет её элементами.

IPageNavigationSectionBuilder.withTitle

Метод добавляет отображаемое в UI название секции.

withTitle(title: string): IPageNavigationSectionBuilder

где:

IPageNavigationSectionBuilder.elementIds

Свойство возвращает список уникальных id элементов секции.

get elementIds(): string[]
IPageNavigationSectionBuilder.count

Свойство возвращает количество элементов секции.

get count(): number
IPageNavigationSectionBuilder.addElement

Метод добавляет элемент в секцию окна навигации.

addItem(id: string, index: number): IPageNavigationSectionElementBuilder

где:

IPageNavigationSectionBuilder.replaceElement

Метод заменяет любой элемент в секции окна навигации.

replaceItem(id: string): IPageNavigationSectionElementBuilder

где:

IPageNavigationSectionElementBuilder

Интерфейс добавляет свойства элементу секции.

IPageNavigationSectionElementBuilder.withTitle

Метод добавляет отображаемое в UI название элемента.

withTitle(title: string): IPageNavigationSectionElementBuilder

где:

IPageNavigationSectionElementBuilder.withDescription

Метод добавляет отображаемое в UI описание элемента.

withDescription(description: string): IPageNavigationSectionElementBuilder

где:

IPageNavigationSectionElementBuilder.withIcon

Метод добавляет иконку в формате SVG. Входные данные: строка в формате base64 или url.

withIcon(name: string, iconSvg: string): IPageNavigationSectionElementBuilder

где:

IPageNavigationSectionElementBuilder.withViewId

Метод создает Openspace контейнер в теле страницы с указанным id.

Id сопоставляется с соответствующим отображением IOpenspaceView.getViewId

withViewId(value: string): IPageNavigationSectionElementBuilder

где:

Сервис IDialogService

Сервис, который позволяет открывать диалог с произвольным контентом.

IDialogService.openDialogWithExit

Метод создает диалог с Openspace контейнером в теле страницы с указанным id.

Id сопоставляется с соответствующим отображением IOpenspaceView.getViewId

openDialogWithExit(viewId: string, context: DialogContext, title: string): Observable<unknown>;

где:

Интерфейс IOpenspaceView

Интерфейс позволяет встраивать HTML элемент в различные части интерфейса приложения (Openspace слоты/контейнеры) в зависимости от контекста.
Для реализации логики освобождения ресурсов, используйте наследование от класса IDisposable: метод dispose() будет вызван перед уничтожением Openspace контейнера и перед выгрузкой расширения.

import { IOpenspaceView, ObjectsViewContext } from "@pilotdev/pilot-web-sdk";

export class OpenspaceViewSample implements IOpenspaceView<ObjectsViewContext>, IDisposable {
  getViewId(): string {
    ...
  }

  getView(context: ObjectsViewContext): void {
	  ...
  }

  dispose(): void {
    ...
  }
}

IOpenspaceView<TOpenspaceViewContext>.getViewId

Метод вызывается для сопоставления экземпляра интерфейса IOpenspaceView c Openspace контейнером.

getViewId(): string

IOpenspaceView<TOpenspaceViewContext>.getView

Метод вызывается для встраивания HTML элемента в Openspace контейнер

getView(context: TOpenspaceViewContext): HTMLElement | undefined

где:

Объекты UI-контекста

ObjectsViewContext

Используйте этот тип контекста для встраивания в Обозреватель элементов. Доступные для встраивания интерфейсы:

import { IMenu, IMenuBuilder, ObjectsViewContext } from "@pilotdev/pilot-web-sdk";

export class MenuSample extends IMenu<ObjectsViewContext> {

  build(builder: IMenuBuilder, context: ObjectsViewContext): void {
	...
  }

  onMenuItemClick(name: string, context: ObjectsViewContext): void {
	...
  }
}

DocumentAnnotationsListContext

Используйте этот тип контекста для встраивания в Замечания к документу. Доступные для встраивания интерфейсы:

import { IMenu, IMenuBuilder, DocumentAnnotationsListContext } from "@pilotdev/pilot-web-sdk";

export class MenuSample extends IMenu<DocumentAnnotationsListContext> {

  build(builder: IMenuBuilder, context: DocumentAnnotationsListContext): void {
	...
  }

  onMenuItemClick(name: string, context: DocumentAnnotationsListContext): void {
	...
  }
}

PageContext

Используйте этот тип контекста для встраивания в Страницу пространства. Доступные для встраивания интерфейсы:

import { IOpenspaceView, PageContext } from "@pilotdev/pilot-web-sdk";

export class OpenspaceViewSample implements IOpenspaceView<PageContext> {
  getViewId(): string {
    ...
  }

  getView(context: PageContext): void {
    ...
  }
}

DialogContext

Используйте этот тип контекста для встраивания в диалог, который может быть вызван в UI через IDialogService.
На данном примере описан вызов диалога по кнопке из контекстного меню:

export class ExampleObjectExtension implements IMenu<ObjectsViewContext>, IInitializable {
  private readonly EXAMPLE_VIEW_ITEM_NAME = "ExampleViewItemName";

  private _objectsRepository!: IObjectsRepository;
  private _dialogService!: IDialogService;

  initialize(injectionSource: InjectionSource): void {
    this._objectsRepository = injectionSource.objectsRepository;
    this._dialogService = injectionSource.dialogService;
  }

  build(builder: IMenuBuilder, context: ObjectsViewContext) {
    ...

    builder.addItem(this.EXAMPLE_VIEW_ITEM_NAME, 0).withHeader("Это диалог");
  }

  onMenuItemClick(name: string, context: ObjectsViewContext) {
    this._dialogService.openDialogWithExit(ExtensionViewId, new DialogContext(context), "Dialog title");
  }
}

BimElementPanelContext

Используйте этот тип контекста для встраивания в левую панель (панель элемента) пространства "Информационного моделирования (BIM)". Доступные для встраивания интерфейсы:

import { ITabs, ITabsBuilder, BimElementPanelContext } from "@pilotdev/pilot-web-sdk";

export class TabsSample extends ITabs<BimElementPanelContext> {

  build(builder: ITabsBuilder, context: BimElementPanelContext): void {
    ...
  }
}
import { IOpenspaceView, BimElementPanelContext } from "@pilotdev/pilot-web-sdk";

export class OpenspaceViewSample implements IOpenspaceView<BimElementPanelContext> {
  getViewId(): string {
    ...
  }

  getView(context: BimElementPanelContext): void {
    ...
  }
}

BimRightPanelContext

Используйте этот тип контекста для встраивания в правую панель пространства "Информационного моделирования (BIM)". Доступные для встраивания интерфейсы:

import { ITabs, ITabsBuilder, BimRightPanelContext } from "@pilotdev/pilot-web-sdk";

export class TabsSample extends ITabs<BimRightPanelContext> {

  build(builder: ITabsBuilder, context: BimRightPanelContext): void {
    ...
  }
}
import { IOpenspaceView, BimRightPanelContext } from "@pilotdev/pilot-web-sdk";

export class OpenspaceViewSample implements IOpenspaceView<BimRightPanelContext> {
  getViewId(): string {
    ...
  }

  getView(context: BimRightPanelContext): void {
	  ...
  }
}

Интерфейсы для работы с сертификатами и криптографией

Интерфейс ICertificate

Представляет сертификат с датами действия, информацией об издателе и субъекте.

Свойства
ICertificate.validToDate

Свойство возвращает дату окончания действия сертификата.

get validToDate(): string
ICertificate.validFromDate

Свойство возвращает дату начала действия сертификата.

get validFromDate(): string
ICertificate.issuer

Свойство возвращает издателя сертификата.

get issuer(): string
ICertificate.subject

Свойство возвращает субъект сертификата.

get subject(): string

Интерфейс ICryptoProvider

Представляет криптографический провайдер для подписания, проверки и получения сертификатов.

Методы
ICryptoProvider.sign

Метод подписывает файл цифровой подписью с использованием предоставленного сертификата.

sign(documentId: string, actualFile: IFile, arrayBuffer: ArrayBuffer, certificate: ICertificate, signatureRequestIds: string[]): Observable<string>

где:

ICryptoProvider.verify

Метод проверяет цифровую подпись файла.

verify(file: ArrayBuffer, sign: ArrayBuffer, signatureRequest: ISignatureRequest): Observable<ISignatureVerificationResult>

где:

ICryptoProvider.verifyImportedSignature

Метод проверяет импортируемую цифровую подпись.

verifyImportedSignature(file: ArrayBuffer, sign: ArrayBuffer): Observable<IImportedSignatureVerificationResult>

где:

ICryptoProvider.getCertificates

Метод получает список цифровых сертификатов.

getCertificates(): Observable<ICertificate[]>

где:

ICryptoProvider.canProcessAlgorithms

Метод определяет, может ли провайдер обрабатывать указанный алгоритм.

  canProcessAlgorithms(publicKeyOid: string): boolean;

где:

ICryptoProvider.canProcessSignature

Метод определяет, может ли провайдер проверить подпись. Метод необходим во время импорта подписи, когда алгоритм подписания неизвестен.

  canProcessSignature(signatureFile: ArrayBuffer): boolean

где:

CadesType

Перечисление типа подписи.

export enum CadesType {
  CadesBes = 0,
  CadesT = 1,
  CadesC = 2,
  CadesXLong = 3,
  CadesXLongType1 = 4
}

Интерфейс ISettingsFeature

Интерфейс позволяет регистрировать представление в диалоге настроек.

ISettingsFeature

Интерфейс для работы с элементами диалога настроек.

key

Метод для получения уникального идентификатора элемента настроек.

get key(): string;
title

Метод для получения заголовка элемента настроек.

get title(): string;
editor

Метод для получения редактора значений элемента настроек.

get editor(): HTMLElement;
setValueProvider

Метод для установки поставщика значения настройки.

setValueProvider(settingValueProvider: ISettingValueProvider): void;

где:

Интерфейс ISettingValueProvider

Интерфейс для поставщика значения личной настройки.

ISettingValueProvider

Интерфейс для работы со значениями личных настроек.

getValue

Метод для получения текущего значения настройки.

getValue(): string;

где:

setValue

Метод для установки значения настройки.

setValue(value: string): void;

где:

3. Интерфейсы для перехвата событий клиентского приложения

Интерфейс IObjectCardHandler

Интерфейс позволяет реализовать работу с атрибутами, отображаемыми в карточке объекта.

import { AttributeValueChangedEventArgs, IAttribute, IAttributeModifier, IObjectCardHandler, ObjectCardContext } from "@pilotdev/pilot-web-sdk";

export class ObjectCardHandlerSample implements IObjectCardHandler {

  handle(modifier: IAttributeModifier, context: ObjectCardContext): void {
	...
  }

  onValueChanged(sender: IAttribute, args: AttributeValueChangedEventArgs, modifier: IAttributeModifier): void {
	...
  }
}

IObjectCardHandler.handle

Метод handle вызывается при каждом построении карточки объекта: при показе диалогов создания и редактирования объекта, при выборе объектов, для которых отображается карточка, в Обозревателе документов. В случае, если карточка находится в режиме редактирования существующего объекта, свойство editingObject аргумента context возвращает сам объект, атрибуты которого показаны в карточке; и null, если карточка показана для создания нового объекта.

handle(modifier: IAttributeModifier, context: ObjectCardContext): void

где:

IObjectCardHandler.onValueChanged

Метод onValueChanged вызывается при изменении пользователем значения какого-либо из отображаемых атрибутов в карточке объекта. Аргумент sender возвращает атрибут, значение которого было изменено. Аргумент args позволяет получить доступ к аргументам события: предыдущему и новому значению атрибута, а также контексту карточки объекта. modifier позволяет отреагировать на изменения и установить новое значение дополнительно одному или нескольким атрибутам. Изменения в значениях атрибутов, которые были сделаны с помощью modifier, не приводят к вызовам метода onValueChanged.

onValueChanged(sender: IAttribute, args: AttributeValueChangedEventArgs, modifier: IAttributeModifier): void

где:

Редактирование атрибутов в карточке IAttributeModifier

Интерфейс позволяет установить новое значения для атрибутов элемента перед тем, как они будут показаны в карточке объекта.

IAttributeModifier.setValue

Метод позволяет задать новое значение атрибуту.

setValue(name: string, value: unknown): void

где:

Контекст карточки ObjectCardContext

Контекст отображения карточки.

ObjectCardContext.currentObjectId

Поле содержит идетификатор объекта, для которого показана карточка. Если карточка показана для создания нового объекта, то поле содержит идентификатор, который будет присвоен новому объекту при создании.

get currentObjectId(): string
ObjectCardContext.displayAttributes

Поле содержит список отображаемых в карточке атрибутов. В этот список не входят сервисные атрибуты.

get displayAttributes(): IAttribute[]
ObjectCardContext.attributeValues

Словарь текущих значений атрибутов карточки объекта, где ключ это имя атрибута, а значение - это значение атрибута.

get attributesValues(): Map<string, unknown>
ObjectCardContext.type

Поле содержит описание типа элемента, для которого показана карточка.

get type(): IType
ObjectCardContext.editiedObject

Текущий редактируемый объект, для которого показана карточка. null, если карточка показана для создания нового объекта.

get editedObject(): IDataObject | null
ObjectCardContext.parent

Поле содержит ID родительского элемента.

get parentId(): string;
ObjectCardContext.isReadOnly

True, если карточка в режиме только для чтения, и атрибуты недоступны для изменения.

get isReadOnly(): boolean;

Перехват цветовой схемы клиента

IThemeService

Интерфейс позваляет получить значение выбранной цветовой схемы клиента (светлая или тёмная).

IThemeService.themes

Позволяет получить текущую цветовую схему клиента.

get themes(): Themes;
IThemeService.change

Позволяет подписаться на событие изменение цветовой схемы клиента.

get change(): Observable<Themes>;

4. Интерфейсы управления данными

Интерфейс IObjectsRepository

Интерфейс даёт доступ к элементам, типам элементов и организационной структуре. Получить интерфейс можно с помощью инжектирования. Для подписки на изменения данных смотри IRepositoryEvents.

IObjectsRepository.getObjects

Метод получает элементы по их идентификаторам.

getObjects(ids: string[]): Observable<IDataObject[]>

где:

IObjectsRepository.getCurrentAccess

Метод получает информацию о доступе пользователя к определенному объекту.

getCurrentAccess(objectId: string, personId: number): Observable<AccessLevel>

где:

IObjectsRepository.getPerson

Метод позволяет получить информацию о пользователе по идентификатору.

getPerson(id: number): IPerson

где:

IObjectsRepository.getCurrentPerson

Метод возвращает текущего пользователя.

getCurrentPerson(): IPerson

где:

IObjectsRepository.getPeople

Метод получает список всех пользователей.

 getPeople(): IPerson[]

где:

IObjectsRepository.getType

Метод получает информацию о типе элемента по идентификатору.

getType(id: number): IType

где:

IObjectsRepository.getTypeByName

Метод получает информацию о типе элемента по имени.

getTypeByName(name: string): IType

где:

IObjectsRepository.getTypes

Метод получает список всех типов.

getTypes(): IType[]

где:

IObjectsRepository.getOrganisationUnit

Метод получает информацию об организационной единице.

getOrganisationUnit(id: number): IOrganizationUnit

где:

IObjectsRepository.getOrganisationUnits

Метод получает список организационных единиц.

  getOrganisationUnits(): IOrganizationUnit[]

где:

Интерфейс IRepositoryEvents

Интерфейс подписывается на изменения в элементах, типах элементов и организационной структуре. Получить интерфейс можно с помощью инжектирования.. Подписка – Hot Observable и срабатывает только на изменение данных.

IRepositoryEvents.subscribeObjects

Метод подписывается на изменения элементов по идентификаторам.

subscribeObjects(ids: string[]): Observable<IDataObject>

где:

IRepositoryEvents.subscribePeople

Метод подписывается на изменения в пользователях.

subscribePeople(): Observable<IPerson>

где:

IRepositoryEvents.subscribeTypes

Метод подписывается на изменения в типах.

subscribeTypes(): Observable<IType>

где:

IRepositoryEvents.subscribeOrganisationUnits

Метод подписывается на изменения в организационных единицах (должностях и подразделениях).

subscribeOrganisationUnits(): Observable<IOrganizationUnit>

где:

Интерфейс IModifierProvider

Интерфейс отдаёт объект IModifier. Получить интерфейс можно с помощью инжектирования.

IModifierProvider.newModifier

Метод получает новый экземпляр класса, реализующий интерфейс IModifier.

newModifier(): IModifier

где:

Интерфейс IModifier

Интерфейс предназначен для создания и изменения элементов. Получить интерфейс можно через IModifierProvider.

IModifier.create

Метод создаёт новый элемент заданного типа.

create(id: string, parentId: string, typeId: number): IObjectBuilder

где:

IModifier.edit

Метод редактирует заданный элемент.

edit(id: string) : IObjectBuilder

где:

IModifier.apply

Метод применяет все сделанные над элементами изменения. Без вызова этого метода изменения не будут применены.

apply(): Observable<IDataObject[]>;

где:

Интерфейс IObjectBuilder

Интерфейс редактирует элементы.

IObjectBuilder.setAttribute

Метод задает или изменяет атрибут с заданным именем.

setAttribute(name: string, value: any, type: AttributeType): IObjectBuilder

где:

IObjectBuilder.setAccess

Метод добавляет права доступа на элемент.

setAccess(record: IAccessRecord): IObjectBuilder

где:

IObjectBuilder.removeAccess

Метод удаляет права доступа на элемент.

removeAccess(record: IAccessRecord): IObjectBuilder

где:

IObjectBuilder.addRelation

Метод добавляет новую связь к элементу.

addRelation(relation: IRelation): IObjectBuilder

где:

IObjectBuilder.removeRelation

Метод удаляет связь.

removeRelation(relationId: string): IObjectBuilder

где:

IObjectBuilder.setTypeId

Метод задаёт элементу тип.

ВНИМАНИЕ!
Рекомендуется использовать этот метод только для восстановления безвозвратно удаленных объектов. В остальных случаях это может привести к неработоспособности системы.

setTypeId(typeId: number): IObjectBuilder

где:

IObjectBuilder.setParentId

Метод задаёт элементу нового родителя.

setParentId(parentId: string): IObjectBuilder

где:

IObjectBuilder.createSnapshot

Метод создаёт снимок файлов и указывает причину. Текущие файлы будут сохранены в предыдущей версии документа.

createSnapshot(reason: string): IObjectBuilder

где:

IObjectBuilder.createSnapshotFrom

Метод делает выбранный снимок файлов текущим.

createSnapshotFrom(version: string, reason: string): IObjectBuilder

где:

IObjectBuilder.addFile

Метод добавляет новый файл в текущий снимок файлов.

addFile(fileId: string, file: File, creationTime: Date, lastAccessTime: Date, lastWriteTime: Date): IObjectBuilder;

где:

IObjectBuilder.removeFile

Метод удаляет файл из текущего снимка файлов.

removeFile(fileId: string): IObjectBuilder;

где:

IObjectBuilder.setIsDeleted

Метод задаёт элементу состояние удалено безвозвратно.

setIsDeleted(isDeleted: boolean): IObjectBuilder

где:

IObjectBuilder.setIsInRecycleBin

Метод задаёт элементу состояние удалено в корзину.

setIsInRecycleBin(isInRecycleBin: boolean): IObjectBuilder

где:

IObjectBuilder.setIsFreezed

Метод задаёт элементу состояние заморозки.

setIsFreezed(isFreezed: boolean): IObjectBuilder

где:

IObjectBuilder.setIsSecret

Метод делает элемент скрытым или общедоступным.

setIsSecret(isSecret: boolean): IObjectBuilder

где:

IObjectBuilder.addAnnotationContainer

Метод создаёт или изменяет замечание.

addAnnotationContainer(container: IAnnotationContainer, attrbutes: any): IObjectBuilder

где:

IObjectBuilder.setSignatures

Метод создаёт модификатор запросов на подпись для указанного файла.

setSignatures(fileId: string): ISignatureModifier;

где:

Интерфейс ISignatureModifier

Интерфейс для создания и изменения запросов на подпись.

ISignatureModifier.create

Метод создает новый запрос на подпись для указанного файла.

add(signatureRequestId: string): ISignatureBuilder;

где:

ISignatureModifier.edit

Метод редактирует запрос на подпись для указанного файла.

edit(signatureRequest: ISignatureRequest): ISignatureBuilder;

где:

ISignatureModifier.remove

Метод удаляет запрос на подпись.

remove(signatureRequestId: string): void;

где:

Интерфейс ISignatureBuilder

Интерфейс для изменения запроса на подпись.

ISignatureBuilder.withPositionId

Метод задает идентификатор должности пользователя, который должен будет подписать этот запрос на подпись.

withPositionId(positionId: number): ISignatureBuilder;

где:

ISignatureBuilder.withRole

Метод задает роль пользователя, под который пользователь должен будет подписать этот запрос на подпись.

withRole(role: string): ISignatureBuilder;

где:

ISignatureBuilder.withSign

Метод задает флаг, подписан ли запрос на подпись или нет.

withSign(sign: string): ISignatureBuilder

где:

ISignatureBuilder.withRequestSigner

Метод задает имя пользователя запроса на подпись.

withRequestSigner(requestSigner: string): ISignatureBuilder;

где:

ISignatureBuilder.withObjectId

Метод задает идентификатор связанного объекта с запросом на подпись. Например идентифкатор задания на согласование.

withObjectId(objectId: string): ISignatureBuilder;

где:

Интерфейс IPersonalSettings

Интерфейс предназначен для работы с персональными и общими настройками пользователя.
Позволяет получать текущие значения настроек, подписываться на их изменения и изменять значения.

IPersonalSettings.getPersonalSettingValue

Получение значения персональной настройки для текущего пользователя по ключу.

getPersonalSettingValue(key: string): Observable<string | undefined>;

где:

IPersonalSettings.subscribePersonalSettingValueChange

Подписка на значение персональной настройки по передаваемому ключу.

subscribePersonalSettingValueChange(key: string): Observable<string | undefined>;

где:

IPersonalSettings.getCommonSettingValue

Получение по ключу списка значений настройки для всех элементов организационной структуры, в которые входит текущий пользователь.

getCommonSettingValue(key: string): Observable<string[]>;

где:

IPersonalSettings.subscribeCommonSettingValueChange

Подписка на изменения значения общей настройки по ключу.

subscribeCommonSettingValueChange(key: string): Observable<string[]>;

где:

IPersonalSettings.changeSettingValue

Изменение значения персональной настройки по ключу.

changeSettingValue(key: string, value: string): Observable<void>;

где:

Интерфейс IBimFeatures

Интерфейс предназначен для работы с инструментами информационного моделирования моделей.
Позволяет получать экземпляры сервисов.

IBimFeatures.searchSetService

Получение экземпляра сервиса IBimSearchSetService для работы с поисковыми наборами и выполнению поиска по BIM‑модели.

get searchSetService(): IBimSearchSetService;

где:

Интерфейс IBimSearchSetService

Интерфейс предназначен для работы с поисковыми наборами и выполнению поиска по BIM‑модели.

IBimSearchSetService.getFromModel

Получение списка поисковых наборов верхнего уровня, расположенных непосредственно в корневой (скрытой) папке модели. Не выполняет обход подкаталогов, возвращает только элементы первого уровня.

getFromModel(id: string): Observable<IBimSearchSetData[]>;

где:

IBimSearchSetService.getRecursivelyFromModel

Получение полного списка всех элементов из корневой (скрытой) папки модели с рекурсивным обходом всех вложенных папок.

getRecursivelyFromModel(id: string): Observable<IBimSearchSetData[]>;

где:

IBimSearchSetService.getFromFolder

Получение списка поисковых наборов, находящихся непосредственно в указанной папке поисковых наборов. Вложенные папки не обходятся.

getFromFolder(id: string): Observable<IBimSearchSetData[]>;

где:

IBimSearchSetService.executeSearchSet

Выполнение сохранённого поискового набора по указанным частям модели.

executeSearchSet(id: string, modelPartIds: string[]): Observable<IBimModelSearchResult[]>;

где:

IBimSearchSetService.executeStringQuery

Выполнение строкового поискового запроса по указанным частям модели.

executeStringQuery(query: string, modelPartIds: string[]): Observable<IBimModelSearchResult[]>;

где:

5. Интерфейсы контекста визуального представления документа

Интерфейс IRenderContextProvider

Отдаёт экземпляр класса RenderContex. Получить интерфейс можно с помощью инжектирования.

getRenderContext(): RenderContext

где:

RenderContext

Используйте этот тип контекста, чтобы узнать версию и элемент отображаемого документа. Получить объект можно через интерфейс IRenderContextProvider.

RenderContext.dataObject

Отдаёт элемент отображаемого документа.

get dataObject(): IDataObject
RenderContext.selectedVersion

Получает версию отображаемого документа.

get selectedVersion(): string

6. Интерфейсы контекста визуального представления пространства модели

Интерфейс BimElementPanelContext

Используйте этот тип контекста, для встраивания в левую панель (панель элемента) пространства "Информационного моделирования (BIM)" и чтобы узнать идентификатор модели и экземпляр PilotWeb3D.Viewer3D - обозревателя модели.

get modelId(): string 

где:

get viewer(): PilotWeb3D.Viewer3D

где:

BimRightPanelContext

Используйте этот тип контекста, для встраивания в правую панель пространства "Информационного моделирования (BIM)" и чтобы узнать идентификатор модели и экземпляр PilotWeb3D.Viewer3D - обозревателя модели.

get modelId(): string 

где:

get viewer(): PilotWeb3D.Viewer3D

где:

7. Дополнительные интерфейсы и утилиты

Ошибка ExpectedError

Класс ожидаемой ошибки. При ее обработке диалог ошибки отображается без дополнительных деталей (callstack, url),
либо вообще не отображается.

isSilent

Определяет, отображается ли диалог ошибки.

isSilent(): boolean = false