Skip to content

Commit 71f5dda

Browse files
authoredMar 21, 2025··
Merge pull request #4757 from continuedev/tomasz/fix-accounts-bug
Fix accounts bug
2 parents 5167899 + d9eb118 commit 71f5dda

File tree

3 files changed

+155
-178
lines changed

3 files changed

+155
-178
lines changed
 

‎core/config/ConfigHandler.ts

-10
Original file line numberDiff line numberDiff line change
@@ -387,16 +387,6 @@ export class ConfigHandler {
387387
this.ideSettingsPromise,
388388
);
389389

390-
// After login, default to the first org as the selected org
391-
try {
392-
const orgs = await this.controlPlaneClient.listOrganizations();
393-
if (orgs.length) {
394-
await this.setSelectedOrgId(orgs[0].id);
395-
}
396-
} catch (e) {
397-
console.error("Failed to fetch control plane profiles: ", e);
398-
}
399-
400390
this.fetchControlPlaneProfiles().catch(async (e) => {
401391
console.error("Failed to fetch control plane profiles: ", e);
402392
await this.loadLocalProfilesOnly();
+150
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
import { Listbox, Transition } from "@headlessui/react";
2+
import {
3+
ArrowTopRightOnSquareIcon,
4+
ChevronUpDownIcon,
5+
PlusCircleIcon,
6+
} from "@heroicons/react/24/outline";
7+
import { Fragment, useContext } from "react";
8+
import AssistantIcon from "../../components/modelSelection/platform/AssistantIcon";
9+
import { useAuth } from "../../context/Auth";
10+
import { IdeMessengerContext } from "../../context/IdeMessenger";
11+
import { useAppDispatch } from "../../redux/hooks";
12+
import { selectProfileThunk } from "../../redux/thunks/profileAndOrg";
13+
import { ScopeSelect } from "./ScopeSelect";
14+
15+
export function AccountManagement({ hubEnabled }: { hubEnabled: boolean }) {
16+
const dispatch = useAppDispatch();
17+
const ideMessenger = useContext(IdeMessengerContext);
18+
19+
const { session, login, profiles, selectedProfile, selectedOrganization } =
20+
useAuth();
21+
22+
const changeProfileId = (id: string) => {
23+
dispatch(selectProfileThunk(id));
24+
};
25+
26+
function handleOpenConfig() {
27+
if (!selectedProfile) {
28+
return;
29+
}
30+
ideMessenger.post("config/openProfile", {
31+
profileId: selectedProfile.id,
32+
});
33+
}
34+
35+
return (
36+
<div className="flex flex-col">
37+
<div className="flex max-w-[400px] flex-col gap-4 py-6">
38+
<h2 className="mb-1 mt-0">Configuration</h2>
39+
{hubEnabled ? (
40+
// Hub: show org selector
41+
session && (
42+
<div className="flex flex-col gap-1.5">
43+
<span className="text-lightgray text-sm">{`Organization`}</span>
44+
<ScopeSelect />
45+
</div>
46+
)
47+
) : (
48+
// Continue for teams: show org text
49+
<div>You are using Continue for Teams</div>
50+
)}
51+
52+
{profiles ? (
53+
<>
54+
<div className="flex flex-col gap-1.5">
55+
<div className="flex items-center justify-between gap-1.5 text-sm">
56+
<span className="text-lightgray">{`${hubEnabled ? "Assistant" : "Profile"}`}</span>
57+
</div>
58+
<Listbox value={selectedProfile?.id} onChange={changeProfileId}>
59+
{({ open }) => (
60+
<div className="relative w-full">
61+
<Listbox.Button className="border-vsc-input-border bg-vsc-background hover:bg-vsc-input-background text-vsc-foreground relative m-0 flex w-full cursor-pointer items-center justify-between rounded-md border border-solid px-3 py-2 text-left">
62+
<div className="flex items-center gap-2">
63+
{selectedProfile && (
64+
<AssistantIcon assistant={selectedProfile} />
65+
)}
66+
<span className="lines lines-1">
67+
{selectedProfile?.title ?? "No Assistant Selected"}
68+
</span>
69+
</div>
70+
<div className="pointer-events-none flex items-center">
71+
<ChevronUpDownIcon
72+
className="h-5 w-5"
73+
aria-hidden="true"
74+
/>
75+
</div>
76+
</Listbox.Button>
77+
78+
<Transition
79+
as={Fragment}
80+
show={open}
81+
enter="transition ease-out duration-100"
82+
enterFrom="transform opacity-0 scale-95"
83+
enterTo="transform opacity-100 scale-100"
84+
leave="transition ease-in duration-75"
85+
leaveFrom="transform opacity-100 scale-100"
86+
leaveTo="transform opacity-0 scale-95"
87+
>
88+
<Listbox.Options className="bg-vsc-background max-h-80vh absolute z-50 mt-0.5 w-full overflow-y-scroll rounded-sm p-0">
89+
{profiles.map((option, idx) => (
90+
<Listbox.Option
91+
key={idx}
92+
value={option.id}
93+
className={`text-vsc-foreground hover:text-list-active-foreground flex cursor-pointer flex-row items-center gap-3 px-3 py-2 ${selectedProfile?.id === option.id ? "bg-list-active" : "bg-vsc-input-background"}`}
94+
>
95+
<AssistantIcon assistant={option} />
96+
<span className="lines lines-1 relative flex h-5 items-center justify-between gap-3 pr-2 text-xs">
97+
{option.title}
98+
</span>
99+
</Listbox.Option>
100+
))}
101+
{hubEnabled && (
102+
<Listbox.Option
103+
key={"no-profiles"}
104+
value={null}
105+
className={`text-vsc-foreground hover:bg-list-active bg-vsc-input-background flex cursor-pointer flex-row items-center gap-2 px-3 py-2`}
106+
onClick={() => {
107+
if (session) {
108+
ideMessenger.post("controlPlane/openUrl", {
109+
path: "new",
110+
orgSlug: selectedOrganization?.slug,
111+
});
112+
} else {
113+
login(false);
114+
}
115+
}}
116+
>
117+
<PlusCircleIcon className="h-4 w-4" />
118+
<span className="lines lines-1 flex items-center justify-between text-xs">
119+
Create new Assistant
120+
</span>
121+
</Listbox.Option>
122+
)}
123+
</Listbox.Options>
124+
</Transition>
125+
126+
{selectedProfile && (
127+
<div className="mt-3 flex w-full justify-center">
128+
<span
129+
className="text-lightgray flex cursor-pointer items-center gap-1 hover:underline"
130+
onClick={handleOpenConfig}
131+
>
132+
<ArrowTopRightOnSquareIcon className="h-4 w-4" />
133+
{hubEnabled
134+
? "Open Assistant configuration"
135+
: "View Workspace"}
136+
</span>
137+
</div>
138+
)}
139+
</div>
140+
)}
141+
</Listbox>
142+
</div>
143+
</>
144+
) : (
145+
<div>Loading...</div>
146+
)}
147+
</div>
148+
</div>
149+
);
150+
}

‎gui/src/pages/config/index.tsx

+5-168
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,16 @@
11
import { ModelRole } from "@continuedev/config-yaml";
2-
import { Listbox, Transition } from "@headlessui/react";
3-
import {
4-
ArrowTopRightOnSquareIcon,
5-
CheckIcon,
6-
ChevronUpDownIcon,
7-
PlusCircleIcon,
8-
XMarkIcon,
9-
} from "@heroicons/react/24/outline";
2+
import { CheckIcon, XMarkIcon } from "@heroicons/react/24/outline";
103
import { ModelDescription } from "core";
114
import {
125
SharedConfigSchema,
136
modifyAnyConfigWithSharedConfig,
147
} from "core/config/sharedConfig";
15-
import { Fragment, useContext, useEffect, useState } from "react";
8+
import { useContext, useEffect, useState } from "react";
169
import { useNavigate } from "react-router-dom";
1710
import { Input } from "../../components";
1811
import NumberInput from "../../components/gui/NumberInput";
1912
import { Select } from "../../components/gui/Select";
2013
import ToggleSwitch from "../../components/gui/Switch";
21-
import AssistantIcon from "../../components/modelSelection/platform/AssistantIcon";
2214
import PageHeader from "../../components/PageHeader";
2315
import { useAuth } from "../../context/Auth";
2416
import { IdeMessengerContext } from "../../context/IdeMessenger";
@@ -29,31 +21,18 @@ import {
2921
setDefaultModel,
3022
updateConfig,
3123
} from "../../redux/slices/configSlice";
32-
import { selectProfileThunk } from "../../redux/thunks/profileAndOrg";
3324
import { getFontSize, isJetBrains } from "../../util";
3425
import { AccountButton } from "./AccountButton";
26+
import { AccountManagement } from "./AccountManagement";
3527
import ModelRoleSelector from "./ModelRoleSelector";
36-
import { ScopeSelect } from "./ScopeSelect";
3728

3829
function ConfigPage() {
3930
useNavigationListener();
4031
const dispatch = useAppDispatch();
4132
const navigate = useNavigate();
4233
const ideMessenger = useContext(IdeMessengerContext);
4334

44-
const {
45-
session,
46-
logout,
47-
login,
48-
profiles,
49-
selectedProfile,
50-
controlServerBetaEnabled,
51-
selectedOrganization,
52-
} = useAuth();
53-
54-
const changeProfileId = (id: string) => {
55-
dispatch(selectProfileThunk(id));
56-
};
35+
const { selectedProfile, controlServerBetaEnabled } = useAuth();
5736

5837
const [hubEnabled, setHubEnabled] = useState(false);
5938
useEffect(() => {
@@ -62,15 +41,6 @@ function ConfigPage() {
6241
});
6342
}, [ideMessenger]);
6443

65-
function handleOpenConfig() {
66-
if (!selectedProfile) {
67-
return;
68-
}
69-
ideMessenger.post("config/openProfile", {
70-
profileId: selectedProfile.id,
71-
});
72-
}
73-
7444
// NOTE Hub takes priority over Continue for Teams
7545
// Since teams will be moving to hub, not vice versa
7646

@@ -161,23 +131,6 @@ function ConfigPage() {
161131
setFormDisableAutocomplete(disableAutocompleteInFiles);
162132
}, [disableAutocompleteInFiles]);
163133

164-
// Workspace prompts
165-
const promptPath = config.experimental?.promptPath || "";
166-
const [formPromptPath, setFormPromptPath] = useState(promptPath);
167-
const cancelChangePromptPath = () => {
168-
setFormPromptPath(promptPath);
169-
};
170-
const handleSubmitPromptPath = () => {
171-
handleUpdate({
172-
promptPath: formPromptPath || "",
173-
});
174-
};
175-
176-
useEffect(() => {
177-
// Necessary so that reformatted/trimmed values don't cause dirty state
178-
setFormPromptPath(promptPath);
179-
}, [promptPath]);
180-
181134
const jetbrains = isJetBrains();
182135

183136
return (
@@ -190,123 +143,7 @@ function ConfigPage() {
190143
/>
191144

192145
<div className="divide-x-0 divide-y-2 divide-solid divide-zinc-700 px-4">
193-
<div className="flex flex-col">
194-
<div className="flex max-w-[400px] flex-col gap-4 py-6">
195-
<h2 className="mb-1 mt-0">Configuration</h2>
196-
{hubEnabled ? (
197-
// Hub: show org selector
198-
session && (
199-
<div className="flex flex-col gap-1.5">
200-
<span className="text-lightgray text-sm">{`Organization`}</span>
201-
<ScopeSelect />
202-
</div>
203-
)
204-
) : (
205-
// Continue for teams: show org text
206-
<div>You are using Continue for Teams</div>
207-
)}
208-
209-
{profiles ? (
210-
<>
211-
<div className="flex flex-col gap-1.5">
212-
<div className="flex items-center justify-between gap-1.5 text-sm">
213-
<span className="text-lightgray">{`${hubEnabled ? "Assistant" : "Profile"}`}</span>
214-
</div>
215-
<Listbox
216-
value={selectedProfile?.id}
217-
onChange={changeProfileId}
218-
>
219-
{({ open }) => (
220-
<div className="relative w-full">
221-
<Listbox.Button className="border-vsc-input-border bg-vsc-background hover:bg-vsc-input-background text-vsc-foreground relative m-0 flex w-full cursor-pointer items-center justify-between rounded-md border border-solid px-3 py-2 text-left">
222-
<div className="flex items-center gap-2">
223-
{selectedProfile && (
224-
<AssistantIcon assistant={selectedProfile} />
225-
)}
226-
<span className="lines lines-1">
227-
{selectedProfile?.title ??
228-
"No Assistant Selected"}
229-
</span>
230-
</div>
231-
<div className="pointer-events-none flex items-center">
232-
<ChevronUpDownIcon
233-
className="h-5 w-5"
234-
aria-hidden="true"
235-
/>
236-
</div>
237-
</Listbox.Button>
238-
239-
<Transition
240-
as={Fragment}
241-
show={open}
242-
enter="transition ease-out duration-100"
243-
enterFrom="transform opacity-0 scale-95"
244-
enterTo="transform opacity-100 scale-100"
245-
leave="transition ease-in duration-75"
246-
leaveFrom="transform opacity-100 scale-100"
247-
leaveTo="transform opacity-0 scale-95"
248-
>
249-
<Listbox.Options className="bg-vsc-background max-h-80vh absolute z-50 mt-0.5 w-full overflow-y-scroll rounded-sm p-0">
250-
{profiles.map((option, idx) => (
251-
<Listbox.Option
252-
key={idx}
253-
value={option.id}
254-
className={`text-vsc-foreground hover:text-list-active-foreground flex cursor-pointer flex-row items-center gap-3 px-3 py-2 ${selectedProfile?.id === option.id ? "bg-list-active" : "bg-vsc-input-background"}`}
255-
>
256-
<AssistantIcon assistant={option} />
257-
<span className="lines lines-1 relative flex h-5 items-center justify-between gap-3 pr-2 text-xs">
258-
{option.title}
259-
</span>
260-
</Listbox.Option>
261-
))}
262-
{hubEnabled && (
263-
<Listbox.Option
264-
key={"no-profiles"}
265-
value={null}
266-
className={`text-vsc-foreground hover:bg-list-active bg-vsc-input-background flex cursor-pointer flex-row items-center gap-2 px-3 py-2`}
267-
onClick={() => {
268-
if (session) {
269-
ideMessenger.post("controlPlane/openUrl", {
270-
path: "new",
271-
orgSlug: selectedOrganization?.slug,
272-
});
273-
} else {
274-
login(false);
275-
}
276-
}}
277-
>
278-
<PlusCircleIcon className="h-4 w-4" />
279-
<span className="lines lines-1 flex items-center justify-between text-xs">
280-
Create new Assistant
281-
</span>
282-
</Listbox.Option>
283-
)}
284-
</Listbox.Options>
285-
</Transition>
286-
287-
{selectedProfile && (
288-
<div className="mt-3 flex w-full justify-center">
289-
<span
290-
className="text-lightgray flex cursor-pointer items-center gap-1 hover:underline"
291-
onClick={handleOpenConfig}
292-
>
293-
<ArrowTopRightOnSquareIcon className="h-4 w-4" />
294-
{hubEnabled
295-
? "Open Assistant configuration"
296-
: "View Workspace"}
297-
</span>
298-
</div>
299-
)}
300-
</div>
301-
)}
302-
</Listbox>
303-
</div>
304-
</>
305-
) : (
306-
<div>Loading...</div>
307-
)}
308-
</div>
309-
</div>
146+
<AccountManagement hubEnabled={hubEnabled} />
310147

311148
{/* Model Roles as a separate section */}
312149
<div className="flex flex-col">

0 commit comments

Comments
 (0)
Please sign in to comment.