Skip to content

Commit a7aeede

Browse files
committed
Merge branch 'main' into ft/suggestions-and-recommendations
2 parents 95c3808 + 8c8685c commit a7aeede

File tree

25 files changed

+400
-200
lines changed

25 files changed

+400
-200
lines changed

.github/workflows/update-image-digest.yml

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -64,13 +64,14 @@ jobs:
6464
done < <(find "$(pwd)" -type f \( -name "*.yaml" -o -name "*.yml" -o -name "Dockerfile*" -o -name "leeway.Dockerfile" \) -print0)
6565
6666
# update for chainguard redis
67-
# redisImageDigest=$(crane digest cgr.dev/chainguard/redis:latest)
68-
# redisExporterDigest=$(crane digest cgr.dev/chainguard/prometheus-redis-exporter:latest)
69-
70-
71-
# sed -i -e "s/^\(\s*ImageDigest\s*=\s*\)\".*\"/\1\"$redisImageDigest\"/" install/installer/pkg/components/redis/constants.go
72-
# sed -i -e "s/^\(\s*ExporterImageDigest\s*=\s*\)\".*\"/\1\"$redisExporterDigest\"/" install/installer/pkg/components/redis/constants.go
73-
# go fmt install/installer/pkg/components/redis/constants.go
67+
redisImageDigest=$(crane digest cgr.dev/chainguard/redis:latest)
68+
# we switch to the quay.io image for the redis exporter, because cgr.dev/chainguard/prometheus-redis-exporter is not public anymore.
69+
# see detail in https://linear.app/gitpod/issue/CLC-1039/#comment-c90cb270
70+
redisExporterDigest=$(crane digest quay.io/oliver006/redis_exporter:latest)
71+
72+
sed -i -e "s/^\(\s*ImageDigest\s*=\s*\)\".*\"/\1\"$redisImageDigest\"/" install/installer/pkg/components/redis/constants.go
73+
sed -i -e "s/^\(\s*ExporterImageDigest\s*=\s*\)\".*\"/\1\"$redisExporterDigest\"/" install/installer/pkg/components/redis/constants.go
74+
go fmt install/installer/pkg/components/redis/constants.go
7475
- name: Check workspace
7576
id: create_pr
7677
shell: bash

WORKSPACE.yaml

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13,15 +13,15 @@ defaultArgs:
1313
codeWebExtensionCommit: 3953e8160fffa97dd4a4509542b4bf7ff9b704cd
1414
xtermCommit: d547d4ff4590b66c3ea24342fc62e3afcf6b77bc
1515
noVerifyJBPlugin: false
16-
intellijDownloadUrl: "https://download.jetbrains.com/idea/ideaIU-2024.3.tar.gz"
17-
golandDownloadUrl: "https://download.jetbrains.com/go/goland-2024.3.tar.gz"
18-
pycharmDownloadUrl: "https://download.jetbrains.com/python/pycharm-professional-2024.3.tar.gz"
19-
phpstormDownloadUrl: "https://download.jetbrains.com/webide/PhpStorm-2024.3.tar.gz"
20-
rubymineDownloadUrl: "https://download.jetbrains.com/ruby/RubyMine-2024.3.tar.gz"
21-
webstormDownloadUrl: "https://download.jetbrains.com/webstorm/WebStorm-2024.3.tar.gz"
16+
intellijDownloadUrl: "https://download.jetbrains.com/idea/ideaIU-2024.3.1.1.tar.gz"
17+
golandDownloadUrl: "https://download.jetbrains.com/go/goland-2024.3.1.tar.gz"
18+
pycharmDownloadUrl: "https://download.jetbrains.com/python/pycharm-professional-2024.3.1.1.tar.gz"
19+
phpstormDownloadUrl: "https://download.jetbrains.com/webide/PhpStorm-2024.3.1.1.tar.gz"
20+
rubymineDownloadUrl: "https://download.jetbrains.com/ruby/RubyMine-2024.3.1.1.tar.gz"
21+
webstormDownloadUrl: "https://download.jetbrains.com/webstorm/WebStorm-2024.3.1.1.tar.gz"
2222
riderDownloadUrl: "https://download.jetbrains.com/rider/JetBrains.Rider-2024.1.4.tar.gz"
23-
clionDownloadUrl: "https://download.jetbrains.com/cpp/CLion-2024.3.tar.gz"
24-
rustroverDownloadUrl: "https://download.jetbrains.com/rustrover/RustRover-2024.3.tar.gz"
23+
clionDownloadUrl: "https://download.jetbrains.com/cpp/CLion-2024.3.1.1.tar.gz"
24+
rustroverDownloadUrl: "https://download.jetbrains.com/rustrover/RustRover-2024.3.2.tar.gz"
2525
jbBackendVersion: "latest"
2626
dockerVersion: "20.10.24"
2727
dockerComposeVersion: "2.27.0-gitpod.0"
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"typescript.preferences.autoImportFileExcludePatterns": [
3+
"@radix-ui/*"
4+
]
5+
}

components/dashboard/src/Insights.tsx

Lines changed: 47 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ import { Item, ItemField, ItemsList } from "./components/ItemsList";
1515
import { useWorkspaceSessions } from "./data/insights/list-workspace-sessions-query";
1616
import { WorkspaceSessionGroup } from "./insights/WorkspaceSessionGroup";
1717
import { gitpodHostUrl } from "./service/service";
18-
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@podkit/select/Select";
1918
import dayjs from "dayjs";
2019
import { Timestamp } from "@bufbuild/protobuf";
2120
import { LoadingButton } from "@podkit/buttons/LoadingButton";
@@ -26,16 +25,11 @@ import { useToast } from "./components/toasts/Toasts";
2625
import { useTemporaryState } from "./hooks/use-temporary-value";
2726
import { DownloadIcon } from "lucide-react";
2827
import { Button } from "@podkit/buttons/Button";
28+
import { DropdownMenu, DropdownMenuTrigger, DropdownMenuContent, DropdownMenuItem } from "@podkit/dropdown/DropDown";
29+
import { useInstallationConfiguration } from "./data/installation/default-workspace-image-query";
2930

3031
export const Insights = () => {
31-
const [prebuildsFilter, setPrebuildsFilter] = useState<"week" | "month" | "year">("week");
32-
const [upperBound, lowerBound] = useMemo(() => {
33-
const from = dayjs().subtract(1, prebuildsFilter).startOf("day");
34-
35-
const fromTimestamp = Timestamp.fromDate(from.toDate());
36-
const toTimestamp = Timestamp.fromDate(new Date());
37-
return [fromTimestamp, toTimestamp];
38-
}, [prebuildsFilter]);
32+
const toDate = useMemo(() => Timestamp.fromDate(new Date()), []);
3933
const {
4034
data,
4135
error: errorMessage,
@@ -44,9 +38,11 @@ export const Insights = () => {
4438
hasNextPage,
4539
fetchNextPage,
4640
} = useWorkspaceSessions({
47-
from: upperBound,
48-
to: lowerBound,
41+
from: Timestamp.fromDate(new Date(0)),
42+
to: toDate,
4943
});
44+
const { data: installationConfig } = useInstallationConfiguration();
45+
const isDedicatedInstallation = !!installationConfig?.isDedicatedInstallation;
5046

5147
const hasMoreThanOnePage = (data?.pages.length ?? 0) > 1;
5248
const sessions = useMemo(() => data?.pages.flatMap((p) => p) ?? [], [data]);
@@ -59,21 +55,11 @@ export const Insights = () => {
5955
<div className="app-container pt-5 pb-8">
6056
<div
6157
className={classNames(
62-
"flex flex-col items-start space-y-3 justify-between",
58+
"flex flex-col items-start space-y-3 justify-end",
6359
"md:flex-row md:items-center md:space-x-4 md:space-y-0",
6460
)}
6561
>
66-
<Select value={prebuildsFilter} onValueChange={(v) => setPrebuildsFilter(v as any)}>
67-
<SelectTrigger className="w-[180px]">
68-
<SelectValue placeholder="Select time range" />
69-
</SelectTrigger>
70-
<SelectContent>
71-
<SelectItem value="week">Last 7 days</SelectItem>
72-
<SelectItem value="month">Last 30 days</SelectItem>
73-
<SelectItem value="year">Last 365 days</SelectItem>
74-
</SelectContent>
75-
</Select>
76-
<DownloadUsage from={upperBound} to={lowerBound} />
62+
<DownloadUsage to={toDate} />
7763
</div>
7864

7965
<div
@@ -108,7 +94,7 @@ export const Insights = () => {
10894

10995
{isLoading && (
11096
<div className="flex items-center justify-center w-full space-x-2 text-pk-content-primary text-sm pt-16 pb-40">
111-
<LoadingState />
97+
<LoadingState delay={false} />
11298
<span>Loading usage...</span>
11399
</div>
114100
)}
@@ -135,7 +121,7 @@ export const Insights = () => {
135121
{" "}
136122
workspaces
137123
</a>{" "}
138-
in the last 30 days or checked your other organizations?
124+
recently{!isDedicatedInstallation && " or checked your other organizations"}?
139125
</Subheading>
140126
</div>
141127
)}
@@ -164,39 +150,51 @@ export const Insights = () => {
164150
};
165151

166152
type DownloadUsageProps = {
167-
from: Timestamp;
168153
to: Timestamp;
169154
};
170-
export const DownloadUsage = ({ from, to }: DownloadUsageProps) => {
155+
export const DownloadUsage = ({ to }: DownloadUsageProps) => {
171156
const { data: org } = useCurrentOrg();
172157
const { toast } = useToast();
173158
// When we start the download, we disable the button for a short time
174159
const [downloadDisabled, setDownloadDisabled] = useTemporaryState(false, 1000);
175160

176-
const handleDownload = useCallback(async () => {
177-
if (!org) {
178-
return;
179-
}
180-
181-
setDownloadDisabled(true);
182-
toast(
183-
<DownloadInsightsToast
184-
organizationName={org?.slug ?? org?.id}
185-
organizationId={org.id}
186-
from={from}
187-
to={to}
188-
/>,
189-
{
190-
autoHide: false,
191-
},
192-
);
193-
}, [org, setDownloadDisabled, toast, from, to]);
161+
const handleDownload = useCallback(
162+
async ({ daysInPast }: { daysInPast: number }) => {
163+
if (!org) {
164+
return;
165+
}
166+
const from = Timestamp.fromDate(dayjs().subtract(daysInPast, "day").toDate());
167+
168+
setDownloadDisabled(true);
169+
toast(
170+
<DownloadInsightsToast
171+
organizationName={org?.slug ?? org?.id}
172+
organizationId={org.id}
173+
from={from}
174+
to={to}
175+
/>,
176+
{
177+
autoHide: false,
178+
},
179+
);
180+
},
181+
[org, setDownloadDisabled, to, toast],
182+
);
194183

195184
return (
196-
<Button variant="secondary" onClick={handleDownload} className="gap-1" disabled={downloadDisabled}>
197-
<DownloadIcon strokeWidth={3} className="w-4" />
198-
<span>Export as CSV</span>
199-
</Button>
185+
<DropdownMenu>
186+
<DropdownMenuTrigger asChild>
187+
<Button variant="secondary" className="gap-1" disabled={downloadDisabled}>
188+
<DownloadIcon strokeWidth={3} className="w-4" />
189+
<span>Export as CSV</span>
190+
</Button>
191+
</DropdownMenuTrigger>
192+
<DropdownMenuContent>
193+
<DropdownMenuItem onClick={() => handleDownload({ daysInPast: 7 })}>Last 7 days</DropdownMenuItem>
194+
<DropdownMenuItem onClick={() => handleDownload({ daysInPast: 30 })}>Last 30 days</DropdownMenuItem>
195+
<DropdownMenuItem onClick={() => handleDownload({ daysInPast: 365 })}>Last 365 days</DropdownMenuItem>
196+
</DropdownMenuContent>
197+
</DropdownMenu>
200198
);
201199
};
202200

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ const featureFlags = {
2424
showBrowserExtensionPromotion: false,
2525
enable_experimental_jbtb: false,
2626
enabled_configuration_prebuild_full_clone: false,
27+
enterprise_onboarding_enabled: false,
2728
};
2829

2930
type FeatureFlags = typeof featureFlags;

components/dashboard/src/teams/OrgSettingsPage.tsx

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import { useCurrentOrg } from "../data/organizations/orgs-query";
1515
import { useFeatureFlag } from "../data/featureflag-query";
1616
import { Organization } from "@gitpod/public-api/lib/gitpod/v1/organization_pb";
1717
import { useIsOwner } from "../data/organizations/members-query";
18-
import { isGitpodIo } from "../utils";
18+
import { useInstallationConfiguration } from "../data/installation/default-workspace-image-query";
1919

2020
export interface OrgSettingsPageProps {
2121
children: React.ReactNode;
@@ -27,6 +27,9 @@ export function OrgSettingsPage({ children }: OrgSettingsPageProps) {
2727
const orgBillingMode = useOrgBillingMode();
2828
const oidcServiceEnabled = useFeatureFlag("oidcServiceEnabled");
2929
const orgGitAuthProviders = useFeatureFlag("orgGitAuthProviders");
30+
const isOnboardingEnabled = useFeatureFlag("enterprise_onboarding_enabled");
31+
const { data: installationConfig } = useInstallationConfiguration();
32+
const isDedicatedInstallation = !!installationConfig?.isDedicatedInstallation;
3033

3134
const menu = useMemo(
3235
() =>
@@ -36,8 +39,18 @@ export function OrgSettingsPage({ children }: OrgSettingsPageProps) {
3639
ssoEnabled: oidcServiceEnabled,
3740
orgGitAuthProviders,
3841
isOwner,
42+
isDedicatedInstallation,
43+
showOnboarding: isOnboardingEnabled && isDedicatedInstallation,
3944
}),
40-
[org.data, orgBillingMode.data, oidcServiceEnabled, orgGitAuthProviders, isOwner],
45+
[
46+
org.data,
47+
orgBillingMode.data,
48+
oidcServiceEnabled,
49+
orgGitAuthProviders,
50+
isOwner,
51+
isDedicatedInstallation,
52+
isOnboardingEnabled,
53+
],
4154
);
4255

4356
const title = "Organization Settings";
@@ -76,8 +89,10 @@ function getOrgSettingsMenu(params: {
7689
ssoEnabled?: boolean;
7790
orgGitAuthProviders: boolean;
7891
isOwner?: boolean;
92+
showOnboarding?: boolean;
93+
isDedicatedInstallation?: boolean;
7994
}) {
80-
const { billingMode, ssoEnabled, orgGitAuthProviders, isOwner } = params;
95+
const { billingMode, ssoEnabled, orgGitAuthProviders, isOwner, showOnboarding, isDedicatedInstallation } = params;
8196
const result = [
8297
{
8398
title: "General",
@@ -92,7 +107,7 @@ function getOrgSettingsMenu(params: {
92107
link: [`/settings/onboarding`],
93108
},
94109
];
95-
if (isGitpodIo()) {
110+
if (!isDedicatedInstallation) {
96111
result.push(
97112
{
98113
title: "Networking",
@@ -104,6 +119,12 @@ function getOrgSettingsMenu(params: {
104119
},
105120
);
106121
}
122+
if (showOnboarding) {
123+
result.push({
124+
title: "Onboarding",
125+
link: [`/settings/onboarding`],
126+
});
127+
}
107128
if (isOwner && ssoEnabled) {
108129
result.push({
109130
title: "SSO",

components/dashboard/src/teams/TeamOnboarding.tsx

Lines changed: 28 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -72,38 +72,34 @@ export default function TeamOnboardingPage() {
7272
}, [settings]);
7373

7474
return (
75-
<>
76-
<OrgSettingsPage>
77-
<div className="space-y-8">
78-
<div>
79-
<Heading2>Policies</Heading2>
80-
<Subheading>
81-
Restrict workspace classes, editors and sharing across your organization.
82-
</Subheading>
83-
</div>
84-
<ConfigurationSettingsField>
85-
<Heading3>Internal dashboard</Heading3>
86-
<Subheading>
87-
The link to your internal dashboard. This link will be shown to your organization members
88-
during the onboarding process. You can disable showing a link by leaving this field empty.
89-
</Subheading>
90-
<form onSubmit={handleUpdateInternalLink}>
91-
<InputField label="Internal dashboard link" error={undefined} className="mb-4">
92-
<TextInput
93-
value={internalLink}
94-
type="url"
95-
placeholder="https://en.wikipedia.org/wiki/Eurosurveillance"
96-
onChange={setInternalLink}
97-
disabled={updateTeamSettings.isLoading || !isOwner}
98-
/>
99-
</InputField>
100-
<LoadingButton type="submit" loading={updateTeamSettings.isLoading} disabled={!isOwner}>
101-
Save
102-
</LoadingButton>
103-
</form>
104-
</ConfigurationSettingsField>
75+
<OrgSettingsPage>
76+
<div className="space-y-8">
77+
<div>
78+
<Heading2>Policies</Heading2>
79+
<Subheading>Restrict workspace classes, editors and sharing across your organization.</Subheading>
10580
</div>
106-
</OrgSettingsPage>
107-
</>
81+
<ConfigurationSettingsField>
82+
<Heading3>Internal dashboard</Heading3>
83+
<Subheading>
84+
The link to your internal dashboard. This link will be shown to your organization members during
85+
the onboarding process. You can disable showing a link by leaving this field empty.
86+
</Subheading>
87+
<form onSubmit={handleUpdateInternalLink}>
88+
<InputField label="Internal dashboard link" error={undefined} className="mb-4">
89+
<TextInput
90+
value={internalLink}
91+
type="url"
92+
placeholder="https://en.wikipedia.org/wiki/Heisenbug"
93+
onChange={setInternalLink}
94+
disabled={updateTeamSettings.isLoading || !isOwner}
95+
/>
96+
</InputField>
97+
<LoadingButton type="submit" loading={updateTeamSettings.isLoading} disabled={!isOwner}>
98+
Save
99+
</LoadingButton>
100+
</form>
101+
</ConfigurationSettingsField>
102+
</div>
103+
</OrgSettingsPage>
108104
);
109105
}

components/dashboard/src/teams/TeamPolicies.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ import { TextInput } from "../components/forms/TextInputField";
2828
import { LoadingButton } from "@podkit/buttons/LoadingButton";
2929
import { MaxParallelWorkspaces } from "./policies/MaxParallelWorkspaces";
3030
import { WorkspaceClassesEnterpriseCallout } from "./policies/WorkspaceClassesEnterpriseCallout";
31-
import { EditorOptions } from "./EditorOptions";
31+
import { EditorOptions } from "./policies/EditorOptions";
3232
import { RolePermissionsRestrictions } from "./policies/RoleRestrictions";
3333
import { OrgWorkspaceClassesOptions } from "./policies/OrgWorkspaceClassesOptions";
3434

0 commit comments

Comments
 (0)