feat: plugin extension slots for access, request interceptors, Users actions, and form fields
Four purely-additive seams that let build-time tooling extend host behaviour without forking files: * `src/access.extensions.ts` — identity `applyAccessExtensions` (mirrors `config/routes.extensions.ts`). `src/access.ts` runs the resolved predicate object through it. Adds two new predicates, `canSeeOrgAdmin` and `canManageCurrentOrg`, alongside the existing `canSeeAdmin`. Resources, Models children, Cluster Management, and Resources/Backends are retagged from `canSeeAdmin` to `canSeeOrgAdmin`. Users and Dashboard stay strict. * `src/request.extensions.ts` — identity-empty `extraRequestInterceptors`. `src/request-config.tsx` spreads it into the existing `requestInterceptors` list so extensions can inject context-aware headers without forking the request config. * Users page action column — renders `getGPUStackPlugin()?.components?.UserRowActions` next to the existing DropdownButtons inside a Space when a plugin component is registered. If absent, the cell renders exactly as before. * `src/components/plugin-extra-fields.tsx` — generic component-slot helper. Renders `pluginManager.components.<name>` if registered, forwarding a `context` payload. Used by create/edit forms to let plugins inject extra `Form.Item` fields. Mounted in the relevant create forms — API Keys, Cloud Credentials, Clusters, Model Routes, Model Providers, and Inference Backends — under the slot name `CreateOrgScopeField`. Resources whose org is implicit from a parent (Models / Workers / Benchmarks / Worker Pools / Model Files inherit from the chosen Cluster) deliberately don't mount the slot.
This commit is contained in:
@@ -0,0 +1,27 @@
|
||||
import { getGPUStackPlugin } from '@/plugins';
|
||||
import React from 'react';
|
||||
|
||||
// Render a plugin-provided component registered under
|
||||
// `pluginManager.components.<key>`. If no plugin is registered, or
|
||||
// the plugin doesn't export this slot, renders nothing — host pages
|
||||
// embedding the slot stay unchanged when no plugin is present.
|
||||
//
|
||||
// Used by create / edit forms to let plugins inject extra Form.Item
|
||||
// fields. Because antd `Form` walks the JSX tree to collect named
|
||||
// `Form.Item` values, the plugin's content gets picked up by the
|
||||
// surrounding form automatically — no host-side wiring required.
|
||||
const PluginExtraFields: React.FC<{
|
||||
name: string;
|
||||
// Free-form payload forwarded to the plugin component, e.g. so a
|
||||
// form-specific slot can pass its action / record context if it
|
||||
// needs to.
|
||||
context?: Record<string, any>;
|
||||
}> = ({ name, context }) => {
|
||||
const Slot = getGPUStackPlugin()?.components?.[name];
|
||||
if (!Slot) {
|
||||
return null;
|
||||
}
|
||||
return <Slot context={context} />;
|
||||
};
|
||||
|
||||
export default PluginExtraFields;
|
||||
Reference in New Issue
Block a user