feat: distinguish same-name GPU service resources across users
Resource names are unique per owning principal, so different users can legally create same-name GPU instances, templates, SSH public keys, storage volumes and storage types — but the admin's cross-tenant lists and the instance-create template picker rendered them indistinguishably. - Group the template picker by owning scope: Your Templates, Global Templates, then — admin cross-tenant view only — one group per owner. A single group renders flat without headers. A plugin can take over grouping via hooks.useTemplateOwnerGroups when its principal model scopes templates beyond USER owners; a plugin without the hook keeps the flat list. - Add an admin-only Creator column to the Instances, SSH Public Keys, Storage and Storage Types tables, sitting right before Created (mirroring the API Keys page convention). Resolves creator_id to a username via the user directory, falling back to owner_principal_id for legacy rows — a personal-scope row's creator IS its owner. - Tag template cards with their owner scope (Global / username) for admins. The Creator column and the card tag defer to a plugin that registers the page's list columns / the OwnerScopeTag slot. Requires the gpustack server change that records creator_id on templates, SSH public keys and storage types.
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
import useCreatorColumn from '@/pages/gpu-service/hooks/use-creator-column';
|
||||
import { usePluginListColumns } from '@/plugins/list-extra-columns';
|
||||
import { AutoTooltip, DropdownButtons } from '@gpustack/core-ui';
|
||||
import { useIntl } from '@umijs/max';
|
||||
@@ -20,6 +21,7 @@ const useStorageColumns = ({
|
||||
}: ColumnsHookProps): ColumnsType<ListItem> => {
|
||||
const intl = useIntl();
|
||||
const pluginCols = usePluginListColumns('gpuStorage');
|
||||
const creatorCols = useCreatorColumn<ListItem>('gpuStorage');
|
||||
return useMemo(() => {
|
||||
const pluginRendered = pluginCols.map((c) => ({
|
||||
title: intl.formatMessage({ id: c.titleId }),
|
||||
@@ -68,6 +70,7 @@ const useStorageColumns = ({
|
||||
sorter: false,
|
||||
render: (value: string) => (value ? value.replace(/Gi$/, 'GB') : '-')
|
||||
},
|
||||
...creatorCols,
|
||||
// {
|
||||
// title: intl.formatMessage({ id: 'common.table.status' }),
|
||||
// dataIndex: ['status', 'phase'],
|
||||
@@ -111,7 +114,14 @@ const useStorageColumns = ({
|
||||
)
|
||||
}
|
||||
];
|
||||
}, [handleSelect, sortOrder, storageClassList, intl, pluginCols]);
|
||||
}, [
|
||||
handleSelect,
|
||||
sortOrder,
|
||||
storageClassList,
|
||||
intl,
|
||||
pluginCols,
|
||||
creatorCols
|
||||
]);
|
||||
};
|
||||
|
||||
export default useStorageColumns;
|
||||
|
||||
Reference in New Issue
Block a user