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

Commit 3fd02e0

Browse files
Get tour step refs to persist past reload
I don't know exactly what I was doing wrong, so I copied the dropdown control and modified it to accept the editor state. this could most likely be done cleaner by allowing for the existing dropdown control to accept a function with generic arguments, but that can be cleaned up later.
1 parent 26ea604 commit 3fd02e0

File tree

3 files changed

+181
-81
lines changed

3 files changed

+181
-81
lines changed

‎client/packages/lowcoder/src/comps/comps/tourComp/componentSelectorControl.tsx‎

Lines changed: 18 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,9 @@ const ExecuteCompTmpAction = (function() {
4646
params: ParamsValueControl
4747
};
4848
return new MultiCompBuilder(childrenMap, () => {
49-
return () => undefined as (React.RefObject<HTMLElement> | undefined);
49+
// return () => undefined as (React.RefObject<HTMLElement> | undefined);
50+
// return () => undefined as (string | undefined);
51+
return undefined as (string | undefined);
5052
// return () => Promise.resolve(undefined as unknown);
5153
})
5254
.setPropertyViewFn(() => <></>)
@@ -72,45 +74,24 @@ export function targetCompAction(params: ExecuteCompActionOptions) {
7274
}
7375
}
7476

75-
selectedComp: React.RefObject<HTMLDivElement> | undefined;
77+
// selectedComp: React.RefObject<HTMLDivElement> | undefined;
78+
selectedComp: string|undefined;
7679
compList: (GridItemComp | HookComp | InstanceType<typeof TemporaryStateItemComp>)[] = [];
7780

78-
updateSelectedComp(compName: string): void {
79-
const compListItem = this.compList.find((compItem) => compItem.children.name.getView() === compName);
80-
if (compListItem) {
81-
console.log(`setting selected comp to ${compListItem}`)
82-
this.selectedComp = ((compListItem as MultiBaseComp).children.comp as GridItemComp).getRef();
83-
}
84-
}
81+
// updateSelectedComp(compName: string): void {
82+
// const compListItem = this.compList.find((compItem) => compItem.children.name.getView() === compName);
83+
// if (compListItem) {
84+
// console.log(`setting selected comp to ${compListItem}`)
85+
// this.selectedComp = ((compListItem as MultiBaseComp).children.comp as GridItemComp).getRef();
86+
// }
87+
// }
8588

86-
override getView(): () => (React.RefObject<HTMLElement> | undefined) {
87-
return () => this.selectedComp;
89+
// override getView(): () => (React.RefObject<HTMLElement> | undefined) {
90+
// override getView(): () => (string | undefined) {
91+
override getView(): string | undefined {
92+
return this.selectedComp;
8893
}
8994

90-
// override getView() {
91-
// const name = this.children.name.getView();
92-
// if (!name) {
93-
// return () => Promise.resolve();
94-
// }
95-
// return () =>
96-
// getPromiseAfterDispatch(
97-
// this.dispatch,
98-
// routeByNameAction(
99-
// name,
100-
// customAction<ExecuteAction>(
101-
// {
102-
// type: "execute",
103-
// methodName: this.children.methodName.getView(),
104-
// params: this.children.params.getView().map((x) => x.getView())
105-
// },
106-
// false
107-
// )
108-
// ),
109-
// {
110-
// notHandledError: trans("eventHandler.notHandledError")
111-
// }
112-
// );
113-
// }
11495
exposingNode() {
11596
return this.node();
11697
}
@@ -130,7 +111,6 @@ export function targetCompAction(params: ExecuteCompActionOptions) {
130111
});
131112

