feat: use the permission page in bottom menu (#2218)

This commit is contained in:
Yingjie He
2025-04-16 14:51:01 -07:00
committed by GitHub
parent ec53e39347
commit 48a8f5a704
7 changed files with 34 additions and 65 deletions
+5 -1
View File
@@ -781,7 +781,11 @@ export default function App() {
}} }}
/> />
)} )}
{view === 'permission' && <PermissionSettingsView onClose={() => setView('settings')} />} {view === 'permission' && (
<PermissionSettingsView
onClose={() => setView((viewOptions as { parentView: View }).parentView)}
/>
)}
</div> </div>
</div> </div>
{isGoosehintsModalOpen && ( {isGoosehintsModalOpen && (
+3 -3
View File
@@ -3,7 +3,7 @@ import { useModel } from './settings/models/ModelContext';
import { Sliders } from 'lucide-react'; import { Sliders } from 'lucide-react';
import { ModelRadioList } from './settings/models/ModelRadioList'; import { ModelRadioList } from './settings/models/ModelRadioList';
import { Document, ChevronUp, ChevronDown } from './icons'; import { Document, ChevronUp, ChevronDown } from './icons';
import type { View } from '../App'; import type { View, ViewOptions } from '../App';
import { settingsV2Enabled } from '../flags'; import { settingsV2Enabled } from '../flags';
import { BottomMenuModeSelection } from './BottomMenuModeSelection'; import { BottomMenuModeSelection } from './BottomMenuModeSelection';
import ModelsBottomBar from './settings_v2/models/bottom_bar/ModelsBottomBar'; import ModelsBottomBar from './settings_v2/models/bottom_bar/ModelsBottomBar';
@@ -13,7 +13,7 @@ export default function BottomMenu({
setView, setView,
}: { }: {
hasMessages: boolean; hasMessages: boolean;
setView: (view: View) => void; setView: (view: View, viewOptions?: ViewOptions) => void;
}) { }) {
const [isModelMenuOpen, setIsModelMenuOpen] = useState(false); const [isModelMenuOpen, setIsModelMenuOpen] = useState(false);
const { currentModel } = useModel(); const { currentModel } = useModel();
@@ -74,7 +74,7 @@ export default function BottomMenu({
</span> </span>
{/* Goose Mode Selector Dropdown */} {/* Goose Mode Selector Dropdown */}
<BottomMenuModeSelection /> <BottomMenuModeSelection setView={setView} />
{/* Right-side section with ToolCount and Model Selector together */} {/* Right-side section with ToolCount and Model Selector together */}
<div className="flex items-center mr-4 space-x-1"> <div className="flex items-center mr-4 space-x-1">
@@ -1,18 +1,18 @@
import React, { useEffect, useRef, useState, useCallback } from 'react'; import React, { useEffect, useRef, useState, useCallback } from 'react';
import { getApiUrl, getSecretKey } from '../config'; import { getApiUrl, getSecretKey } from '../config';
import { ChevronDown, ChevronUp } from './icons'; import { ChevronDown, ChevronUp } from './icons';
import { import { all_goose_modes, ModeSelectionItem } from './settings_v2/mode/ModeSelectionItem';
all_goose_modes,
filterGooseModes,
ModeSelectionItem,
} from './settings/basic/ModeSelectionItem';
import { useConfig } from './ConfigContext'; import { useConfig } from './ConfigContext';
import { settingsV2Enabled } from '../flags'; import { settingsV2Enabled } from '../flags';
import { View, ViewOptions } from '../App';
export const BottomMenuModeSelection = () => { interface BottomMenuModeSelectionProps {
setView: (view: View, viewOptions?: ViewOptions) => void;
}
export const BottomMenuModeSelection = ({ setView }: BottomMenuModeSelectionProps) => {
const [isGooseModeMenuOpen, setIsGooseModeMenuOpen] = useState(false); const [isGooseModeMenuOpen, setIsGooseModeMenuOpen] = useState(false);
const [gooseMode, setGooseMode] = useState('auto'); const [gooseMode, setGooseMode] = useState('auto');
const [previousApproveModel, setPreviousApproveModel] = useState('');
const gooseModeDropdownRef = useRef<HTMLDivElement>(null); const gooseModeDropdownRef = useRef<HTMLDivElement>(null);
const { read, upsert } = useConfig(); const { read, upsert } = useConfig();
@@ -105,20 +105,14 @@ export const BottomMenuModeSelection = () => {
console.error('Store response error:', errorText); console.error('Store response error:', errorText);
throw new Error(`Failed to store new goose mode: ${newMode}`); throw new Error(`Failed to store new goose mode: ${newMode}`);
} }
if (gooseMode.includes('approve')) {
setPreviousApproveModel(gooseMode);
}
setGooseMode(newMode); setGooseMode(newMode);
} else { } else {
await upsert('GOOSE_MODE', newMode, false); await upsert('GOOSE_MODE', newMode, false);
if (gooseMode.includes('approve')) {
setPreviousApproveModel(gooseMode);
}
setGooseMode(newMode); setGooseMode(newMode);
} }
}; };
function getValueByKey(key) { function getValueByKey(key: string) {
const mode = all_goose_modes.find((mode) => mode.key === key); const mode = all_goose_modes.find((mode) => mode.key === key);
return mode ? mode.label : 'auto'; return mode ? mode.label : 'auto';
} }
@@ -139,15 +133,17 @@ export const BottomMenuModeSelection = () => {
{/* Dropdown Menu */} {/* Dropdown Menu */}
{isGooseModeMenuOpen && ( {isGooseModeMenuOpen && (
<div className="absolute bottom-[24px] right-0 w-[240px] bg-bgApp rounded-lg border border-borderSubtle"> <div className="absolute bottom-[24px] pl-4 pt-2 right-0 w-[240px] bg-bgApp rounded-lg border border-borderSubtle">
<div> <div>
{filterGooseModes(gooseMode, all_goose_modes, previousApproveModel).map((mode) => ( {all_goose_modes.map((mode) => (
<ModeSelectionItem <ModeSelectionItem
key={mode.key} key={mode.key}
mode={mode} mode={mode}
currentMode={gooseMode} currentMode={gooseMode}
showDescription={false} showDescription={false}
isApproveModeConfigure={false} isApproveModeConfigure={false}
parentView="chat"
setView={setView}
handleModeChange={handleModeChange} handleModeChange={handleModeChange}
/> />
))} ))}
@@ -1,6 +1,6 @@
import { ScrollArea } from '../ui/scroll-area'; import { ScrollArea } from '../ui/scroll-area';
import BackButton from '../ui/BackButton'; import BackButton from '../ui/BackButton';
import type { View } from '../../App'; import type { View, ViewOptions } from '../../App';
import ExtensionsSection from './extensions/ExtensionsSection'; import ExtensionsSection from './extensions/ExtensionsSection';
import ModelsSection from './models/ModelsSection'; import ModelsSection from './models/ModelsSection';
import { ModeSection } from './mode/ModeSection'; import { ModeSection } from './mode/ModeSection';
@@ -18,7 +18,7 @@ export default function SettingsView({
viewOptions, viewOptions,
}: { }: {
onClose: () => void; onClose: () => void;
setView: (view: View) => void; setView: (view: View, viewOptions?: ViewOptions) => void;
viewOptions: SettingsViewOptions; viewOptions: SettingsViewOptions;
}) { }) {
return ( return (
@@ -1,10 +1,10 @@
import React, { useEffect, useState } from 'react'; import { useEffect, useState } from 'react';
import { getApiUrl, getSecretKey } from '../../../config'; import { getApiUrl, getSecretKey } from '../../../config';
import { all_goose_modes, ModeSelectionItem } from './ModeSelectionItem'; import { all_goose_modes, ModeSelectionItem } from './ModeSelectionItem';
import { View } from '../../../App'; import { View, ViewOptions } from '../../../App';
interface ModeSectionProps { interface ModeSectionProps {
setView: (view: View) => void; setView: (view: View, viewOptions?: ViewOptions) => void;
} }
export const ModeSection = ({ setView }: ModeSectionProps) => { export const ModeSection = ({ setView }: ModeSectionProps) => {
@@ -74,6 +74,7 @@ export const ModeSection = ({ setView }: ModeSectionProps) => {
currentMode={currentMode} currentMode={currentMode}
showDescription={true} showDescription={true}
isApproveModeConfigure={false} isApproveModeConfigure={false}
parentView="settings"
setView={setView} setView={setView}
handleModeChange={handleModeChange} handleModeChange={handleModeChange}
/> />
@@ -1,7 +1,7 @@
import React, { useEffect, useState } from 'react'; import { useEffect, useState } from 'react';
import { Gear } from '../../icons'; import { Gear } from '../../icons';
import { ConfigureApproveMode } from './ConfigureApproveMode'; import { ConfigureApproveMode } from './ConfigureApproveMode';
import { View } from '../../../App'; import { View, ViewOptions } from '../../../App';
export interface GooseMode { export interface GooseMode {
key: string; key: string;
@@ -32,47 +32,13 @@ export const all_goose_modes: GooseMode[] = [
}, },
]; ];
export function filterGooseModes(
currentMode: string,
modes: GooseMode[],
previousApproveMode: string
) {
return modes.filter((mode) => {
const approveList = ['approve', 'smart_approve'];
const nonApproveList = ['auto', 'chat'];
// Always keep 'auto' and 'chat'
if (nonApproveList.includes(mode.key)) {
return true;
}
// If current mode is non approve mode, we display write approve by default.
if (nonApproveList.includes(currentMode) && !previousApproveMode) {
return mode.key === 'smart_approve';
}
// Always include the current and previou approve mode
if (mode.key === currentMode) {
return true;
}
// Current mode and previous approve mode cannot exist at the same time.
if (approveList.includes(currentMode) && approveList.includes(previousApproveMode)) {
return false;
}
if (mode.key === previousApproveMode) {
return true;
}
return false;
});
}
interface ModeSelectionItemProps { interface ModeSelectionItemProps {
currentMode: string; currentMode: string;
mode: GooseMode; mode: GooseMode;
showDescription: boolean; showDescription: boolean;
isApproveModeConfigure: boolean; isApproveModeConfigure: boolean;
setView: (view: View) => void; parentView: View;
setView: (view: View, viewOptions?: ViewOptions) => void;
handleModeChange: (newMode: string) => void; handleModeChange: (newMode: string) => void;
} }
@@ -81,6 +47,7 @@ export function ModeSelectionItem({
mode, mode,
showDescription, showDescription,
isApproveModeConfigure, isApproveModeConfigure,
parentView,
setView, setView,
handleModeChange, handleModeChange,
}: ModeSelectionItemProps) { }: ModeSelectionItemProps) {
@@ -112,7 +79,9 @@ export function ModeSelectionItem({
{!isApproveModeConfigure && (mode.key == 'approve' || mode.key == 'smart_approve') && ( {!isApproveModeConfigure && (mode.key == 'approve' || mode.key == 'smart_approve') && (
<button <button
onClick={() => { onClick={() => {
setView('permission'); setView('permission', {
parentView,
});
}} }}
> >
<Gear className="w-5 h-5 text-textSubtle hover:text-textStandard" /> <Gear className="w-5 h-5 text-textSubtle hover:text-textStandard" />
@@ -9,7 +9,6 @@ function RuleItem({ title, description }: { title: string; description: string }
const [isModalOpen, setIsModalOpen] = useState(false); const [isModalOpen, setIsModalOpen] = useState(false);
const handleModalClose = () => { const handleModalClose = () => {
console.log('close modal');
setIsModalOpen(false); setIsModalOpen(false);
}; };