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

Commit0c7f4c1

Browse files
committed
chore: get parity with create workspace page
1 parentf19178c commit0c7f4c1

File tree

4 files changed

+141
-87
lines changed

4 files changed

+141
-87
lines changed

‎site/src/pages/WorkspaceSettingsPage/WorkspaceParametersPage/WorkspaceParametersExperimentRouter.tsx

Lines changed: 28 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,28 @@ const WorkspaceParametersExperimentRouter: FC = () => {
2323
workspace.template_id,
2424
"optOut",
2525
],
26-
queryFn:()=>({
27-
templateId:workspace.template_id,
28-
workspaceId:workspace.id,
29-
optedOut:
30-
localStorage.getItem(optOutKey(workspace.template_id))==="true",
31-
}),
26+
queryFn:()=>{
27+
consttemplateId=workspace.template_id;
28+
constworkspaceId=workspace.id;
29+
constlocalStorageKey=optOutKey(templateId);
30+
conststoredOptOutString=localStorage.getItem(localStorageKey);
31+
32+
letoptOutResult:boolean;
33+
34+
if(storedOptOutString!==null){
35+
optOutResult=storedOptOutString==="true";
36+
}else{
37+
optOutResult=Boolean(
38+
workspace.template_use_classic_parameter_flow,
39+
);
40+
}
41+
42+
return{
43+
templateId,
44+
workspaceId,
45+
optedOut:optOutResult,
46+
};
47+
},
3248
}
3349
:{enabled:false},
3450
);
@@ -43,7 +59,12 @@ const WorkspaceParametersExperimentRouter: FC = () => {
4359

4460
consttoggleOptedOut=()=>{
4561
constkey=optOutKey(optOutQuery.data.templateId);
46-
constcurrent=localStorage.getItem(key)==="true";
62+
conststoredValue=localStorage.getItem(key);
63+
64+
constcurrent=storedValue
65+
?storedValue==="true"
66+
:Boolean(workspace.template_use_classic_parameter_flow);
67+
4768
localStorage.setItem(key,(!current).toString());
4869
optOutQuery.refetch();
4970
};

‎site/src/pages/WorkspaceSettingsPage/WorkspaceParametersPage/WorkspaceParametersPage.tsx

Lines changed: 18 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ import { ErrorAlert } from "components/Alert/ErrorAlert";
77
import{ButtonasShadcnButton}from"components/Button/Button";
88
import{EmptyState}from"components/EmptyState/EmptyState";
99
import{Loader}from"components/Loader/Loader";
10-
import{PageHeader,PageHeaderTitle}from"components/PageHeader/PageHeader";
1110
import{ExternalLinkIcon}from"lucide-react";
1211
import{typeFC,useContext}from"react";
1312
import{Helmet}from"react-helmet-async";
@@ -116,27 +115,25 @@ export const WorkspaceParametersPageView: FC<
116115
})=>{
117116
constexperimentalFormContext=useContext(ExperimentalFormContext);
118117
return(
119-
<>
120-
<PageHeader
121-
css={{paddingTop:0}}
122-
actions={
123-
experimentalFormContext&&(
124-
<ShadcnButton
125-
size="sm"
126-
variant="outline"
127-
onClick={experimentalFormContext.toggleOptedOut}
128-
>
129-
Try out the new workspace parameters ✨
130-
</ShadcnButton>
131-
)
132-
}
133-
>
134-
<PageHeaderTitle>Workspace parameters</PageHeaderTitle>
135-
</PageHeader>
118+
<divclassName="flex flex-col gap-10">
119+
<headerclassName="flex flex-col items-start gap-2">
120+
<spanclassName="flex flex-row justify-between items-center gap-2">
121+
<h1className="text-3xl m-0">Workspace parameters</h1>
122+
</span>
123+
{experimentalFormContext&&(
124+
<ShadcnButton
125+
size="sm"
126+
variant="outline"
127+
onClick={experimentalFormContext.toggleOptedOut}
128+
>
129+
Try out the new workspace parameters ✨
130+
</ShadcnButton>
131+
)}
132+
</header>
136133

137-
{submitError&&!isApiValidationError(submitError)&&(
134+
{submitError&&!isApiValidationError(submitError)?(
138135
<ErrorAlerterror={submitError}css={{marginBottom:48}}/>
139-
)}
136+
) :null}
140137

141138
{data ?(
142139
data.templateVersionRichParameters.length>0 ?(
@@ -177,7 +174,7 @@ export const WorkspaceParametersPageView: FC<
177174
) :(
178175
<Loader/>
179176
)}
180-
</>
177+
</div>
181178
);
182179
};
183180

‎site/src/pages/WorkspaceSettingsPage/WorkspaceParametersPage/WorkspaceParametersPageExperimental.tsx

Lines changed: 30 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import { EmptyState } from "components/EmptyState/EmptyState";
1212
import{FeatureStageBadge}from"components/FeatureStageBadge/FeatureStageBadge";
1313
import{Link}from"components/Link/Link";
1414
import{Loader}from"components/Loader/Loader";
15+
import{useEffectEvent}from"hooks/hookPolyfills";
1516
importtype{FC}from"react";
1617
import{
1718
useCallback,
@@ -39,21 +40,31 @@ const WorkspaceParametersPageExperimental: FC = () => {
3940
constnavigate=useNavigate();
4041
constexperimentalFormContext=useContext(ExperimentalFormContext);
4142

42-
const[currentResponse,setCurrentResponse]=
43+
const[latestResponse,setLatestResponse]=
4344
useState<DynamicParametersResponse|null>(null);
44-
const[wsResponseId,setWSResponseId]=useState<number>(-1);
45+
constwsResponseId=useRef<number>(-1);
4546
constws=useRef<WebSocket|null>(null);
4647
const[wsError,setWsError]=useState<Error|null>(null);
4748

48-
constonMessage=useCallback((response:DynamicParametersResponse)=>{
49-
setCurrentResponse((prev)=>{
50-
if(prev?.id===response.id){
51-
returnprev;
52-
}
53-
returnresponse;
54-
});
49+
constsendMessage=useCallback((formValues:Record<string,string>)=>{
50+
constrequest:DynamicParametersRequest={
51+
id:wsResponseId.current+1,
52+
inputs:formValues,
53+
};
54+
if(ws.current&&ws.current.readyState===WebSocket.OPEN){
55+
ws.current.send(JSON.stringify(request));
56+
wsResponseId.current=wsResponseId.current+1;
57+
}
5558
},[]);
5659

60+
constonMessage=useEffectEvent((response:DynamicParametersResponse)=>{
61+
if(latestResponse&&latestResponse?.id>=response.id){
62+
return;
63+
}
64+
65+
setLatestResponse(response);
66+
});
67+
5768
useEffect(()=>{
5869
if(!workspace.latest_build.template_version_id)return;
5970

@@ -63,7 +74,9 @@ const WorkspaceParametersPageExperimental: FC = () => {
6374
{
6475
onMessage,
6576
onError:(error)=>{
66-
setWsError(error);
77+
if(ws.current===socket){
78+
setWsError(error);
79+
}
6780
},
6881
onClose:()=>{
6982
if(ws.current===socket){
@@ -89,20 +102,6 @@ const WorkspaceParametersPageExperimental: FC = () => {
89102
onMessage,
90103
]);
91104

92-
constsendMessage=useCallback((formValues:Record<string,string>)=>{
93-
setWSResponseId((prevId)=>{
94-
constrequest:DynamicParametersRequest={
95-
id:prevId+1,
96-
inputs:formValues,
97-
};
98-
if(ws.current&&ws.current.readyState===WebSocket.OPEN){
99-
ws.current.send(JSON.stringify(request));
100-
returnprevId+1;
101-
}
102-
returnprevId;
103-
});
104-
},[]);
105-
106105
constupdateParameters=useMutation({
107106
mutationFn:(buildParameters:WorkspaceBuildParameter[])=>
108107
API.postWorkspaceBuild(workspace.id,{
@@ -125,12 +124,12 @@ const WorkspaceParametersPageExperimental: FC = () => {
125124
consthandleSubmit=(values:{
126125
rich_parameter_values:WorkspaceBuildParameter[];
127126
})=>{
128-
if(!currentResponse||!currentResponse.parameters){
127+
if(!latestResponse||!latestResponse.parameters){
129128
return;
130129
}
131130

132131
// Only submit mutable parameters
133-
constonlyMutableValues=currentResponse.parameters
132+
constonlyMutableValues=latestResponse.parameters
134133
.filter((p)=>p.mutable)
135134
.map((p)=>{
136135
constvalue=values.rich_parameter_values.find(
@@ -146,16 +145,16 @@ const WorkspaceParametersPageExperimental: FC = () => {
146145
};
147146

148147
constsortedParams=useMemo(()=>{
149-
if(!currentResponse?.parameters){
148+
if(!latestResponse?.parameters){
150149
return[];
151150
}
152-
return[...currentResponse.parameters].sort((a,b)=>a.order-b.order);
153-
},[currentResponse?.parameters]);
151+
return[...latestResponse.parameters].sort((a,b)=>a.order-b.order);
152+
},[latestResponse?.parameters]);
154153

155154
consterror=wsError||updateParameters.error;
156155

157156
if(
158-
!currentResponse||
157+
!latestResponse||
159158
(ws.current&&ws.current.readyState===WebSocket.CONNECTING)
160159
){
161160
return<Loader/>;
@@ -190,7 +189,7 @@ const WorkspaceParametersPageExperimental: FC = () => {
190189
workspace={workspace}
191190
canChangeVersions={canChangeVersions}
192191
parameters={sortedParams}
193-
diagnostics={currentResponse.diagnostics}
192+
diagnostics={latestResponse.diagnostics}
194193
isSubmitting={updateParameters.isLoading}
195194
onSubmit={handleSubmit}
196195
onCancel={()=>

‎site/src/pages/WorkspaceSettingsPage/WorkspaceParametersPage/WorkspaceParametersPageViewExperimental.tsx

Lines changed: 65 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
importtype*asTypesGenfrom"api/typesGenerated";
12
importtype{
23
PreviewParameter,
34
Workspace,
@@ -7,14 +8,13 @@ import { Alert } from "components/Alert/Alert";
78
import{Button}from"components/Button/Button";
89
import{Spinner}from"components/Spinner/Spinner";
910
import{useFormik}from"formik";
10-
import{useDebouncedFunction}from"hooks/debounce";
1111
import{
1212
DynamicParameter,
1313
getInitialParameterValues,
1414
useValidationSchemaForDynamicParameters,
1515
}from"modules/workspaces/DynamicParameter/DynamicParameter";
1616
importtype{FC}from"react";
17-
17+
import{useEffect,useRef}from"react";
1818
exporttypeWorkspaceParametersPageViewExperimentalProps={
1919
workspace:Workspace;
2020
parameters:PreviewParameter[];
@@ -60,37 +60,17 @@ export const WorkspaceParametersPageViewExperimental: FC<
6060
workspace.template_require_active_version&&
6161
!canChangeVersions;
6262

63-
const{debounced:handleChangeDebounced}=useDebouncedFunction(
64-
async(
65-
parameter:PreviewParameter,
66-
parameterField:string,
67-
value:string,
68-
)=>{
69-
awaitform.setFieldValue(parameterField,{
70-
name:parameter.name,
71-
value,
72-
});
73-
form.setFieldTouched(parameter.name,true);
74-
sendDynamicParamsRequest(parameter,value);
75-
},
76-
500,
77-
);
78-
7963
consthandleChange=async(
8064
parameter:PreviewParameter,
8165
parameterField:string,
8266
value:string,
8367
)=>{
84-
if(parameter.form_type==="input"||parameter.form_type==="textarea"){
85-
handleChangeDebounced(parameter,parameterField,value);
86-
}else{
87-
awaitform.setFieldValue(parameterField,{
88-
name:parameter.name,
89-
value,
90-
});
91-
form.setFieldTouched(parameter.name,true);
92-
sendDynamicParamsRequest(parameter,value);
93-
}
68+
awaitform.setFieldValue(parameterField,{
69+
name:parameter.name,
70+
value,
71+
});
72+
form.setFieldTouched(parameter.name,true);
73+
sendDynamicParamsRequest(parameter,value);
9474
};
9575

9676
// Send the changed parameter and all touched parameters to the websocket
@@ -114,6 +94,12 @@ export const WorkspaceParametersPageViewExperimental: FC<
11494
sendMessage(formInputs);
11595
};
11696

97+
useSyncFormParameters({
98+
parameters,
99+
formValues:form.values.rich_parameter_values??[],
100+
setFieldValue:form.setFieldValue,
101+
});
102+
117103
return(
118104
<>
119105
{disabled&&(
@@ -171,6 +157,7 @@ export const WorkspaceParametersPageViewExperimental: FC<
171157
onChange={(value)=>
172158
handleChange(parameter,parameterField,value)
173159
}
160+
autofill={false}
174161
disabled={isDisabled}
175162
/>
176163
);
@@ -201,6 +188,7 @@ export const WorkspaceParametersPageViewExperimental: FC<
201188
onChange={(value)=>
202189
handleChange(parameter,parameterField,value)
203190
}
191+
autofill={false}
204192
disabled={isDisabled}
205193
/>
206194
);
@@ -225,3 +213,52 @@ export const WorkspaceParametersPageViewExperimental: FC<
225213
</>
226214
);
227215
};
216+
217+
typeUseSyncFormParametersProps={
218+
parameters:readonlyPreviewParameter[];
219+
formValues:readonlyTypesGen.WorkspaceBuildParameter[];
220+
setFieldValue:(
221+
field:string,
222+
value:TypesGen.WorkspaceBuildParameter[],
223+
)=>void;
224+
};
225+
226+
functionuseSyncFormParameters({
227+
parameters,
228+
formValues,
229+
setFieldValue,
230+
}:UseSyncFormParametersProps){
231+
// Form values only needs to be updated when parameters change
232+
// Keep track of form values in a ref to avoid unnecessary updates to rich_parameter_values
233+
constformValuesRef=useRef(formValues);
234+
235+
useEffect(()=>{
236+
formValuesRef.current=formValues;
237+
},[formValues]);
238+
239+
useEffect(()=>{
240+
if(!parameters)return;
241+
constcurrentFormValues=formValuesRef.current;
242+
243+
constnewParameterValues=parameters.map((param)=>{
244+
return{
245+
name:param.name,
246+
value:param.value.valid ?param.value.value :"",
247+
};
248+
});
249+
250+
constisChanged=
251+
currentFormValues.length!==newParameterValues.length||
252+
newParameterValues.some(
253+
(p)=>
254+
!currentFormValues.find(
255+
(formValue)=>
256+
formValue.name===p.name&&formValue.value===p.value,
257+
),
258+
);
259+
260+
if(isChanged){
261+
setFieldValue("rich_parameter_values",newParameterValues);
262+
}
263+
},[parameters,setFieldValue]);
264+
}

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp