Skip to content

[TB] allow to config launcher from Dashboard #20051

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Jul 19, 2024
Merged
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
1 change: 1 addition & 0 deletions components/dashboard/src/data/featureflag-query.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ const featureFlags = {
dashboard_logging_tracing: false,
showBrowserExtensionPromotion: false,
usage_update_scheduler_duration: "15m",
enable_experimental_jbtb: false,
};

type FeatureFlags = typeof featureFlags;
Expand Down
9 changes: 8 additions & 1 deletion components/dashboard/src/service/service.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -344,8 +344,15 @@ export class IDEFrontendService implements IDEFrontendDashboardService.IServer {
const desktopLink = new URL(url);
// allow to redirect only for whitelisted trusted protocols
// IDE-69
const trustedProtocols = ["vscode:", "vscode-insiders:", "jetbrains-gateway:"];
const trustedProtocols = ["vscode:", "vscode-insiders:", "jetbrains-gateway:", "jetbrains:"];
redirect = trustedProtocols.includes(desktopLink.protocol);
if (
redirect &&
desktopLink.protocol === "jetbrains:" &&
!desktopLink.href.startsWith("jetbrains://gateway/io.gitpod.toolbox.gateway/")
) {
redirect = false;
}
} catch (e) {
console.error("invalid desktop link:", e);
}
Expand Down
44 changes: 38 additions & 6 deletions components/dashboard/src/user-settings/SelectIDE.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ import { useUpdateCurrentUserMutation } from "../data/current-user/update-mutati
import { converter } from "../service/public-api";
import { isOrganizationOwned } from "@gitpod/public-api-common/lib/user-utils";
import Alert from "../components/Alert";
import { useFeatureFlag } from "../data/featureflag-query";
import { IDESettingsVersion } from "@gitpod/gitpod-protocol/lib/ide-protocol";

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

const [defaultIde, setDefaultIde] = useState<string>(user?.editorSettings?.name || "code");
const [useLatestVersion, setUseLatestVersion] = useState<boolean>(user?.editorSettings?.version === "latest");
const [preferToolbox, setPreferToolbox] = useState<boolean>(user?.editorSettings?.preferToolbox || false);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: we can only default on undefined

Suggested change
const [preferToolbox, setPreferToolbox] = useState<boolean>(user?.editorSettings?.preferToolbox || false);
const [preferToolbox, setPreferToolbox] = useState<boolean>(user?.editorSettings?.preferToolbox ?? false);

const [ideWarning, setIdeWarning] = useState<ReactNode | undefined>(undefined);
const enableExperimentalJBTB = useFeatureFlag("enable_experimental_jbtb");

const isOrgOwnedUser = user && isOrganizationOwned(user);

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

if (option.ideSettings) {
option.ideSettings.useLatestVersion = useLatestVersion;
option.ideSettings.preferToolbox = preferToolbox;
}

return option;
Expand All @@ -46,9 +51,10 @@ export default function SelectIDE(props: SelectIDEProps) {
additionalData: {
workspaceAutostartOptions,
ideSettings: {
settingVersion: "2.0",
settingVersion: IDESettingsVersion,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nice!

defaultIde: selectedIde,
useLatestVersion: useLatestVersion,
preferToolbox: preferToolbox,
},
},
});
Expand All @@ -59,18 +65,26 @@ export default function SelectIDE(props: SelectIDEProps) {

const actuallySetDefaultIde = useCallback(
async (value: string) => {
await actualUpdateUserIDEInfo(value, useLatestVersion);
await actualUpdateUserIDEInfo(value, useLatestVersion, preferToolbox);
setDefaultIde(value);
},
[actualUpdateUserIDEInfo, useLatestVersion],
[actualUpdateUserIDEInfo, useLatestVersion, preferToolbox],
);

const actuallySetUseLatestVersion = useCallback(
async (value: boolean) => {
await actualUpdateUserIDEInfo(defaultIde, value);
await actualUpdateUserIDEInfo(defaultIde, value, preferToolbox);
setUseLatestVersion(value);
},
[actualUpdateUserIDEInfo, defaultIde],
[actualUpdateUserIDEInfo, defaultIde, preferToolbox],
);

const actuallySetPreferToolbox = useCallback(
async (value: boolean) => {
await actualUpdateUserIDEInfo(defaultIde, useLatestVersion, value);
setPreferToolbox(value);
},
[actualUpdateUserIDEInfo, defaultIde, useLatestVersion],
);

const shouldShowJetbrainsNotice = isJetbrains(defaultIde);
Expand Down Expand Up @@ -142,6 +156,24 @@ export default function SelectIDE(props: SelectIDEProps) {
checked={useLatestVersion}
onChange={(checked) => actuallySetUseLatestVersion(checked)}
/>

{enableExperimentalJBTB && (
<CheckboxInputField
label={
<span className="flex items-center gap-2">
Launch in JetBrains Toolbox{" "}
<PillLabel type="warn">
<a href="https://www.gitpod.io/docs/references/gitpod-releases">
<span className="text-xs">BETA</span>
</a>
</PillLabel>
</span>
}
hint={<span>Launch JetBrains IDEs in the JetBrains Toolbox.</span>}
checked={preferToolbox}
onChange={(checked) => actuallySetPreferToolbox(checked)}
/>
)}
</>
);
}
19 changes: 18 additions & 1 deletion components/dashboard/src/workspaces/CreateWorkspacePage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,9 @@ export function CreateWorkspacePage() {
props.ideSettings?.useLatestVersion !== undefined
? props.ideSettings.useLatestVersion
: user?.editorSettings?.version === "latest";
const defaultPreferToolbox = props.ideSettings?.preferToolbox ?? user?.editorSettings?.preferToolbox ?? false;
const [useLatestIde, setUseLatestIde] = useState(defaultLatestIde);
const [preferToolbox, setPreferToolbox] = useState(defaultPreferToolbox);
// Note: it has data fetching and UI rendering race between the updating of `selectedProjectId` and `selectedIde`
// We have to stored the using repositoryId locally so that we can know selectedIde is updated because if which repo
// so that it doesn't show ide error messages in middle state
Expand Down Expand Up @@ -145,6 +147,7 @@ export function CreateWorkspacePage() {
editorSettings: new EditorReference({
name: selectedIde,
version: useLatestIde ? "latest" : "stable",
preferToolbox: preferToolbox,
}),
}),
);
Expand All @@ -156,7 +159,17 @@ export function CreateWorkspacePage() {
},
});
setUser(updatedUser);
}, [updateUser, currentOrg, selectedIde, selectedWsClass, setUser, useLatestIde, user, workspaceContext.data]);
}, [
updateUser,
currentOrg,
selectedIde,
selectedWsClass,
setUser,
useLatestIde,
preferToolbox,
user,
workspaceContext.data,
]);

// see if we have a matching project based on context url and project's repo url
const project = useMemo(() => {
Expand Down Expand Up @@ -271,6 +284,7 @@ export function CreateWorkspacePage() {
contextUrlSource.editor = {
name: selectedIde,
version: useLatestIde ? "latest" : undefined,
preferToolbox: preferToolbox,
};
}
opts.source = {
Expand Down Expand Up @@ -301,6 +315,7 @@ export function CreateWorkspacePage() {
selectedWsClass,
selectedIde,
useLatestIde,
preferToolbox,
createWorkspaceMutation,
selectedProjectID,
storeAutoStartOptions,
Expand Down Expand Up @@ -358,6 +373,7 @@ export function CreateWorkspacePage() {
}
setSelectedIde(rememberedOptions.editorSettings?.name, false);
setUseLatestIde(rememberedOptions.editorSettings?.version === "latest");
setPreferToolbox(rememberedOptions.editorSettings?.preferToolbox || false);
}

if (!selectedWsClassIsDirty) {
Expand All @@ -374,6 +390,7 @@ export function CreateWorkspacePage() {
if (!selectedIdeIsDirty) {
setSelectedIde(defaultIde, false);
setUseLatestIde(defaultLatestIde);
setPreferToolbox(defaultPreferToolbox);
}
if (!selectedWsClassIsDirty) {
const projectWsClass = project?.settings?.workspaceClasses?.regular;
Expand Down
1 change: 1 addition & 0 deletions components/gitpod-protocol/go/gitpod-service.go
Original file line number Diff line number Diff line change
Expand Up @@ -2058,6 +2058,7 @@ type IDESettings struct {
UseDesktopIde bool `json:"useDesktopIde,omitempty"`
DefaultDesktopIde string `json:"defaultDesktopIde,omitempty"`
UseLatestVersion bool `json:"useLatestVersion"`
PreferToolbox bool `json:"preferToolbox"`
}

// EmailNotificationSettings is the EmailNotificationSettings message type
Expand Down
1 change: 1 addition & 0 deletions components/gitpod-protocol/src/protocol.ts
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,7 @@ export type IDESettings = {
settingVersion?: string;
defaultIde?: string;
useLatestVersion?: boolean;
preferToolbox?: boolean;
// DEPRECATED: Use defaultIde after `settingVersion: 2.0`, no more specialify desktop or browser.
useDesktopIde?: boolean;
// DEPRECATED: Same with useDesktopIde.
Expand Down
1 change: 1 addition & 0 deletions components/gitpod-protocol/src/workspace-instance.ts
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,7 @@ export namespace WorkspaceInstanceRepoStatus {
export interface ConfigurationIdeConfig {
useLatest?: boolean;
ide?: string;
preferToolbox?: boolean;
}

export interface IdeSetup {
Expand Down
12 changes: 12 additions & 0 deletions components/ide-service/example-ide-config.json
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,18 @@
"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."
]
},
"jetbrains-toolbox": {
"defaultDesktopIDE": "intellij",
"desktopIDEs": [
"intellij",
"goland",
"pycharm",
"phpstorm"
],
"installationSteps": [
"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."
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Draft changes, will update in the future

]
},
"vscode": {
"defaultDesktopIDE": "code-desktop",
"desktopIDEs": [
Expand Down
12 changes: 12 additions & 0 deletions components/ide-service/pkg/server/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -303,6 +303,7 @@ func grpcProbe(cfg baseserver.ServerConfiguration) func() error {
type IDESettings struct {
DefaultIde string `json:"defaultIde,omitempty"`
UseLatestVersion bool `json:"useLatestVersion,omitempty"`
PreferToolbox bool `json:"preferToolbox,omitempty"`
PinnedIDEversions map[string]string `json:"pinnedIDEversions,omitempty"`
}

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

userIdeName := ""
useLatest := false
preferToolbox := false
resultingIdeName := ideConfig.IdeOptions.DefaultIde
chosenIDE := ideConfig.IdeOptions.Options[resultingIdeName]

if ideSettings != nil {
userIdeName = ideSettings.DefaultIde
useLatest = ideSettings.UseLatestVersion
preferToolbox = ideSettings.PreferToolbox
}

if preferToolbox {
preferToolboxEnv := api.EnvironmentVariable{
Name: "GITPOD_PREFER_TOOLBOX",
Value: "true",
}
resp.Envvars = append(resp.Envvars, &preferToolboxEnv)
}

if userIdeName != "" {
Expand Down Expand Up @@ -499,6 +510,7 @@ func (s *IDEServiceServer) ResolveWorkspaceConfig(ctx context.Context, req *api.
resultingIdeSettings := &IDESettings{
DefaultIde: resultingIdeName,
UseLatestVersion: useLatest,
PreferToolbox: preferToolbox,
}

err = enc.Encode(resultingIdeSettings)
Expand Down
Loading
Loading