Skip to content
Merged

440 #1748

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -1780,8 +1780,8 @@ private CodeBlock getSchemaCodeBlock(
}
} else {
builder.add(
getExtensionsCodeBlock(propertyName, propertyDescription, required, schema, outputSchema,
extensionMap));
getExtensionsCodeBlock(
propertyName, propertyDescription, required, schema, outputSchema, extensionMap));
}

return builder.build();
Expand Down
4 changes: 2 additions & 2 deletions client/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ const automationNavigation: NavigationType[] = [
name: 'Project Instances',
},
{
href: '/automation/api-platform/api-collections',
href: '/automation/api-platform',
icon: LandmarkIcon,
name: 'API Collections',
},
Expand Down Expand Up @@ -230,7 +230,7 @@ function App() {
<Outlet />

{ai.enabled && showCopilot && (
<aside className="border-l">
<aside className="border-l border-l-border/70">
<CopilotPanel />
</aside>
)}
Expand Down
13 changes: 11 additions & 2 deletions client/src/components/ComboBox/ComboBox.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ export type ComboBoxItemType = {

export interface ComboBoxProps {
disabled?: boolean;
emptyMessage?: string;
items: ComboBoxItemType[];
maxHeight?: boolean;
name?: string;
Expand All @@ -26,7 +27,15 @@ export interface ComboBoxProps {
value?: any;
}

const ComboBox: React.FC<ComboBoxProps> = ({disabled, items, name, onBlur, onChange, value}: ComboBoxProps) => {
const ComboBox: React.FC<ComboBoxProps> = ({
disabled,
emptyMessage,
items,
name,
onBlur,
onChange,
value,
}: ComboBoxProps) => {
const [open, setOpen] = useState(false);

const commandItems = items.map((comboBoxItem) => (
Expand Down Expand Up @@ -84,7 +93,7 @@ const ComboBox: React.FC<ComboBoxProps> = ({disabled, items, name, onBlur, onCha
<CommandInput className="h-9 border-none ring-0" placeholder="Search..." />

<CommandList>
<CommandEmpty>No item found.</CommandEmpty>
<CommandEmpty>{emptyMessage ?? 'No item found.'}</CommandEmpty>

<CommandGroup>{commandItems}</CommandGroup>
</CommandList>
Expand Down
4 changes: 2 additions & 2 deletions client/src/components/TagList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ interface TagProps {
}

const Tag = ({onDeleteTag, tag}: TagProps) => (
<div className="group flex max-h-8 items-center justify-between rounded-full border border-muted pl-2 pr-1 text-xs text-gray-700">
<div className="group flex max-h-8 items-center justify-between rounded-full border border-border/50 pl-2 pr-1 text-xs text-gray-700">
<span className="py-1">{tag.name}</span>

<Tooltip>
Expand Down Expand Up @@ -153,7 +153,7 @@ const TagList = ({getRequest, id, remainingTags, tags, updateTagsMutation}: TagL
</>
) : (
<div
className="flex size-6 cursor-pointer items-center justify-center rounded border border-muted hover:bg-gray-200"
className="flex size-6 cursor-pointer items-center justify-center rounded border border-border/50 hover:bg-gray-200"
onClick={(event) => {
event.preventDefault();

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
import {Type} from '@/ee/pages/automation/api-platform/api-collections/ApiCollections';
import {LeftSidebarNav, LeftSidebarNavItem} from '@/shared/layout/LeftSidebarNav';
import {Project, Tag} from '@/shared/middleware/automation/configuration';
import {TagIcon} from 'lucide-react';
import {useLocation} from 'react-router-dom';

interface ApiPlatformLeftSidebarNavProps {
environment?: number;
filterData?: {id?: number; type: Type};
projects: Project[] | undefined;
tags: Tag[] | undefined;
}

const ApiPlatformLeftSidebarNav = ({environment, filterData, projects, tags}: ApiPlatformLeftSidebarNavProps) => {
const location = useLocation();

return (
<>
<LeftSidebarNav
body={
<>
{[{label: 'All Environments'}, {label: 'Test', value: 1}, {label: 'Production', value: 2}]?.map(
(item) => (
<LeftSidebarNavItem
item={{
current:
environment === item.value && !location.pathname.includes('api-clients'),
id: item.value,
name: item.label,
}}
key={item.value ?? ''}
toLink={`../api-collections?environment=${item.value ?? ''}${filterData?.id ? `&${filterData.type === Type.Project ? 'projectId' : 'tagId'}=${filterData.id}` : ''}`}
/>
)
)}
</>
}
title="Environments"
/>

<LeftSidebarNav
body={
<>
<LeftSidebarNavItem
item={{
current: !filterData?.id && filterData?.type === Type.Project,
name: 'All Projects',
}}
toLink={`../api-collections?environment=${environment ?? ''}`}
/>

{projects &&
projects?.map((item) => (
<LeftSidebarNavItem
item={{
current: filterData?.id === item.id && filterData?.type === Type.Project,
id: item.id,
name: item.name,
}}
key={item.name}
toLink={`../api-collections?projectId=${item.id}&environment=${environment ?? ''}`}
/>
))}
</>
}
title="Projects"
/>

<LeftSidebarNav
body={
<>
{tags && !!tags.length ? (
tags?.map((item) => (
<LeftSidebarNavItem
icon={<TagIcon className="mr-1 size-4" />}
item={{
current: filterData?.id === item.id && filterData?.type === Type.Tag,
id: item.id!,
name: item.name,
}}
key={item.id}
toLink={`?tagId=${item.id}&environment=${environment ?? ''}`}
/>
))
) : (
<span className="px-3 text-xs">No defined tags.</span>
)}
</>
}
title="Tags"
/>

<LeftSidebarNav
body={
<LeftSidebarNavItem
item={{
current: location.pathname.includes('api-clients'),
id: 'api-clients',
name: 'API Clients',
}}
toLink="../api-clients"
/>
}
/>
</>
);
};

export default ApiPlatformLeftSidebarNav;
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import EmptyList from '@/components/EmptyList';
import PageLoader from '@/components/PageLoader';
import {Button} from '@/components/ui/button';
import ApiPlatformLeftSidebarNav from '@/ee/pages/automation/api-platform/ApiPlatformLeftSidebarNav';
import ApiClientDialog from '@/ee/pages/automation/api-platform/api-clients/components/ApiClientDialog';
import ApiClientTable from '@/ee/pages/automation/api-platform/api-clients/components/ApiClientTable';
import {useGetApiCollectionTagsQuery} from '@/ee/queries/apiCollectionTags.queries';
import {useWorkspaceStore} from '@/pages/automation/stores/useWorkspaceStore';
import Header from '@/shared/layout/Header';
import LayoutContainer from '@/shared/layout/LayoutContainer';
import {useGetWorkspaceProjectsQuery} from '@/shared/queries/automation/projects.queries';
import {useGetApiClientsQuery} from '@/shared/queries/platform/apiClients.queries';
import {KeyIcon} from 'lucide-react';
import {useState} from 'react';

const ApiClients = () => {
const [showEditDialog, setShowEditDialog] = useState(false);

const {currentWorkspaceId} = useWorkspaceStore();

const {data: apiKeys, error: apiKeysError, isLoading: apiKeysLoading} = useGetApiClientsQuery();

const {data: projects} = useGetWorkspaceProjectsQuery({
id: currentWorkspaceId!,
projectInstances: true,
});

const {data: tags} = useGetApiCollectionTagsQuery();

return (
<PageLoader errors={[apiKeysError]} loading={apiKeysLoading}>
<LayoutContainer
header={
<Header
className="w-full px-4 2xl:mx-auto 2xl:w-4/5"
position="main"
right={
apiKeys &&
apiKeys.length > 0 && <ApiClientDialog triggerNode={<Button>New API Client</Button>} />
}
title="API Clients"
/>
}
leftSidebarBody={<ApiPlatformLeftSidebarNav projects={projects} tags={tags} />}
leftSidebarHeader={<Header title="API Collections" />}
leftSidebarWidth="64"
>
{apiKeys && apiKeys.length > 0 ? (
<ApiClientTable apiClients={apiKeys} />
) : (
<EmptyList
button={<Button onClick={() => setShowEditDialog(true)}>New API Client</Button>}
icon={<KeyIcon className="size-24 text-gray-300" />}
message="Get started by creating a new API client."
title="No API Clients"
/>
)}

{showEditDialog && <ApiClientDialog onClose={() => setShowEditDialog(false)} />}
</LayoutContainer>
</PageLoader>
);
};

export default ApiClients;
Loading