132113
function changeMethodAction(compName: string, methodName: string) {
133-
console.log("sldjafldkdf")
134114
const currentMethods = compMethods[compName] ?? {};
135115
const params = currentMethods[methodName];
136116
return {
@@ -161,7 +141,8 @@ export function targetCompAction(params: ExecuteCompActionOptions) {
161141
onChange={(value) => {
162142
console.log(`the value is ${value}`);
163143
// After the value is changed, update `selectedComp`
164-
this.updateSelectedComp(value);
144+
// this.updateSelectedComp(value);
145+
this.selectedComp = value;
165146

166147
console.log("am i here? ")
167148
return this.dispatchChangeValueAction(

‎client/packages/lowcoder/src/comps/comps/tourComp/tourComp.tsx‎

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { styleControl } from "comps/controls/styleControl";
22
import { SelectStyle } from "comps/controls/styleControlConstants";
33
import { trans } from "i18n";
44
import {
5-
CommonNameConfig,
5+
CommonNameConfig,MultiBaseComp,
66
NameConfig,
77
stringExposingStateControl,
88
UICompBuilder,
@@ -13,6 +13,12 @@ import { baseSelectRefMethods, TourChildrenMap, TourPropertyView } from "./tourC
1313
import { TourInputCommonConfig } from "./tourInputConstants";
1414
import { Tour, TourProps } from "antd";
1515
import { PlacementType } from "@lowcoder-ee/comps/controls/tourStepControl";
16+
import { useContext } from "react";
17+
import { EditorContext } from "@lowcoder-ee/comps/editorState";
18+
import { GridItemComp } from "@lowcoder-ee/comps/comps/gridItemComp";
19+
import { HookComp } from "@lowcoder-ee/comps/hooks/hookComp";
20+
import { TemporaryStateItemComp } from "@lowcoder-ee/comps/comps/temporaryStateComp";
21+
import { delay } from "redux-saga/effects";
1622

1723
/**
1824
* This component builds the Property Panel and the fake 'UI' for the Tour component
@@ -25,13 +31,31 @@ let TourBasicComp = (function () {
2531
// style: styleControl(SelectStyle),
2632
};
2733
return new UICompBuilder(childrenMap, (props, dispatch) => {
28-
34+
const editorState = useContext(EditorContext);
35+
console.log("EDITOR STATE IS HERE")
36+
console.log(editorState)
37+
const compMap: (GridItemComp | HookComp | InstanceType<typeof TemporaryStateItemComp>)[] = Object.values(editorState.getAllUICompMap());
38+
console.log("COMP MAP IS HERE")
39+
console.log(compMap)
40+
2941
const steps: TourProps['steps'] = props.options.map((step) => {
42+
const targetName = step.target;
43+
let target = undefined;
44+
const compListItem = compMap.find((compItem) => compItem.children.name.getView() === targetName);
45+
if (compListItem) {
46+
console.log(`setting selected comp to ${compListItem}`)
47+
try {
48+
target = ((compListItem as MultiBaseComp).children.comp as GridItemComp).getRef();
49+
} catch (e) {
50+
target = ((compListItem as MultiBaseComp).children.comp as HookComp).getRef();
51+
}
52+
}
53+
3054
return {
3155
title: step.title,
3256
description: step.description,
33-
target: step.target()?.current,
34-
// arrow: step.arrow,
57+
target: target?.current,
58+
arrow: step.arrow||true,
3559
placement: step.placement as PlacementType,
3660
}
3761
})

‎client/packages/lowcoder/src/comps/controls/tourStepControl.tsx‎

Lines changed: 135 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import { ViewDocIcon } from "assets/icons";
21
import { BoolCodeControl, StringControl } from "comps/controls/codeControl";
32
import { dropdownControl } from "comps/controls/dropdownControl";
43
import { MultiCompBuilder, withDefault } from "comps/generators";
@@ -15,12 +14,14 @@ import {
1514
ConstructorToView,
1615
fromRecord,
1716
MultiBaseComp,
17+
SimpleAbstractComp,
1818
withFunction
1919
} from "lowcoder-core";
20-
import { controlItem, Option } from "lowcoder-design";
21-
import styled from "styled-components";
20+
import { controlItem, Dropdown, Option, OptionsType, ValueFromOption } from "lowcoder-design";
2221
import { getNextEntityName } from "util/stringUtils";
23-
import { TargetCompAction } from "@lowcoder-ee/comps/comps/tourComp/componentSelectorControl";
22+
import { BoolControl, ControlParams } from "lowcoder-sdk";
23+
import { ReactNode, useContext, useEffect, useState } from "react";
24+
import { EditorContext, EditorState } from "@lowcoder-ee/comps/editorState";
2425
// import { PlacementType } from "@rc-component"
2526
export type PlacementType = 'left' | 'leftTop' | 'leftBottom' | 'right' | 'rightTop' | 'rightBottom' | 'top' | 'topLeft' | 'topRight' | 'bottom' | 'bottomLeft' | 'bottomRight' | 'center';
2627

@@ -205,35 +206,6 @@ export function manualTourStepsControl<T extends TourStepControlType>(
205206
: ManualOptionControl;
206207
}
207208

208-
const TipLabel = styled.p`
209-
display: inline;
210-
margin: 2px 0 0 0;
211-
padding: 0;
212-
213-
font-size: 13px;
214-
color: #9195a3;
215-
line-height: 18px;
216-
cursor: pointer;
217-
218-
:hover g g {
219-
stroke: #315efb;
220-
}
221-
`;
222-
const DocIcon = styled(ViewDocIcon)`
223-
transform: translateY(1px);
224-
margin-right: 6px;
225-
`;
226-
227-
const optionListDocUrl = trans("docUrls.optionList");
228-
const OptionTip = optionListDocUrl ? (
229-
<TipLabel onClick={() => window.open(optionListDocUrl)}>
230-
<DocIcon title={trans("optionsControl.viewDocs")} />
231-
{trans("optionsControl.tip")}
232-
</TipLabel>
233-
) : (
234-
<></>
235-
);
236-
237209
type TourStepChildType = {
238210
title: InstanceType<typeof StringControl>,
239211
};
@@ -308,14 +280,131 @@ const PlacementOptions: {label: string, value: PlacementType}[] = [
308280
{ label: "Bottom Right", value: "bottomRight"},
309281
];
310282

283+
284+
export function editorStateDropdownControl<T extends OptionsType>(
285+
options: ((editorState: EditorState) => T),
286+
defaultValue: ValueFromOption<T>
287+
) {
288+
return class extends editorStateDropdownAbstractControl(options, defaultValue) {
289+
override getView() {
290+
return this.value;
291+
}
292+
};
293+
}
294+
295+
interface EditorStateDropdownControlParams<T extends OptionsType> extends ControlParams {
296+
radioButton?: boolean;
297+
border?: boolean;
298+
type?: "oneline";
299+
disabled?: boolean;
300+
// parent comp may batch dispatch in some cases
301+
disableDispatchValueChange?: boolean;
302+
onChange?: (value: string) => void;
303+
options?: T;
304+
showSearch?: boolean;
305+
dropdownStyle?: React.CSSProperties;
306+
labelStyle?: React.CSSProperties;
307+
IconType?: "OnlyAntd" | "All" | "default" | undefined;
308+
}
309+
type EditorStateDropdownOptions<T extends OptionsType> = (editorState: EditorState) => T;
310+
311+
interface DropdownPropertyViewProps<T extends OptionsType>
312+
extends Omit<EditorStateDropdownControlParams<T>, "options"> {
313+
options: EditorStateDropdownOptions<T>;
314+
onChange: (value: ValueFromOption<T>) => void;
315+
value: ValueFromOption<T>;
316+
}
317+
318+
function EditorStateDropdownPropertyView<T extends OptionsType>(props: DropdownPropertyViewProps<T>) {
319+
const { options, onChange, value, ...params } = props;
320+
const [finalOptions, setFinalOptions] = useState<T>(
321+
typeof options === "function" ? ([] as unknown as T) : options
322+
);
323+
const editorState = useContext(EditorContext);
324+
325+
useEffect(() => {
326+
if (typeof options !== "function") {
327+
setFinalOptions(options);
328+
return;
329+
}
330+
if (!finalOptions?.length) {
331+
setFinalOptions(options(editorState))
332+
//.then((items) => setFinalOptions(items));
333+
}
334+
}, [finalOptions.length, options]);
335+
336+
return (
337+
<Dropdown
338+
placement={params.placement}
339+
toolTip={params.tooltip}
340+
value={value}
341+
options={finalOptions}
342+
radioButton={params.radioButton}
343+
border={params.border}
344+
type={params.type}
345+
label={params.label}
346+
showSearch={params.showSearch}
347+
onChange={onChange}
348+
disabled={params.disabled}
349+
dropdownStyle={props.dropdownStyle}
350+
labelStyle={props.labelStyle}
351+
/>
352+
);
353+
}
354+
355+
/**
356+
* Leave a getView method unimplemented, because the type cannot be changed by inheritance
357+
*/
358+
export function editorStateDropdownAbstractControl<T extends OptionsType>(
359+
options: ((editorState: EditorState) => T),
360+
defaultValue: ValueFromOption<T>
361+
) {
362+
abstract class DropdownControl extends SimpleAbstractComp<ValueFromOption<T>> {
363+
override getDefaultValue(): ValueFromOption<T> {
364+
return defaultValue;
365+
}
366+
367+
propertyView(params: EditorStateDropdownControlParams<T>) {
368+
return controlItem(
369+
{ filterText: params.label },
370+
<EditorStateDropdownPropertyView<T>
371+
{...params}
372+
value={this.value}
373+
options={options}
374+
onChange={(value) => {
375+
if (!params.disableDispatchValueChange) {
376+
this.dispatchChangeValueAction(value);
377+
}
378+
params.onChange?.(value);
379+
}}
380+
/>
381+
);
382+
}
383+
384+
getPropertyView(): ReactNode {
385+
throw new Error("Method not implemented.");
386+
}
387+
}
388+
389+
return DropdownControl;
390+
}
391+
311392
let TourStep = new MultiCompBuilder(
312393
{
313-
target: TargetCompAction,
314-
// target: dropdownControl(editorState.getAllUICompMap(), ""),
315-
arrow: BoolCodeControl,
394+
// target: TargetCompAction,
395+
target: editorStateDropdownControl((editorState) => {
396+
console.log("Is editor defined? ")
397+
console.log(editorState)
398+
return Object.values(editorState.getAllUICompMap()).map((it) => ({
399+
label: it.children.name.getView(),
400+
value: it.children.name.getView(),
401+
}))
402+
},
403+
""),
404+
arrow: BoolControl,
316405
title: StringControl,
317406
description: StringControl,
318-
placement: dropdownControl(PlacementOptions, "center"),
407+
placement: dropdownControl(PlacementOptions, "bottom"),
319408
hidden: BoolCodeControl,
320409
},
321410
(props) => props
@@ -333,11 +422,17 @@ TourStep = class extends TourStep implements TourStepCompProperty {
333422
label: "Description",
334423
placeholder: "Welcome to lowcoder, this is your first tutorial step",
335424
})}
336-
{this.children.target.propertyView()}
425+
{this.children.target.propertyView({
426+
label: "TARGET",
427+
radioButton: false,
428+
})}
337429
{this.children.placement.propertyView({
338430
label: trans("textShow.verticalAlignment"),
339431
radioButton: false
340432
})}
433+
{this.children.arrow.propertyView({
434+
label: "Arrow"
435+
})}
341436
{hiddenPropertyView(this.children)}
342437
</>
343438
);
@@ -346,7 +441,7 @@ TourStep = class extends TourStep implements TourStepCompProperty {
346441

347442
export const TourStepControl = tourStepsControl(TourStep, {
348443
initOptions: [
349-
{ title: "BLAHHH", description: "I love tutorials" },
350-
{ title: "second title", description: "Because they mean I don't have to teach people" },
444+
{ title: "Welcome", description: "Welcome to lowcoder" },
445+
{ title: "Step 2", description: "This is a tutorial step" },
351446
],
352447
});

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /