Skip to content

Commit

Permalink
feat: [alpha] Providers grid refactor (#1345)
Browse files Browse the repository at this point in the history
Co-authored-by: Yingjie He <[email protected]>
  • Loading branch information
lily-de and yingjiehe-xyz authored Feb 24, 2025
1 parent d786eca commit c0c9fcc
Show file tree
Hide file tree
Showing 45 changed files with 1,445 additions and 21 deletions.
6 changes: 6 additions & 0 deletions Justfile
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,12 @@ run-ui:
@echo "Running UI..."
cd ui/desktop && npm install && npm run start-gui

# Run UI with alpha changes
run-ui-alpha:
@just release-binary
@echo "Running UI..."
cd ui/desktop && npm install && ALPHA=true npm run start-alpha-gui

# Run UI with latest (Windows version)
run-ui-windows:
@just release-windows
Expand Down
40 changes: 40 additions & 0 deletions ui/desktop/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion ui/desktop/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@
"lint:check": "eslint \"src/**/*.{ts,tsx}\"",
"format": "prettier --write \"src/**/*.{ts,tsx,css,json}\"",
"format:check": "prettier --check \"src/**/*.{ts,tsx,css,json}\"",
"prepare": "cd ../.. && husky install"
"prepare": "cd ../.. && husky install",
"start-alpha-gui": "ALPHA=true npm run start-gui"
},
"devDependencies": {
"@electron-forge/cli": "^7.5.0",
Expand Down
7 changes: 6 additions & 1 deletion ui/desktop/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import ChatView from './components/ChatView';
import SettingsView, { type SettingsViewOptions } from './components/settings/SettingsView';
import MoreModelsView from './components/settings/models/MoreModelsView';
import ConfigureProvidersView from './components/settings/providers/ConfigureProvidersView';
import ProviderSettings from './components/settings/providers/providers/NewProviderSettingsPage';

import 'react-toastify/dist/ReactToastify.css';

Expand All @@ -26,7 +27,8 @@ export type View =
| 'settings'
| 'moreModels'
| 'configureProviders'
| 'configPage';
| 'configPage'
| 'alphaConfigureProviders';

export type ViewConfig = {
view: View;
Expand Down Expand Up @@ -224,6 +226,9 @@ export default function App() {
}}
/>
)}
{view === 'alphaConfigureProviders' && (
<ProviderSettings onClose={() => setView('chat')} />
)}
{view === 'chat' && <ChatView setView={setView} />}
</div>
</div>
Expand Down
14 changes: 12 additions & 2 deletions ui/desktop/src/components/MoreMenu.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import { Popover, PopoverContent, PopoverTrigger, PopoverPortal } from '@radix-ui/react-popover';
import React, { useEffect, useState } from 'react';
import { More } from './icons';
import type { View } from '../ChatWindow';

