Skip to content

Commit 8192444

Browse files
authored
[TB] allow to config launcher from Dashboard (#20051)
* [TB] allow to config launcher from dashboard * Control by FF * nit follow up * LImit oauth entry with FF * 💄
1 parent 910b133 commit 8192444

File tree

32 files changed

+394
-34
lines changed

32 files changed

+394
-34
lines changed

components/dashboard/src/data/featureflag-query.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ const featureFlags = {
2727
dashboard_logging_tracing: false,
2828
showBrowserExtensionPromotion: false,
2929
usage_update_scheduler_duration: "15m",
30+
enable_experimental_jbtb: false,
3031
};
3132

3233
type FeatureFlags = typeof featureFlags;

components/dashboard/src/service/service.tsx

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -344,8 +344,15 @@ export class IDEFrontendService implements IDEFrontendDashboardService.IServer {
344344
const desktopLink = new URL(url);
345345
// allow to redirect only for whitelisted trusted protocols
346346
// IDE-69
347-
const trustedProtocols = ["vscode:", "vscode-insiders:", "jetbrains-gateway:"];
347+
const trustedProtocols = ["vscode:", "vscode-insiders:", "jetbrains-gateway:", "jetbrains:"];
348348
redirect = trustedProtocols.includes(desktopLink.protocol);
349+
if (
350+
redirect &&
351+
desktopLink.protocol === "jetbrains:" &&
352+
!desktopLink.href.startsWith("jetbrains://gateway/io.gitpod.toolbox.gateway/")
353+
) {
354+
redirect = false;
355+
}
349356
} catch (e) {
350357
console.error("invalid desktop link:", e);
351358
}

components/dashboard/src/user-settings/SelectIDE.tsx

Lines changed: 38 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ import { useUpdateCurrentUserMutation } from "../data/current-user/update-mutati
1313
import { converter } from "../service/public-api";
1414
import { isOrganizationOwned } from "@gitpod/public-api-common/lib/user-utils";
1515
import Alert from "../components/Alert";
16+
import { useFeatureFlag } from "../data/featureflag-query";
17+
import { IDESettingsVersion } from "@gitpod/gitpod-protocol/lib/ide-protocol";
1618

1719
export type IDEChangedTrackLocation = "workspace_list" | "workspace_start" | "preferences";
1820
interface SelectIDEProps {
@@ -25,18 +27,21 @@ export default function SelectIDE(props: SelectIDEProps) {
2527

2628
const [defaultIde, setDefaultIde] = useState<string>(user?.editorSettings?.name || "code");
2729
const [useLatestVersion, setUseLatestVersion] = useState<boolean>(user?.editorSettings?.version === "latest");
30+
const [preferToolbox, setPreferToolbox] = useState<boolean>(user?.editorSettings?.preferToolbox || false);
2831
const [ideWarning, setIdeWarning] = useState<ReactNode | undefined>(undefined);
32+
const enableExperimentalJBTB = useFeatureFlag("enable_experimental_jbtb");
2933

3034
const isOrgOwnedUser = user && isOrganizationOwned(user);
3135

3236
const actualUpdateUserIDEInfo = useCallback(
33-
async (selectedIde: string, useLatestVersion: boolean) => {
37+
async (selectedIde: string, useLatestVersion: boolean, preferToolbox: boolean) => {
3438
// update stored autostart options to match useLatestVersion value set here
3539
const workspaceAutostartOptions = user?.workspaceAutostartOptions?.map((o) => {
3640
const option = converter.fromWorkspaceAutostartOption(o);
3741

3842
if (option.ideSettings) {
3943
option.ideSettings.useLatestVersion = useLatestVersion;
44+
option.ideSettings.preferToolbox = preferToolbox;
4045
}
4146

4247
return option;
@@ -46,9 +51,10 @@ export default function SelectIDE(props: SelectIDEProps) {
4651
additionalData: {
4752
workspaceAutostartOptions,
4853
ideSettings: {
49-
settingVersion: "2.0",
54+
settingVersion: IDESettingsVersion,
5055
defaultIde: selectedIde,
5156
useLatestVersion: useLatestVersion,
57+
preferToolbox: preferToolbox,
5258
},
5359
},
5460
});
@@ -59,18 +65,26 @@ export default function SelectIDE(props: SelectIDEProps) {
5965

6066
const actuallySetDefaultIde = useCallback(
6167
async (value: string) => {
62-
await actualUpdateUserIDEInfo(value, useLatestVersion);
68+
await actualUpdateUserIDEInfo(value, useLatestVersion, preferToolbox);
6369
setDefaultIde(value);
6470
},
65-
[actualUpdateUserIDEInfo, useLatestVersion],
71+
[actualUpdateUserIDEInfo, useLatestVersion, preferToolbox],
6672
);
6773

6874
const actuallySetUseLatestVersion = useCallback(
6975
async (value: boolean) => {
70-
await actualUpdateUserIDEInfo(defaultIde, value);
76+
await actualUpdateUserIDEInfo(defaultIde, value, preferToolbox);
7177
setUseLatestVersion(value);
7278
},
73-
[actualUpdateUserIDEInfo, defaultIde],
79+
[actualUpdateUserIDEInfo, defaultIde, preferToolbox],
80+
);
81+
82+
const actuallySetPreferToolbox = useCallback(
83+
async (value: boolean) => {
84+
await actualUpdateUserIDEInfo(defaultIde, useLatestVersion, value);
85+
setPreferToolbox(value);
86+
},
87+
[actualUpdateUserIDEInfo, defaultIde, useLatestVersion],
7488
);
7589

7690
const shouldShowJetbrainsNotice = isJetbrains(defaultIde);
@@ -142,6 +156,24 @@ export default function SelectIDE(props: SelectIDEProps) {
142156
checked={useLatestVersion}
143157
onChange={(checked) => actuallySetUseLatestVersion(checked)}
144158
/>
159+
160+
{enableExperimentalJBTB && (
161+
<CheckboxInputField
162+
label={
163+
<span className="flex items-center gap-2">
164+
Launch in JetBrains Toolbox{" "}
165+
<PillLabel type="warn">
166+
<a href="https://www.gitpod.io/docs/references/gitpod-releases">
167+
<span className="text-xs">BETA</span>
168+
</a>
169+
</PillLabel>
170+
</span>
171+
}
172+
hint={<span>Launch JetBrains IDEs in the JetBrains Toolbox.</span>}
173+
checked={preferToolbox}
174+
onChange={(checked) => actuallySetPreferToolbox(checked)}
175+
/>
176+
)}
145177
</>
146178
);
147179
}

components/dashboard/src/workspaces/CreateWorkspacePage.tsx

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,9 @@ export function CreateWorkspacePage() {
8181
props.ideSettings?.useLatestVersion !== undefined
8282
? props.ideSettings.useLatestVersion
8383
: user?.editorSettings?.version === "latest";
84+
const defaultPreferToolbox = props.ideSettings?.preferToolbox ?? user?.editorSettings?.preferToolbox ?? false;
8485
const [useLatestIde, setUseLatestIde] = useState(defaultLatestIde);
86+
const [preferToolbox, setPreferToolbox] = useState(defaultPreferToolbox);
8587
// Note: it has data fetching and UI rendering race between the updating of `selectedProjectId` and `selectedIde`
8688
// We have to stored the using repositoryId locally so that we can know selectedIde is updated because if which repo
8789
// so that it doesn't show ide error messages in middle state
@@ -145,6 +147,7 @@ export function CreateWorkspacePage() {
145147
editorSettings: new EditorReference({
146148
name: selectedIde,
147149
version: useLatestIde ? "latest" : "stable",
150+
preferToolbox: preferToolbox,
148151
}),
149152
}),
150153
);
@@ -156,7 +159,17 @@ export function CreateWorkspacePage() {
156159
},
157160
});
158161
setUser(updatedUser);
159-
}, [updateUser, currentOrg, selectedIde, selectedWsClass, setUser, useLatestIde, user, workspaceContext.data]);
162+
}, [
163+
updateUser,
164+
currentOrg,
165+
selectedIde,
166+
selectedWsClass,
167+
setUser,
168+
useLatestIde,
169+
preferToolbox,
170+
user,
171+
workspaceContext.data,
172+
]);
160173

161174
// see if we have a matching project based on context url and project's repo url
162175
const project = useMemo(() => {
@@ -271,6 +284,7 @@ export function CreateWorkspacePage() {
271284
contextUrlSource.editor = {
272285
name: selectedIde,
273286
version: useLatestIde ? "latest" : undefined,
287+
preferToolbox: preferToolbox,
274288
};
275289
}
276290
opts.source = {
@@ -301,6 +315,7 @@ export function CreateWorkspacePage() {
301315
selectedWsClass,
302316
selectedIde,
303317
useLatestIde,
318+
preferToolbox,
304319
createWorkspaceMutation,
305320
selectedProjectID,
306321
storeAutoStartOptions,
@@ -358,6 +373,7 @@ export function CreateWorkspacePage() {
358373
}
359374
setSelectedIde(rememberedOptions.editorSettings?.name, false);
360375
setUseLatestIde(rememberedOptions.editorSettings?.version === "latest");
376+
setPreferToolbox(rememberedOptions.editorSettings?.preferToolbox || false);
361377
}
362378

363379
if (!selectedWsClassIsDirty) {
@@ -374,6 +390,7 @@ export function CreateWorkspacePage() {
374390
if (!selectedIdeIsDirty) {
375391
setSelectedIde(defaultIde, false);
376392
setUseLatestIde(defaultLatestIde);
393+
setPreferToolbox(defaultPreferToolbox);
377394
}
378395
if (!selectedWsClassIsDirty) {
379396
const projectWsClass = project?.settings?.workspaceClasses?.regular;

components/gitpod-protocol/go/gitpod-service.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2058,6 +2058,7 @@ type IDESettings struct {
20582058
UseDesktopIde bool `json:"useDesktopIde,omitempty"`
20592059
DefaultDesktopIde string `json:"defaultDesktopIde,omitempty"`
20602060
UseLatestVersion bool `json:"useLatestVersion"`
2061+
PreferToolbox bool `json:"preferToolbox"`
20612062
}
20622063

20632064
// EmailNotificationSettings is the EmailNotificationSettings message type

components/gitpod-protocol/src/protocol.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,7 @@ export type IDESettings = {
171171
settingVersion?: string;
172172
defaultIde?: string;
173173
useLatestVersion?: boolean;
174+
preferToolbox?: boolean;
174175
// DEPRECATED: Use defaultIde after `settingVersion: 2.0`, no more specialify desktop or browser.
175176
useDesktopIde?: boolean;
176177
// DEPRECATED: Same with useDesktopIde.

components/gitpod-protocol/src/workspace-instance.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -269,6 +269,7 @@ export namespace WorkspaceInstanceRepoStatus {
269269
export interface ConfigurationIdeConfig {
270270
useLatest?: boolean;
271271
ide?: string;
272+
preferToolbox?: boolean;
272273
}
273274

274275
export interface IdeSetup {

components/ide-service/example-ide-config.json

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,18 @@
129129
"If you don't see an open dialog in your browser, make sure you have the \u003ca target='_blank' class='gp-link' href='https://www.gitpod.io/docs/ides-and-editors/jetbrains-gateway#getting-started-jetbrains-gateway'\u003eJetBrains Gateway with Gitpod Plugin\u003c/a\u003e installed on your machine, and then click \u003cb\u003e${OPEN_LINK_LABEL}\u003c/b\u003e below."
130130
]
131131
},
132+
"jetbrains-toolbox": {
133+
"defaultDesktopIDE": "intellij",
134+
"desktopIDEs": [
135+
"intellij",
136+
"goland",
137+
"pycharm",
138+
"phpstorm"
139+
],
140+
"installationSteps": [
141+
"If you don't see an open dialog in your browser, make sure you have the \u003ca target='_blank' class='gp-link' href='https://www.gitpod.io/docs/ides-and-editors/jetbrains-gateway#getting-started-jetbrains-gateway'\u003eJetBrains Toolbox with Gitpod Plugin\u003c/a\u003e installed on your machine, and then click \u003cb\u003e${OPEN_LINK_LABEL}\u003c/b\u003e below."
142+
]
143+
},
132144
"vscode": {
133145
"defaultDesktopIDE": "code-desktop",
134146
"desktopIDEs": [

components/ide-service/pkg/server/server.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -303,6 +303,7 @@ func grpcProbe(cfg baseserver.ServerConfiguration) func() error {
303303
type IDESettings struct {
304304
DefaultIde string `json:"defaultIde,omitempty"`
305305
UseLatestVersion bool `json:"useLatestVersion,omitempty"`
306+
PreferToolbox bool `json:"preferToolbox,omitempty"`
306307
PinnedIDEversions map[string]string `json:"pinnedIDEversions,omitempty"`
307308
}
308309

@@ -440,12 +441,22 @@ func (s *IDEServiceServer) ResolveWorkspaceConfig(ctx context.Context, req *api.
440441

441442
userIdeName := ""
442443
useLatest := false
444+
preferToolbox := false
443445
resultingIdeName := ideConfig.IdeOptions.DefaultIde
444446
chosenIDE := ideConfig.IdeOptions.Options[resultingIdeName]
445447

446448
if ideSettings != nil {
447449
userIdeName = ideSettings.DefaultIde
448450
useLatest = ideSettings.UseLatestVersion
451+
preferToolbox = ideSettings.PreferToolbox
452+
}
453+
454+
if preferToolbox {
455+
preferToolboxEnv := api.EnvironmentVariable{
456+
Name: "GITPOD_PREFER_TOOLBOX",
457+
Value: "true",
458+
}
459+
resp.Envvars = append(resp.Envvars, &preferToolboxEnv)
449460
}
450461

451462
if userIdeName != "" {
@@ -499,6 +510,7 @@ func (s *IDEServiceServer) ResolveWorkspaceConfig(ctx context.Context, req *api.
499510
resultingIdeSettings := &IDESettings{
500511
DefaultIde: resultingIdeName,
501512
UseLatestVersion: useLatest,
513+
PreferToolbox: preferToolbox,
502514
}
503515

504516
err = enc.Encode(resultingIdeSettings)

0 commit comments

Comments
 (0)