fix(gpu-service): show global instance templates under custom scopes

The Instance Templates management page requested the `mine` list scope,
which drops admin-curated Global templates for non-admin callers. The
Inference Backend page uses the default scope and shows Global + own
rows, so the two pages behaved inconsistently.

Use the default scope on the templates page so Global templates are
visible alongside the caller's own, and gate Edit/Delete on the card so
Global rows a non-admin can't modify render read-only.
This commit is contained in:
gitlawr
2026-07-08 16:27:40 +08:00
committed by jialin
parent f18c12662b
commit fdafdfc3d1
3 changed files with 18 additions and 10 deletions
@@ -6,8 +6,8 @@ import useUserDirectory from '../hooks/use-user-directory';
/**
* Owner tag for template cards, disambiguating same-name templates in
* the admin's cross-tenant view. Renders nothing for non-admin callers
* (the management page is `mine`-scoped for them) and when a plugin
* provides its own `OwnerScopeTag` slot.
* (gated on `canSeeAdmin`) and when a plugin provides its own
* `OwnerScopeTag` slot.
*/
const OwnerTag: React.FC<{ ownerId?: number | null }> = ({ ownerId }) => {
const intl = useIntl();
@@ -28,7 +28,7 @@ import {
TemplateCard,
ThemeTag
} from '@gpustack/core-ui';
import { useIntl } from '@umijs/max';
import { useAccess, useIntl } from '@umijs/max';
import { Button, Tag } from 'antd';
import { useMemo } from 'react';
import styled from 'styled-components';
@@ -144,8 +144,15 @@ interface TemplateCardProps {
const TemplateCardItem: React.FC<TemplateCardProps> = ({ data, onSelect }) => {
const intl = useIntl();
const access = useAccess();
const { isDarkTheme } = useUserSettings();
// Global templates (owner_principal_id NULL) are admin-curated and
// only editable by an admin. Principal-owned rows only reach a
// non-admin's list when they own them, so those are always
// manageable by the caller.
const canManage = !!access.canSeeAdmin || data.owner_principal_id != null;
const manufacturerLabelMap: Record<string, string> = useMemo(() => {
return Object.values(GPUsConfigs).reduce(
(acc, item) => {
@@ -234,6 +241,9 @@ const TemplateCardItem: React.FC<TemplateCardProps> = ({ data, onSelect }) => {
};
const renderActions = () => {
if (!canManage) {
return null;
}
return (
<span onClick={handleonClickAction} className="operations">
<DropdownActions
+5 -7
View File
@@ -45,13 +45,11 @@ const GPUServiceTemplates: React.FC = () => {
isInfiniteScroll: true,
contentForDelete: intl.formatMessage({ id: 'gpuservice.template' }),
defaultQueryParams: {
perPage: 24,
// Management view: drop Global rows for non-admin callers — the
// page is a CRUD surface, and admin-curated Global templates
// they can't edit only add visual noise. The instance-create
// picker (uses ``useQueryTemplates`` separately) doesn't set
// this and so still sees Global presets.
mine: true
// Default (non-``mine``) scope: Global rows plus rows owned by the
// caller's current principal, matching the Inference Backend page.
// Global rows a non-admin can't edit render read-only — the card
// gates Edit/Delete on ownership.
perPage: 24
}
});
const { openTemplateModalStatus, openTemplateModal, closeTemplateModal } =