Add hook to add extra content to Web UI pages

Allow plugins to extend Web UI pages provided by Clusterio by
adding components in the componentExtra property of the plugin.
This commit is contained in:
Hornwitser committed 2022-02-10 14:51:51 +01:00
1 parent 68b8ac6b8c
commit 5319ff3907
11 files changed
+73 -1

No files matched your search

+36
View File
@@ -653,6 +653,42 @@ class BaseWebPlugin {
* @type {Array<module:lib/plugin~Page>}
*/
this.pages = [];
/**
* Extra react component to add to core components
*
* Interface to augment core components of the web UI. Setting a
* component as one of the supported properties of this object will
* cause the web UI to render it when displaying that component,
* usually at the end. Each component will receive a `plugin` param
* which is the instance of the web plugin that contained the
* component extra.
*
* @type {object}
* @property {React.ComponentType} MasterPage -
* Placed at the end of the master page.
* @property {React.ComponentType} SlavesPage -
* Placed at the end of the slaves list page.
* @property {React.ComponentType} SlaveViewPage -
* Placed at the end of each slave page. Takes a `slave` param
* which is the slave the page is displayed for.
* @property {React.ComponentType} InstancesPage -
* Placed at the end of the instance list page.
* @property {React.ComponentType} InstanceViewPage -
* Placed at the end of each instance page. Takes an `instance`
* param which is the instance the page is displayed for.
* @property {React.ComponentType} UsersPage -
* Placed at the end of the users list page.
* @property {React.ComponentType} UserViewPage -
* Placed at the end of each user page. Takes a `user` param
* which is the user object the page is displayed for.
* @property {React.ComponentType} RolesPage -
* Placed at the end of the roles list page.
* @property {React.ComponentType} RoleViewPage -
* Placed at the end of each role page. Takes a `role` param
* which is the role object the page is displayed for.
*/
this.componentExtra = {};
}
/**
@@ -8,6 +8,7 @@ import { libLink } from "@clusterio/lib";
import { useAccount } from "../model/account";
import ControlContext from "./ControlContext";
import PageLayout from "./PageLayout";
import PluginExtra from "./PluginExtra";
import InstanceConfigTree from "./InstanceConfigTree";
import LogConsole from "./LogConsole";
import InstanceRcon from "./InstanceRcon";
@@ -147,5 +148,7 @@ export default function InstanceViewPage(props) {
}
{account.hasPermission("core.instance.get_config") && <InstanceConfigTree id={instanceId} />}
<PluginExtra component="InstanceViewPage" instance={instance} />
</PageLayout>;
}
@@ -7,6 +7,7 @@ import { libConfig, libLink } from "@clusterio/lib";
import { useAccount } from "../model/account";
import ControlContext from "./ControlContext";
import PageLayout from "./PageLayout";
import PluginExtra from "./PluginExtra";
import { useInstanceList } from "../model/instance";
import InstanceList from "./InstanceList";
import { notifyErrorHandler } from "../util/notify";
@@ -94,5 +95,6 @@ export default function InstancesPage() {
/>
<InstanceList instances={instanceList} />
<PluginExtra component="InstancesPage" />
</PageLayout>;
}
@@ -1,6 +1,7 @@
import React from "react";
import { Typography } from "antd";
import PluginExtra from "./PluginExtra";
import LogConsole from "./LogConsole";
import { useAccount } from "../model/account";
import MasterConfigTree from "./MasterConfigTree";
@@ -9,7 +10,7 @@ import PageLayout from "./PageLayout";
const { Title } = Typography;
export default function SlavesPage() {
export default function MasterPage() {
let account = useAccount();
return <PageLayout nav={[{ name: "Master" }]}>
@@ -19,5 +20,6 @@ export default function SlavesPage() {
<LogConsole master={true} />
</>}
{account.hasPermission("core.master.get_config") && <MasterConfigTree />}
<PluginExtra component="MasterPage" />
</PageLayout>;
};
@@ -0,0 +1,17 @@
import React, { useContext } from "react";
import ControlContext from "./ControlContext";
export default function PluginExtra(params) {
let control = useContext(ControlContext);
let components = [];
for (let [name, plugin] of control.plugins) {
if (Object.prototype.hasOwnProperty.call(plugin.componentExtra, params.component)) {
let ComponentExtra = plugin.componentExtra[params.component];
components.push(<ComponentExtra key={name} plugin={plugin} {...params}/>);
}
}
return components;
}
@@ -8,6 +8,7 @@ import { libLink, libUsers } from "@clusterio/lib";
import { useAccount } from "../model/account";
import ControlContext from "./ControlContext";
import PageLayout from "./PageLayout";
import PluginExtra from "./PluginExtra";
import { notifyErrorHandler } from "../util/notify";
@@ -149,5 +150,6 @@ export default function RoleViewPage() {
</Form.Item>
))}
</Form>
<PluginExtra component="RoleViewPage" role={role} />
</PageLayout>;
}
@@ -8,6 +8,7 @@ import { useAccount } from "../model/account";
import ControlContext from "./ControlContext";
import { notifyErrorHandler } from "../util/notify";
import PageLayout from "./PageLayout";
import PluginExtra from "./PluginExtra";
const strcmp = new Intl.Collator(undefined, { numerice: "true", sensitivity: "base" }).compare;
@@ -99,5 +100,6 @@ export default function RolesPage() {
},
})}
/>
<PluginExtra component="RolesPage" />
</PageLayout>;
}
@@ -8,6 +8,7 @@ import { useAccount } from "../model/account";
import { useInstanceList } from "../model/instance";
import { useSlave } from "../model/slave";
import PageLayout from "./PageLayout";
import PluginExtra from "./PluginExtra";
const { Title } = Typography;
@@ -60,5 +61,6 @@ export default function SlaveViewPage(props) {
<Title level={5} style={{ marginTop: 16 }}>Console</Title>
<LogConsole slaves={[slaveId]} />
</>}
<PluginExtra component="SlaveViewPage" slave={slave} />
</PageLayout>;
}
@@ -7,6 +7,7 @@ import { libLink } from "@clusterio/lib";
import { useAccount } from "../model/account";
import ControlContext from "./ControlContext";
import PageLayout from "./PageLayout";
import PluginExtra from "./PluginExtra";
import { useSlaveList } from "../model/slave";
import { notifyErrorHandler } from "../util/notify";
@@ -129,5 +130,6 @@ export default function SlavesPage() {
},
})}
/>
<PluginExtra component="SlavesPage" />
</PageLayout>;
};
@@ -8,6 +8,7 @@ import { libLink } from "@clusterio/lib";
import { useAccount } from "../model/account";
import ControlContext from "./ControlContext";
import PageLayout from "./PageLayout";
import PluginExtra from "./PluginExtra";
import { notifyErrorHandler } from "../util/notify";
@@ -258,5 +259,6 @@ export default function UserViewPage() {
</Space>
</Form.Item>
</Form>
<PluginExtra component="UserViewPage" user={user} />
</PageLayout>;
}
@@ -8,6 +8,7 @@ import { useAccount } from "../model/account";
import ControlContext from "./ControlContext";
import { notifyErrorHandler } from "../util/notify";
import PageLayout from "./PageLayout";
import PluginExtra from "./PluginExtra";
const strcmp = new Intl.Collator(undefined, { numerice: "true", sensitivity: "base" }).compare;
@@ -121,5 +122,6 @@ export default function UsersPage() {
},
})}
/>
<PluginExtra component="UsersPage" />
</PageLayout>;
}