Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit67e4024

Browse files
feat: add extra workspace actions in the workspaces table (#17775)
**Demo:**<img width="1624" alt="Screenshot 2025-05-12 at 16 53 36"src="https://github.com/user-attachments/assets/7f125b31-5ce8-4c1f-8e26-c3136346cae3"/>
1 parent60762d4 commit67e4024

File tree

37 files changed

+599
-517
lines changed

37 files changed

+599
-517
lines changed

‎site/src/api/api.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -482,10 +482,10 @@ class ApiMethods {
482482
returnresponse.data;
483483
};
484484

485-
checkAuthorization=async(
485+
checkAuthorization=async<TResponseextendsTypesGen.AuthorizationResponse>(
486486
params:TypesGen.AuthorizationRequest,
487-
):Promise<TypesGen.AuthorizationResponse>=>{
488-
constresponse=awaitthis.axios.post<TypesGen.AuthorizationResponse>(
487+
)=>{
488+
constresponse=awaitthis.axios.post<TResponse>(
489489
"/api/v2/authcheck",
490490
params,
491491
);

‎site/src/api/queries/authCheck.ts

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,19 @@
11
import{API}from"api/api";
2-
importtype{AuthorizationRequest}from"api/typesGenerated";
2+
importtype{
3+
AuthorizationRequest,
4+
AuthorizationResponse,
5+
}from"api/typesGenerated";
36

47
constAUTHORIZATION_KEY="authorization";
58

69
exportconstgetAuthorizationKey=(req:AuthorizationRequest)=>
710
[AUTHORIZATION_KEY,req]asconst;
811

9-
exportconstcheckAuthorization=(req:AuthorizationRequest)=>{
12+
exportconstcheckAuthorization=<TResponseextendsAuthorizationResponse>(
13+
req:AuthorizationRequest,
14+
)=>{
1015
return{
1116
queryKey:getAuthorizationKey(req),
12-
queryFn:()=>API.checkAuthorization(req),
17+
queryFn:()=>API.checkAuthorization<TResponse>(req),
1318
};
1419
};

‎site/src/api/queries/deployment.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ export const deploymentConfig = () => {
66
return{
77
queryKey:deploymentConfigQueryKey,
88
queryFn:API.getDeploymentConfig,
9+
staleTime:Number.POSITIVE_INFINITY,
910
};
1011
};
1112

‎site/src/api/queries/templates.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -139,9 +139,14 @@ export const templateVersionByName = (
139139
};
140140
};
141141

142+
exportconsttemplateVersionsQueryKey=(templateId:string)=>[
143+
"templateVersions",
144+
templateId,
145+
];
146+
142147
exportconsttemplateVersions=(templateId:string)=>{
143148
return{
144-
queryKey:["templateVersions",templateId],
149+
queryKey:templateVersionsQueryKey(templateId),
145150
queryFn:()=>API.getTemplateVersions(templateId),
146151
};
147152
};

‎site/src/api/queries/workspaces.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,17 @@ import type {
1111
WorkspacesResponse,
1212
}from"api/typesGenerated";
1313
importtype{Dayjs}from"dayjs";
14+
import{
15+
typeWorkspacePermissions,
16+
workspaceChecks,
17+
}from"modules/workspaces/permissions";
1418
importtype{ConnectionStatus}from"pages/TerminalPage/types";
1519
importtype{
1620
QueryClient,
1721
QueryOptions,
1822
UseMutationOptions,
1923
}from"react-query";
24+
import{checkAuthorization}from"./authCheck";
2025
import{disabledRefetchOptions}from"./util";
2126
import{workspaceBuildsKey}from"./workspaceBuilds";
2227

@@ -390,3 +395,14 @@ export const workspaceUsage = (options: WorkspaceUsageOptions) => {
390395
refetchIntervalInBackground:true,
391396
};
392397
};
398+
399+
exportconstworkspacePermissions=(workspace?:Workspace)=>{
400+
return{
401+
...checkAuthorization<WorkspacePermissions>({
402+
checks:workspace ?workspaceChecks(workspace) :{},
403+
}),
404+
queryKey:["workspaces",workspace?.id,"permissions"],
405+
enabled:!!workspace,
406+
staleTime:Number.POSITIVE_INFINITY,
407+
};
408+
};

‎site/src/components/DropdownMenu/DropdownMenu.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ export const DropdownMenuItem = forwardRef<
111111
[
112112
"relative flex cursor-default select-none items-center gap-2 rounded-sm px-2 py-2 text-sm text-content-secondary font-medium outline-none transition-colors",
113113
"focus:bg-surface-secondary focus:text-content-primary data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
114-
"[&>svg]:size-4 [&>svg]:shrink-0",
114+
"[&>svg]:size-4 [&>svg]:shrink-0 no-underline",
115115
inset&&"pl-8",
116116
],
117117
className,
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
importtype{Meta,StoryObj}from"@storybook/react";
2+
import{templateVersionsQueryKey}from"api/queries/templates";
3+
import{
4+
MockTemplateVersion,
5+
MockTemplateVersionWithMarkdownMessage,
6+
MockWorkspace,
7+
}from"testHelpers/entities";
8+
import{ChangeWorkspaceVersionDialog}from"./ChangeWorkspaceVersionDialog";
9+
10+
constnoMessage={
11+
...MockTemplateVersion,
12+
name:"no-message",
13+
id:"no-message",
14+
message:"",
15+
};
16+
17+
constmeta:Meta<typeofChangeWorkspaceVersionDialog>={
18+
title:"modules/workspaces/ChangeWorkspaceVersionDialog",
19+
component:ChangeWorkspaceVersionDialog,
20+
args:{
21+
open:true,
22+
workspace:MockWorkspace,
23+
},
24+
parameters:{
25+
queries:[
26+
{
27+
key:templateVersionsQueryKey(MockWorkspace.template_id),
28+
data:[
29+
MockTemplateVersion,
30+
MockTemplateVersionWithMarkdownMessage,
31+
noMessage,
32+
],
33+
},
34+
],
35+
},
36+
};
37+
38+
exportdefaultmeta;
39+
typeStory=StoryObj<typeofChangeWorkspaceVersionDialog>;
40+
41+
exportconstCurrentVersion:Story={};
42+
43+
exportconstNoMessage:Story={
44+
args:{
45+
workspace:{
46+
...MockWorkspace,
47+
latest_build:{
48+
...MockWorkspace.latest_build,
49+
template_version_id:noMessage.id,
50+
},
51+
},
52+
},
53+
};
54+
55+
exportconstTextMessage:Story={
56+
args:{
57+
workspace:{
58+
...MockWorkspace,
59+
latest_build:{
60+
...MockWorkspace.latest_build,
61+
template_version_id:MockTemplateVersion.id,
62+
},
63+
},
64+
},
65+
};
66+
67+
exportconstMarkdownMessage:Story={
68+
args:{
69+
workspace:{
70+
...MockWorkspace,
71+
latest_build:{
72+
...MockWorkspace.latest_build,
73+
template_version_id:MockTemplateVersionWithMarkdownMessage.id,
74+
},
75+
},
76+
},
77+
};

‎site/src/pages/WorkspacePage/ChangeVersionDialog.tsxrenamed to‎site/src/modules/workspaces/WorkspaceMoreActions/ChangeWorkspaceVersionDialog.tsx

Lines changed: 32 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@ import AlertTitle from "@mui/material/AlertTitle";
33
importAutocompletefrom"@mui/material/Autocomplete";
44
importCircularProgressfrom"@mui/material/CircularProgress";
55
importTextFieldfrom"@mui/material/TextField";
6-
importtype{Template,TemplateVersion}from"api/typesGenerated";
6+
import{templateVersions}from"api/queries/templates";
7+
importtype{TemplateVersion,Workspace}from"api/typesGenerated";
78
import{Alert}from"components/Alert/Alert";
89
import{Avatar}from"components/Avatar/Avatar";
910
import{AvatarData}from"components/Avatar/AvatarData";
@@ -15,41 +16,38 @@ import { Pill } from "components/Pill/Pill";
1516
import{Stack}from"components/Stack/Stack";
1617
import{InfoIcon}from"lucide-react";
1718
import{TemplateUpdateMessage}from"modules/templates/TemplateUpdateMessage";
18-
import{typeFC,useRef,useState}from"react";
19+
import{typeFC,useState}from"react";
20+
import{useQuery}from"react-query";
1921
import{createDayString}from"utils/createDayString";
2022

21-
exporttypeChangeVersionDialogProps=DialogProps&{
22-
template:Template|undefined;
23-
templateVersions:TemplateVersion[]|undefined;
24-
defaultTemplateVersion:TemplateVersion|undefined;
23+
exporttypeChangeWorkspaceVersionDialogProps=DialogProps&{
24+
workspace:Workspace;
2525
onClose:()=>void;
26-
onConfirm:(templateVersion:TemplateVersion)=>void;
26+
onConfirm:(version:TemplateVersion)=>void;
2727
};
2828

29-
exportconstChangeVersionDialog:FC<ChangeVersionDialogProps>=({
30-
onConfirm,
31-
onClose,
32-
template,
33-
templateVersions,
34-
defaultTemplateVersion,
35-
...dialogProps
36-
})=>{
29+
exportconstChangeWorkspaceVersionDialog:FC<
30+
ChangeWorkspaceVersionDialogProps
31+
>=({ workspace, onClose, onConfirm, ...dialogProps})=>{
32+
const{data:versions}=useQuery({
33+
...templateVersions(workspace.template_id),
34+
select:(data)=>[...data].reverse(),
35+
});
3736
const[isAutocompleteOpen,setIsAutocompleteOpen]=useState(false);
38-
constselectedTemplateVersion=useRef<TemplateVersion|undefined>(
39-
defaultTemplateVersion,
37+
constcurrentVersion=versions?.find(
38+
(v)=>workspace.latest_build.template_version_id===v.id,
4039
);
41-
constversion=selectedTemplateVersion.current;
42-
constvalidTemplateVersions=templateVersions?.filter((version)=>{
43-
returnversion.job.status==="succeeded";
44-
});
40+
const[newVersion,setNewVersion]=useState<TemplateVersion>();
41+
constvalidVersions=versions?.filter((v)=>v.job.status==="succeeded");
42+
constselectedVersion=newVersion||currentVersion;
4543

4644
return(
4745
<ConfirmDialog
4846
{...dialogProps}
4947
onClose={onClose}
5048
onConfirm={()=>{
51-
if(selectedTemplateVersion.current){
52-
onConfirm(selectedTemplateVersion.current);
49+
if(newVersion){
50+
onConfirm(newVersion);
5351
}
5452
}}
5553
hideCancel={false}
@@ -60,18 +58,17 @@ export const ChangeVersionDialog: FC<ChangeVersionDialogProps> = ({
6058
description={
6159
<Stack>
6260
<p>You are about to change the version of this workspace.</p>
63-
{validTemplateVersions ?(
61+
{validVersions ?(
6462
<>
6563
<FormFields>
6664
<Autocomplete
6765
disableClearable
68-
options={validTemplateVersions}
69-
defaultValue={defaultTemplateVersion}
66+
options={validVersions}
67+
defaultValue={selectedVersion}
7068
id="template-version-autocomplete"
7169
open={isAutocompleteOpen}
7270
onChange={(_,newTemplateVersion)=>{
73-
selectedTemplateVersion.current=
74-
newTemplateVersion??undefined;
71+
setNewVersion(newTemplateVersion);
7572
}}
7673
onOpen={()=>{
7774
setIsAutocompleteOpen(true);
@@ -112,9 +109,8 @@ export const ChangeVersionDialog: FC<ChangeVersionDialogProps> = ({
112109
/>
113110
)}
114111
</Stack>
115-
{template?.active_version_id===option.id&&(
116-
<Pilltype="success">Active</Pill>
117-
)}
112+
{workspace.template_active_version_id===
113+
option.id&&<Pilltype="success">Active</Pill>}
118114
</Stack>
119115
}
120116
subtitle={createDayString(option.created_at)}
@@ -131,9 +127,7 @@ export const ChangeVersionDialog: FC<ChangeVersionDialogProps> = ({
131127
...params.InputProps,
132128
endAdornment:(
133129
<>
134-
{!templateVersions ?(
135-
<CircularProgresssize={16}/>
136-
) :null}
130+
{!versions&&<CircularProgresssize={16}/>}
137131
{params.InputProps.endAdornment}
138132
</>
139133
),
@@ -144,16 +138,16 @@ export const ChangeVersionDialog: FC<ChangeVersionDialogProps> = ({
144138
)}
145139
/>
146140
</FormFields>
147-
{version&&(
141+
{selectedVersion&&(
148142
<>
149-
{version.message&&(
143+
{selectedVersion.message&&(
150144
<TemplateUpdateMessage>
151-
{version.message}
145+
{selectedVersion.message}
152146
</TemplateUpdateMessage>
153147
)}
154148
<Alertseverity="info">
155149
<AlertTitle>
156-
Published by{version.created_by.username}
150+
Published by{selectedVersion.created_by.username}
157151
</AlertTitle>
158152
</Alert>
159153
</>

‎site/src/pages/WorkspacePage/WorkspaceActions/DownloadLogsDialog.stories.tsxrenamed to‎site/src/modules/workspaces/WorkspaceMoreActions/DownloadLogsDialog.stories.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import { withDesktopViewport } from "testHelpers/storybook";
66
import{DownloadLogsDialog}from"./DownloadLogsDialog";
77

88
constmeta:Meta<typeofDownloadLogsDialog>={
9-
title:"pages/WorkspacePage/DownloadLogsDialog",
9+
title:"modules/workspaces/DownloadLogsDialog",
1010
component:DownloadLogsDialog,
1111
args:{
1212
open:true,

‎site/src/pages/WorkspacePage/WorkspaceActions/DownloadLogsDialog.tsxrenamed to‎site/src/modules/workspaces/WorkspaceMoreActions/DownloadLogsDialog.tsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -221,8 +221,9 @@ const DownloadingItem: FC<DownloadingItemProps> = ({ file, giveUpTimeMs }) => {
221221
functionhumanBlobSize(size:number){
222222
constBLOB_SIZE_UNITS=["B","KB","MB","GB","TB"]asconst;
223223
leti=0;
224-
while(size>1024&&i<BLOB_SIZE_UNITS.length){
225-
size/=1024;
224+
letsizeIterator=size;
225+
while(sizeIterator>1024&&i<BLOB_SIZE_UNITS.length){
226+
sizeIterator/=1024;
226227
i++;
227228
}
228229

‎site/src/pages/WorkspacePage/WorkspaceDeleteDialog/WorkspaceDeleteDialog.stories.tsxrenamed to‎site/src/modules/workspaces/WorkspaceMoreActions/WorkspaceDeleteDialog.stories.tsx

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,21 @@
11
importtype{Meta,StoryObj}from"@storybook/react";
22
import{MockFailedWorkspace,MockWorkspace}from"testHelpers/entities";
3+
import{daysAgo}from"utils/time";
34
import{WorkspaceDeleteDialog}from"./WorkspaceDeleteDialog";
45

56
constmeta:Meta<typeofWorkspaceDeleteDialog>={
6-
title:"pages/WorkspacePage/WorkspaceDeleteDialog",
7+
title:"modules/workspaces/WorkspaceDeleteDialog",
78
component:WorkspaceDeleteDialog,
89
args:{
9-
workspace:MockWorkspace,
10-
canUpdateTemplate:false,
10+
workspace:{
11+
...MockWorkspace,
12+
latest_build:{
13+
...MockWorkspace.latest_build,
14+
created_at:daysAgo(2),
15+
},
16+
},
17+
canDeleteFailedWorkspace:false,
1118
isOpen:true,
12-
onCancel:()=>{},
13-
onConfirm:()=>{},
14-
workspaceBuildDateStr:"2 days ago",
1519
},
1620
};
1721

@@ -30,14 +34,14 @@ export const Unhealthy: Story = {
3034
// Should look the same as `Example`
3135
exportconstAdminView:Story={
3236
args:{
33-
canUpdateTemplate:true,
37+
canDeleteFailedWorkspace:true,
3438
},
3539
};
3640

3741
// Should show the `--orphan` option
3842
exportconstUnhealthyAdminView:Story={
3943
args:{
4044
workspace:MockFailedWorkspace,
41-
canUpdateTemplate:true,
45+
canDeleteFailedWorkspace:true,
4246
},
4347
};

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp