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

Commitf8ed067

Browse files
committed
fix: get things working correctly
1 parent05bd144 commitf8ed067

File tree

1 file changed

+135
-120
lines changed

1 file changed

+135
-120
lines changed

‎site/src/pages/TemplatePage/TemplateEmbedPage/TemplateEmbedPageExperimental.tsx

Lines changed: 135 additions & 120 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,5 @@
11
importCheckOutlinedfrom"@mui/icons-material/CheckOutlined";
22
importFileCopyOutlinedfrom"@mui/icons-material/FileCopyOutlined";
3-
importFormControlLabelfrom"@mui/material/FormControlLabel";
4-
importRadiofrom"@mui/material/Radio";
5-
importRadioGroupfrom"@mui/material/RadioGroup";
63
import{API}from"api/api";
74
import{DetailedError}from"api/errors";
85
importtype{
@@ -11,56 +8,48 @@ import type {
118
FriendlyDiagnostic,
129
PreviewParameter,
1310
Template,
14-
User,
1511
}from"api/typesGenerated";
1612
import{ErrorAlert}from"components/Alert/ErrorAlert";
1713
import{Button}from"components/Button/Button";
18-
import{FormSection}from"components/Form/Form";
19-
import{Loader}from"components/Loader/Loader";
14+
import{Label}from"components/Label/Label";
15+
import{RadioGroup,RadioGroupItem}from"components/RadioGroup/RadioGroup";
16+
import{Skeleton}from"components/Skeleton/Skeleton";
17+
import{useAuthenticated}from"hooks";
2018
import{useEffectEvent}from"hooks/hookPolyfills";
2119
import{useClipboard}from"hooks/useClipboard";
2220
import{
2321
Diagnostics,
2422
DynamicParameter,
2523
}from"modules/workspaces/DynamicParameter/DynamicParameter";
2624
import{useTemplateLayoutContext}from"pages/TemplatePage/TemplateLayout";
27-
import{
28-
typeFC,
29-
useCallback,
30-
useEffect,
31-
useMemo,
32-
useRef,
33-
useState,
34-
}from"react";
25+
import{typeFC,useEffect,useMemo,useRef,useState}from"react";
3526
import{Helmet}from"react-helmet-async";
36-
import{useQuery}from"react-query";
3727
import{pageTitle}from"utils/page";
3828

3929
typeButtonValues=Record<string,string>;
4030

4131
constTemplateEmbedPageExperimental:FC=()=>{
4232
const{ template}=useTemplateLayoutContext();
33+
const{user:me}=useAuthenticated();
4334
const[latestResponse,setLatestResponse]=
4435
useState<DynamicParametersResponse|null>(null);
4536
constwsResponseId=useRef<number>(-1);
4637
constws=useRef<WebSocket|null>(null);
4738
const[wsError,setWsError]=useState<Error|null>(null);
4839

49-
const{data:authenticatedUser}=useQuery<User>({
50-
queryKey:["authenticatedUser"],
51-
queryFn:()=>API.getAuthenticatedUser(),
52-
});
53-
54-
constsendMessage=useCallback((formValues:Record<string,string>)=>{
55-
constrequest:DynamicParametersRequest={
56-
id:wsResponseId.current+1,
57-
inputs:formValues,
58-
};
59-
if(ws.current&&ws.current.readyState===WebSocket.OPEN){
60-
ws.current.send(JSON.stringify(request));
61-
wsResponseId.current=wsResponseId.current+1;
62-
}
63-
},[]);
40+
constsendMessage=useEffectEvent(
41+
(formValues:Record<string,string>,ownerId?:string)=>{
42+
constrequest:DynamicParametersRequest={
43+
id:wsResponseId.current+1,
44+
owner_id:me.id,
45+
inputs:formValues,
46+
};
47+
if(ws.current&&ws.current.readyState===WebSocket.OPEN){
48+
ws.current.send(JSON.stringify(request));
49+
wsResponseId.current=wsResponseId.current+1;
50+
}
51+
},
52+
);
6453

6554
constonMessage=useEffectEvent((response:DynamicParametersResponse)=>{
6655
if(latestResponse&&latestResponse?.id>=response.id){
@@ -71,25 +60,29 @@ const TemplateEmbedPageExperimental: FC = () => {
7160
});
7261

7362
useEffect(()=>{
74-
if(!template.active_version_id||!authenticatedUser){
63+
if(!template.active_version_id||!me){
7564
return;
7665
}
7766

7867
constsocket=API.templateVersionDynamicParameters(
79-
authenticatedUser.id,
8068
template.active_version_id,
69+
me.id,
8170
{
8271
onMessage,
8372
onError:(error)=>{
84-
setWsError(error);
73+
if(ws.current===socket){
74+
setWsError(error);
75+
}
8576
},
8677
onClose:()=>{
87-
setWsError(
88-
newDetailedError(
89-
"Websocket connection for dynamic parameters unexpectedly closed.",
90-
"Refresh the page to reset the form.",
91-
),
92-
);
78+
if(ws.current===socket){
79+
setWsError(
80+
newDetailedError(
81+
"Websocket connection for dynamic parameters unexpectedly closed.",
82+
"Refresh the page to reset the form.",
83+
),
84+
);
85+
}
9386
},
9487
},
9588
);
@@ -99,7 +92,7 @@ const TemplateEmbedPageExperimental: FC = () => {
9992
return()=>{
10093
socket.close();
10194
};
102-
},[authenticatedUser,template.active_version_id,onMessage]);
95+
},[template.active_version_id,onMessage,me]);
10396

10497
constsortedParams=useMemo(()=>{
10598
if(!latestResponse?.parameters){
@@ -108,6 +101,9 @@ const TemplateEmbedPageExperimental: FC = () => {
108101
return[...latestResponse.parameters].sort((a,b)=>a.order-b.order);
109102
},[latestResponse?.parameters]);
110103

104+
constisLoading=
105+
ws.current?.readyState===WebSocket.CONNECTING||!latestResponse;
106+
111107
return(
112108
<>
113109
<Helmet>
@@ -119,6 +115,7 @@ const TemplateEmbedPageExperimental: FC = () => {
119115
diagnostics={latestResponse?.diagnostics??[]}
120116
error={wsError}
121117
sendMessage={sendMessage}
118+
isLoading={isLoading}
122119
/>
123120
</>
124121
);
@@ -130,6 +127,7 @@ interface TemplateEmbedPageViewProps {
130127
diagnostics:readonlyFriendlyDiagnostic[];
131128
error:unknown;
132129
sendMessage:(message:Record<string,string>)=>void;
130+
isLoading:boolean;
133131
}
134132

135133
constTemplateEmbedPageView:FC<TemplateEmbedPageViewProps>=({
@@ -138,45 +136,46 @@ const TemplateEmbedPageView: FC<TemplateEmbedPageViewProps> = ({
138136
diagnostics,
139137
error,
140138
sendMessage,
139+
isLoading,
141140
})=>{
142-
const[buttonValues,setButtonValues]=useState<ButtonValues|undefined>();
143-
const[localParameters,setLocalParameters]=useState<
144-
Record<string,string>
145-
>({});
141+
const[formState,setFormState]=useState<{
142+
mode:"manual"|"auto";
143+
paramValues:Record<string,string>;
144+
}>({
145+
mode:"manual",
146+
paramValues:{},
147+
});
146148

147149
useEffect(()=>{
148150
if(parameters){
149-
constinitialInputs:Record<string,string>={};
150-
constcurrentMode=buttonValues?.mode||"manual";
151-
constinitialButtonParamValues:ButtonValues={mode:currentMode};
152-
151+
constserverParamValues:Record<string,string>={};
153152
for(constpofparameters){
154153
constinitialVal=p.value?.valid ?p.value.value :"";
155-
initialInputs[p.name]=initialVal;
156-
initialButtonParamValues[`param.${p.name}`]=initialVal;
154+
serverParamValues[p.name]=initialVal;
157155
}
158-
setLocalParameters(initialInputs);
156+
setFormState((prev)=>({ ...prev,paramValues:serverParamValues}));
157+
}
158+
},[parameters]);
159159

160-
setButtonValues(initialButtonParamValues);
160+
constbuttonValues=useMemo(()=>{
161+
constvalues:ButtonValues={mode:formState.mode};
162+
for(const[key,value]ofObject.entries(formState.paramValues)){
163+
values[`param.${key}`]=value;
161164
}
162-
},[parameters,buttonValues?.mode]);
165+
returnvalues;
166+
},[formState]);
163167

164168
consthandleChange=(
165169
changedParamInfo:PreviewParameter,
166170
newValue:string,
167171
)=>{
168-
constnewFormInputs={
169-
...localParameters,
172+
constnewParamValues={
173+
...formState.paramValues,
170174
[changedParamInfo.name]:newValue,
171175
};
172-
setLocalParameters(newFormInputs);
173-
174-
setButtonValues((prevButtonValues)=>({
175-
...(prevButtonValues||{}),
176-
[`param.${changedParamInfo.name}`]:newValue,
177-
}));
176+
setFormState((prev)=>({ ...prev,paramValues:newParamValues}));
178177

179-
constformInputsToSend:Record<string,string>={ ...newFormInputs};
178+
constformInputsToSend:Record<string,string>={ ...newParamValues};
180179
for(constpofparameters){
181180
if(!(p.nameinformInputsToSend)){
182181
formInputsToSend[p.name]=p.value?.valid ?p.value.value :"";
@@ -186,68 +185,84 @@ const TemplateEmbedPageView: FC<TemplateEmbedPageViewProps> = ({
186185
sendMessage(formInputsToSend);
187186
};
188187

189-
useEffect(()=>{
190-
if(!buttonValues&&parameters.length===0){
191-
setButtonValues({mode:"manual"});
192-
}elseif(buttonValues&&!buttonValues.mode&&parameters.length>0){
193-
setButtonValues((prev)=>({ ...prev,mode:"manual"}));
194-
}
195-
},[buttonValues,parameters]);
196-
197-
if(!buttonValues||(!parameters&&!error)){
198-
return<Loader/>;
199-
}
200-
201188
return(
202189
<>
203190
<divclassName="flex items-start gap-12">
204-
<divclassName="flex flex-col gap-5 max-w-screen-md">
205-
{Boolean(error)&&<ErrorAlerterror={error}/>}
206-
{diagnostics.length>0&&<Diagnosticsdiagnostics={diagnostics}/>}
207-
<divclassName="flex flex-col">
208-
<FormSection
209-
title="Creation mode"
210-
description="By changing the mode to automatic, when the user clicks the button, the workspace will be created automatically instead of showing a form to the user."
211-
>
212-
<RadioGroup
213-
defaultValue={buttonValues?.mode||"manual"}
214-
onChange={(_,v)=>{
215-
setButtonValues((prevButtonValues)=>({
216-
...(prevButtonValues||{}),
217-
mode:v,
218-
}));
219-
}}
220-
>
221-
<FormControlLabel
222-
value="manual"
223-
control={<Radiosize="small"/>}
224-
label="Manual"
225-
/>
226-
<FormControlLabel
227-
value="auto"
228-
control={<Radiosize="small"/>}
229-
label="Automatic"
230-
/>
231-
</RadioGroup>
232-
</FormSection>
233-
234-
{parameters.length>0&&(
191+
<divclassName="w-full flex flex-col gap-5 max-w-screen-md">
192+
{isLoading ?(
193+
<divclassName="flex flex-col gap-9">
194+
<divclassName="flex flex-col gap-2">
195+
<SkeletonclassName="h-5 w-1/3"/>
196+
<SkeletonclassName="h-9 w-full"/>
197+
</div>
198+
<divclassName="flex flex-col gap-2">
199+
<SkeletonclassName="h-5 w-1/3"/>
200+
<SkeletonclassName="h-9 w-full"/>
201+
</div>
202+
<divclassName="flex flex-col gap-2">
203+
<SkeletonclassName="h-5 w-1/3"/>
204+
<SkeletonclassName="h-9 w-full"/>
205+
</div>
206+
</div>
207+
) :(
208+
<>
209+
{Boolean(error)&&<ErrorAlerterror={error}/>}
210+
{diagnostics.length>0&&(
211+
<Diagnosticsdiagnostics={diagnostics}/>
212+
)}
235213
<divclassName="flex flex-col gap-9">
236-
{parameters.map((parameter)=>{
237-
constisDisabled=parameter.styling?.disabled;
238-
return(
239-
<DynamicParameter
240-
key={parameter.name}
241-
parameter={parameter}
242-
onChange={(value)=>handleChange(parameter,value)}
243-
disabled={isDisabled}
244-
value={localParameters[parameter.name]||""}
245-
/>
246-
);
247-
})}
214+
<sectionclassName="flex flex-col gap-2">
215+
<div>
216+
<h2className="text-lg font-bold m-0">Creation mode</h2>
217+
<pclassName="text-sm text-content-secondary m-0">
218+
When set to automatic mode, clicking the button will
219+
create the workspace automatically without displaying a
220+
form to the user.
221+
</p>
222+
</div>
223+
<RadioGroup
224+
value={formState.mode}
225+
onValueChange={(v)=>{
226+
setFormState((prev)=>({
227+
...prev,
228+
mode:vas"manual"|"auto",
229+
}));
230+
}}
231+
>
232+
<divclassName="flex items-center gap-3">
233+
<RadioGroupItemvalue="manual"id="manual"/>
234+
<LabelhtmlFor={"manual"}className="cursor-pointer">
235+
Manual
236+
</Label>
237+
</div>
238+
<divclassName="flex items-center gap-3">
239+
<RadioGroupItemvalue="auto"id="automatic"/>
240+
<LabelhtmlFor={"automatic"}className="cursor-pointer">
241+
Automatic
242+
</Label>
243+
</div>
244+
</RadioGroup>
245+
</section>
246+
247+
{parameters.length>0&&(
248+
<divclassName="flex flex-col gap-9">
249+
{parameters.map((parameter)=>{
250+
constisDisabled=parameter.styling?.disabled;
251+
return(
252+
<DynamicParameter
253+
key={parameter.name}
254+
parameter={parameter}
255+
onChange={(value)=>handleChange(parameter,value)}
256+
disabled={isDisabled}
257+
value={formState.paramValues[parameter.name]||""}
258+
/>
259+
);
260+
})}
261+
</div>
262+
)}
248263
</div>
249-
)}
250-
</div>
264+
</>
265+
)}
251266
</div>
252267

253268
<ButtonPreviewtemplate={template}buttonValues={buttonValues}/>
@@ -285,7 +300,7 @@ const ButtonPreview: FC<ButtonPreviewProps> = ({ template, buttonValues }) => {
285300

286301
return(
287302
<div
288-
className="sticky top-10 flex gap-16 h-80 p-14 flex-1 flex-col items-center justify-center
303+
className="sticky top-10 flex gap-16 h-96 flex-1 flex-col items-center justify-center
289304
rounded-lg border border-border border-solid bg-surface-secondary"
290305
>
291306
<imgsrc="/open-in-coder.svg"alt="Open in Coder button"/>

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp