Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
<!-- Raise an issue to propose your change (https://github.com/opencv/cvat/issues). It helps to avoid duplication of efforts from multiple independent contributors. Discuss your ideas with maintainers to be sure that changes will be approved and merged. Read the [Contribution guide](https://opencv.github.io/cvat/docs/contributing/). --> <!-- Provide a general summary of your changes in the Title above --> ### Motivation and context <!-- Why is this change required? What problem does it solve? If it fixes an open issue, please link to the issue here. Describe your changes in detail, add screenshots. --> ### How has this been tested? <!-- Please describe in detail how you tested your changes. Include details of your testing environment, and the tests you ran to see how your change affects other areas of the code, etc. --> ### Checklist <!-- Go over all the following points, and put an `x` in all the boxes that apply. If an item isn't applicable for some reason, then ~~explicitly strikethrough~~ the whole line. If you don't do that, GitHub will show incorrect progress for the pull request. If you're unsure about any of these, don't hesitate to ask. We're here to help! --> - [x] I submit my changes into the `develop` branch - [ ] I have added a description of my changes into the [CHANGELOG](https://github.com/opencv/cvat/blob/develop/CHANGELOG.md) file - [ ] I have updated the documentation accordingly - [ ] I have added tests to cover my changes - [ ] I have linked related issues (see [GitHub docs]( https://help.github.com/en/github/managing-your-work-on-github/linking-a-pull-request-to-an-issue#linking-a-pull-request-to-an-issue-using-a-keyword)) - [x] I have increased versions of npm packages if it is necessary ([cvat-canvas](https://github.com/opencv/cvat/tree/develop/cvat-canvas#versioning), [cvat-core](https://github.com/opencv/cvat/tree/develop/cvat-core#versioning), [cvat-data](https://github.com/opencv/cvat/tree/develop/cvat-data#versioning) and [cvat-ui](https://github.com/opencv/cvat/tree/develop/cvat-ui#versioning)) ### License - [x] I submit _my code changes_ under the same [MIT License]( https://github.com/opencv/cvat/blob/develop/LICENSE) that covers the project. Feel free to contact the maintainers if that's a concern. # How to add your own plugin **1. Write a ``PluginBuilder``** ``PluginBuilder`` is a function that accepts the following object as an argument: ```js { dispatch, REGISTER_ACTION, REMOVE_ACTION, core, } ``` This object is passed from the core application. Where: - ``dispatch`` is a redux function that can be used to add any React components - ``REGISTER_ACTION`` is action name to append component - ``REMOVE_ACTION`` is action name to remove component - ``core`` core library to access to server and interaction with any available API, e.g. ``core.tasks.get()``, ``core.server.request('dummy/url/...', { method: 'POST', data: { param1: 'value1', param2: 'value2' } })`` If you want to include authorization headers to the request, you must do the request via the core library. ``PluginBuilder`` must return the following object ``` { name: string; destructor: CallableFunction; } ``` - ``name`` is a plugin name - ``destructor`` is a function that removes plugin from storage and does any destructive actions ``PluginBuilder`` might register additional components this way: ```tsx const Component = () => <Button> Press me </Button>; dispatch({ type: REGISTER_ACTION, payload: { path: 'loginPage.loginForm', // path must be supported by the core application component: Component, data: { // optional method, define if necessary to render component conditionally, based on props, state of a target component shouldBeRendered: (targetComponentProps, targetComponentState) => { return true; } // optional field, define if necessary to affect rendering order weight: 5, } } }); ``` Destructor callback of a ``PluginBuilder`` must remove components this way: ```ts dispatch({ type: REMOVE_ACTION, payload: { path: 'loginPage.loginForm', // the same path as when register component: Component, // the same component as when register } }); ``` **2. Define plugin entrypoint** It must be in ``<plugin_directory>/src/ts/index.tsx``. Plugin entrypoint might register plugin in the core application when ``plugins.ready`` event is triggered. To achieve that, pass ``PluginBuilder`` to the exposed method: ``window.cvatUI.registerComponent(PluginBuilder)``. In general plugin can register itself anytime, but the above method must be available. Example code is below: ```ts function register() { if (Object.prototype.hasOwnProperty.call(window, 'cvatUI')) { (window as any as { cvatUI: { registerComponent: PluginEntryPoint } }) .cvatUI.registerComponent(PluginBuilder); } }; window.addEventListener('plugins.ready', register, { once: true }); ``` **3. Build/run core application together with plugins:** Just pass ``CLIENT_PLUGINS`` env variable to webpack. It can include multiple plugins: ```sh CLIENT_PLUGINS="path/to/plugin1:path/to/plugin2:path/to/plugin3" yarn start:cvat-ui CLIENT_PLUGINS="path/to/plugin1:path/to/plugin2:path/to/plugin3" yarn build:cvat-ui ``` Path may be defined in two formats: - relative to ``cvat-ui`` directory: ``plugins/plugin1``, ``../../another_place/plugin2`` - absolute, including entrypoint file: ``/home/user/some_path/plugin/src/ts/index.tsx`` **Webpack defines two aliases:** ``@modules`` - to use dependencies of the core application For example React may be imported this way: ```ts import React from '@modules/react'; ``` ``@root`` - to import something from the core application ```ts import { CombinedState } from '@root/reducers'; ``` You can install other dependencies to plugin directory if necessary. To avoid typescript errors in IDE and working with types, you can add ``tsconfig.json``. ```json { "compilerOptions": { "target": "es2020", "baseUrl": ".", "paths": { "@modules/*": ["/path/to/cvat/node_modules/*"], "@root/*": ["path/to/cvat/cvat-ui/src/*"] }, "moduleResolution": "node", "lib": ["dom", "dom.iterable", "esnext"], "jsx": "react", } } ```
- Loading branch information