import { View } from '../App';
interface VersionInfo {
current_version: string;
available_versions: string[];
Expand Down Expand Up @@ -260,6 +259,17 @@ export default function MoreMenu({ setView }: { setView: (view: View) => void })
>
Reset Provider
</button>
{process.env.ALPHA && (
<button
onClick={() => {
setOpen(false);
setView('alphaConfigureProviders');
}}
className="w-full text-left p-2 text-sm hover:bg-bgSubtle transition-colors text-indigo-800"
>
See new providers grid
</button>
)}
</div>
</PopoverContent>
</PopoverPortal>
Expand Down
28 changes: 14 additions & 14 deletions ui/desktop/src/components/settings/api_keys/utils.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,22 +24,22 @@ export async function getActiveProviders(): Promise<string[]> {
const configSettings = await getConfigSettings();

const activeProviders = Object.values(configSettings)
.filter((provider) => {
// 1. Get provider's config_status
const configStatus = provider.config_status ?? {};
.filter((provider) => {
// 1. Get provider's config_status
const configStatus = provider.config_status ?? {};

// 2. Collect only the keys *not* in default_key_value
const requiredKeyEntries = Object.entries(configStatus).filter(([k]) => isRequiredKey(k));
// 2. Collect only the keys *not* in default_key_value
const requiredKeyEntries = Object.entries(configStatus).filter(([k]) => isRequiredKey(k));

// 3. If there are *no* non-default keys, it is NOT active
if (requiredKeyEntries.length === 0) {
return false;
}
// 3. If there are *no* non-default keys, it is NOT active
if (requiredKeyEntries.length === 0) {
return false;
}

// 4. Otherwise, all non-default keys must be `is_set`
return requiredKeyEntries.every(([_, value]) => value?.is_set);
})
.map((provider) => provider.name || 'Unknown Provider');
// 4. Otherwise, all non-default keys must be `is_set`
return requiredKeyEntries.every(([_, value]) => value?.is_set);
})
.map((provider) => provider.name || 'Unknown Provider');

console.log('[GET ACTIVE PROVIDERS]:', activeProviders);
return activeProviders;
Expand Down Expand Up @@ -93,4 +93,4 @@ export async function getProvidersList(): Promise<Provider[]> {
models: item.details?.models || [], // Nested models array
requiredKeys: item.details?.required_keys || [], // Nested required keys array
}));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -235,8 +235,8 @@ export function ConfigureProvidersGrid() {
<div className="relative z-[9999]">
<ProviderSetupModal
provider={providers.find((p) => p.id === selectedForSetup)?.name || ''}
model="Example Model"
endpoint="Example Endpoint"
_model="Example Model"
_endpoint="Example Endpoint"
title={
modalMode === 'edit'
? `Edit ${providers.find((p) => p.id === selectedForSetup)?.name} Configuration`
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
import React from 'react';
import { ScrollArea } from '../../../ui/scroll-area';
import BackButton from '../../../ui/BackButton';
import ProviderGrid from './ProviderGrid';
import ProviderState from './interfaces/ProviderState';

const fakeProviderState: ProviderState[] = [
{
id: 'openai',
name: 'OpenAI',
isConfigured: true,
metadata: null,
},
{
id: 'anthropic',
name: 'Anthropic',
isConfigured: false,
metadata: null,
},
{
id: 'groq',
name: 'Groq',
isConfigured: false,
metadata: null,
},
{
id: 'google',
name: 'Google',
isConfigured: false,
metadata: null,
},
{
id: 'openrouter',
name: 'OpenRouter',
isConfigured: false,
metadata: null,
},
{
id: 'databricks',
name: 'Databricks',
isConfigured: false,
metadata: null,
},
{
id: 'ollama',
name: 'Ollama',
isConfigured: false,
metadata: { location: null },
},
];

export default function ProviderSettings({ onClose }: { onClose: () => void }) {
return (
<div className="h-screen w-full">
<div className="relative flex items-center h-[36px] w-full bg-bgSubtle"></div>

<ScrollArea className="h-full w-full">
<div className="px-8 pt-6 pb-4">
<BackButton onClick={onClose} />
<h1 className="text-3xl font-medium text-textStandard mt-1">Configure</h1>
</div>

<div className=" py-8 pt-[20px]">
<div className="flex justify-between items-center mb-6 border-b border-borderSubtle px-8">
<h2 className="text-xl font-medium text-textStandard">Providers</h2>
</div>

{/* Content Area */}
<div className="max-w-5xl pt-4 px-8">
<div className="relative z-10">
<ProviderGrid providers={fakeProviderState} />
</div>
</div>
</div>
</ScrollArea>
</div>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import React from 'react';
import { ProviderCard } from './subcomponents/ProviderCard';
import ProviderState from './interfaces/ProviderState';
import OnShowModal from './callbacks/ShowModal';
import OnAdd from './callbacks/AddProviderParameters';
import OnDelete from './callbacks/DeleteProviderParameters';
import OnShowSettings from './callbacks/UpdateProviderParameters';
import OnRefresh from './callbacks/RefreshActiveProviders';
import DefaultProviderActions from './subcomponents/actions/DefaultProviderActions';

function GridLayout({ children }: { children: React.ReactNode }) {
return (
<div className="grid grid-cols-3 sm:grid-cols-4 lg:grid-cols-5 xl:grid-cols-6 2xl:grid-cols-7 gap-3 auto-rows-fr max-w-full [&_*]:z-20">
{children}
</div>
);
}

function ProviderCards({ providers }: { providers: ProviderState[] }) {
const providerCallbacks = {
onShowModal: OnShowModal,
onAdd: OnAdd,
onDelete: OnDelete,
onShowSettings: OnShowSettings,
onRefresh: OnRefresh,
};
return (
<>
{providers.map((provider) => (
<ProviderCard
key={provider.name} // helps React efficiently update and track components when rendering lists
provider={provider}
providerCallbacks={providerCallbacks}
/>
))}
</>
);
}

export default function ProviderGrid({ providers }: { providers: ProviderState[] }) {
console.log('got these providers', providers);
return (
<GridLayout>
<ProviderCards providers={providers} />
</GridLayout>
);
}
Loading

0 comments on commit c0c9fcc

Please sign in to comment.