UI-Extensions
How to extend the SCM-Manager UI with plugins
UI-Extensions contains the building blocks for the SCM-Manager ui extension system.
Extensions and ExtensionPoints
Extension points are spots in the ui, where the ui could be extended or modified. An extension point requires a unique name and is represented as React component.
Example:
<div>
<h2>Repository</h2>
<ExtensionPoint name="repo.details" />
</div>
We can register an extension, in the form of a React component, to the "repo.details" extension point, by using the binder:
import { binder } from "@scm-manager/ui-extensions";
const Rtfm = () => {
return <strong>Read the f*** manual</strong>;
};
binder.bind("repo.details", Rtfm);
The ExtensionPoint will now find and render the Rtfm component.
Render multiple extensions
An extension point can render multiple extensions at one. This can be done with the renderAll parameter:
<div>
<h2>Repository</h2>
<ExtensionPoint name="repo.details" renderAll={true} />
</div>
Now we can bind multiple components to the same extension point.
const Rtfm = () => {
return <strong>Read the f*** manual</strong>;
};
const RealyRtfm = () => {
return <h1>Read the f*** manual</h1>;
};
binder.bind("repo.details", Rtfm);
binder.bind("repo.details", RealyRtfm);
Passing props to extensions
An extension point author can pass React properties to the extensions. This can be done with the props
property:
<div>
<ExtensionPoint name="repo.title" props={{name: "myrepo"}} />
</div>
The extension becomes now the defined react properties as input:
const Title = (props) => {
return <h1>Repository {props.name}</h1>;
};
binder.bind("repo.title", Title);
Defaults
An ExtensionPoint is able to render a default, if no extension is bound to the ExtensionPoint. The default can be passed as React children:
<ExtensionPoint name="repo.title">
<h1>Default Title</h1>
</ExtensionPoint>
Conditional rendering
An extension can specify a predicate function to the binder. This function becomes the props of the ExtensionPoint as input and only if the predicate returns true the extension will be rendered:
const GitAvatar = () => {
return <img src="/git/avatar.png" alt="git avatar" />;
};
binder.bind("repo.avatar", GitAvatar, (props) => props.type === "git");
<ExtensionPoint name="repo.avatar" props={type: "git"} />