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 62e1afa

Browse files
Merge pull request #2038 from iamfaran/fix/2021-nav-dropdown
Add Map Mode for NavComponent
2 parents 0e5aa97 + 1d86562 commit 62e1afa

File tree

4 files changed

+156
-29
lines changed

4 files changed

+156
-29
lines changed
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
import { BoolCodeControl, StringControl } from "comps/controls/codeControl";
2+
import { clickEvent, eventHandlerControl } from "comps/controls/eventHandlerControl";
3+
import { MultiCompBuilder } from "comps/generators/multi";
4+
import { dropdownControl } from "comps/controls/dropdownControl";
5+
import { mapOptionsControl } from "comps/controls/optionsControl";
6+
import { trans } from "i18n";
7+
import { navListComp } from "../navItemComp";
8+
import { controlItem } from "lowcoder-design";
9+
import { menuPropertyView } from "./MenuItemList";
10+
11+
export function createNavItemsControl() {
12+
const OptionTypes = [
13+
{ label: trans("prop.manual"), value: "manual" },
14+
{ label: trans("prop.map"), value: "map" },
15+
] as const;
16+
17+
const NavMapOption = new MultiCompBuilder(
18+
{
19+
label: StringControl,
20+
hidden: BoolCodeControl,
21+
disabled: BoolCodeControl,
22+
active: BoolCodeControl,
23+
onEvent: eventHandlerControl([clickEvent]),
24+
},
25+
(props) => props
26+
)
27+
.setPropertyViewFn((children) => (
28+
<>
29+
{children.label.propertyView({ label: trans("label"), placeholder: "{{item}}" })}
30+
{children.active.propertyView({ label: trans("navItemComp.active") })}
31+
{children.hidden.propertyView({ label: trans("hidden") })}
32+
{children.disabled.propertyView({ label: trans("disabled") })}
33+
{children.onEvent.getPropertyView()}
34+
</>
35+
))
36+
.build();
37+
38+
const TmpNavItemsControl = new MultiCompBuilder(
39+
{
40+
optionType: dropdownControl(OptionTypes, "manual"),
41+
manual: navListComp(),
42+
mapData: mapOptionsControl(NavMapOption),
43+
},
44+
(props) => {
45+
return props.optionType === "manual" ? props.manual : props.mapData;
46+
}
47+
)
48+
.setPropertyViewFn(() => {
49+
throw new Error("Method not implemented.");
50+
})
51+
.build();
52+
53+
return class NavItemsControl extends TmpNavItemsControl {
54+
exposingNode() {
55+
return this.children.optionType.getView() === "manual"
56+
? (this.children.manual as any).exposingNode()
57+
: (this.children.mapData as any).exposingNode();
58+
}
59+
60+
propertyView() {
61+
const isManual = this.children.optionType.getView() === "manual";
62+
const content = isManual
63+
? menuPropertyView(this.children.manual as any)
64+
: this.children.mapData.getPropertyView();
65+
66+
return controlItem(
67+
{ searchChild: true },
68+
<>
69+
{this.children.optionType.propertyView({ radioButton: true, type: "oneline" })}
70+
{content}
71+
</>
72+
);
73+
}
74+
};
75+
}
76+
77+

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

Lines changed: 70 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
import { NameConfig, NameConfigHidden, withExposingConfigs } from "comps/generators/withExposing";
2+
import { MultiCompBuilder } from "comps/generators/multi";
23
import { UICompBuilder, withDefault } from "comps/generators";
34
import { Section, sectionNames } from "lowcoder-design";
45
import styled from "styled-components";
56
import { clickEvent, eventHandlerControl } from "comps/controls/eventHandlerControl";
6-
import { StringControl } from "comps/controls/codeControl";
7+
import { BoolCodeControl,StringControl } from "comps/controls/codeControl";
78
import { alignWithJustifyControl } from "comps/controls/alignControl";
89
import { navListComp } from "./navItemComp";
910
import { menuPropertyView } from "./components/MenuItemList";
@@ -22,6 +23,8 @@ import { trans } from "i18n";
2223

2324
import { useContext } from "react";
2425
import { EditorContext } from "comps/editorState";
26+
import { controlItem } from "lowcoder-design";
27+
import { createNavItemsControl } from "./components/NavItemsControl";
2528

2629
type IProps = {
2730
$justify: boolean;
@@ -63,11 +66,12 @@ const Item = styled.div<{
6366
$padding: string;
6467
$textTransform:string;
6568
$textDecoration:string;
69+
$disabled?: boolean;
6670
}>`
6771
height: 30px;
6872
line-height: 30px;
6973
padding: ${(props) => props.$padding ? props.$padding : '0 16px'};
70-
color: ${(props) => (props.$active ? props.$activeColor : props.$color)};
74+
color: ${(props) => props.$disabled ? `${props.$color}80` : (props.$active ? props.$activeColor : props.$color)};
7175
font-weight: ${(props) => (props.$textWeight ? props.$textWeight : 500)};
7276
font-family:${(props) => (props.$fontFamily ? props.$fontFamily : 'sans-serif')};
7377
font-style:${(props) => (props.$fontStyle ? props.$fontStyle : 'normal')};
@@ -77,8 +81,8 @@ const Item = styled.div<{
7781
margin:${(props) => props.$margin ? props.$margin : '0px'};
7882
7983
&:hover {
80-
color: ${(props) => props.$activeColor};
81-
cursor: pointer;
84+
color: ${(props) => props.$disabled ? (props.$active ? props.$activeColor : props.$color) : props.$activeColor};
85+
cursor: ${(props)=>props.$disabled ? 'not-allowed' : 'pointer'};
8286
}
8387
8488
.anticon {
@@ -131,41 +135,74 @@ function fixOldStyleData(oldData: any) {
131135
return oldData;
132136
}
133137

138+
function fixOldItemsData(oldData: any) {
139+
if (Array.isArray(oldData)) {
140+
return {
141+
optionType: "manual",
142+
manual: oldData,
143+
};
144+
}
145+
if (oldData && !oldData.optionType && Array.isArray(oldData.manual)) {
146+
return {
147+
optionType: "manual",
148+
manual: oldData.manual,
149+
};
150+
}
151+
return oldData;
152+
}
153+
134154
const childrenMap = {
135155
logoUrl: StringControl,
136156
logoEvent: withDefault(eventHandlerControl(logoEventHandlers), [{ name: "click" }]),
137157
horizontalAlignment: alignWithJustifyControl(),
138158
style: migrateOldData(styleControl(NavigationStyle, 'style'), fixOldStyleData),
139159
animationStyle: styleControl(AnimationStyle, 'animationStyle'),
140-
items: withDefault(navListComp(), [
141-
{
142-
label: trans("menuItem") + " 1",
143-
},
144-
]),
160+
items: withDefault(migrateOldData(createNavItemsControl(), fixOldItemsData), {
161+
optionType: "manual",
162+
manual: [
163+
{
164+
label: trans("menuItem") + " 1",
165+
},
166+
],
167+
}),
145168
};
146169

147170
const NavCompBase = new UICompBuilder(childrenMap, (props) => {
148171
const data = props.items;
149172
const items = (
150173
<>
151-
{data.map((menuItem, idx) => {
152-
const { hidden, label, items, active, onEvent } = menuItem.getView();
174+
{data.map((menuItem: any, idx: number) => {
175+
const isCompItem = typeof menuItem?.getView === "function";
176+
const view = isCompItem ? menuItem.getView() : menuItem;
177+
const hidden = !!view?.hidden;
153178
if (hidden) {
154179
return null;
155180
}
156-
const subMenuItems: Array<{ key: string; label: string }> = [];
181+
182+
const label = view?.label;
183+
const active = !!view?.active;
184+
const onEvent = view?.onEvent;
185+
const disabled = !!view?.disabled;
186+
const subItems = isCompItem ? view?.items : [];
187+
188+
const subMenuItems: Array<{ key: string; label: any; disabled?: boolean }> = [];
157189
const subMenuSelectedKeys: Array<string> = [];
158-
items.forEach((subItem, originalIndex) => {
159-
if (subItem.children.hidden.getView()) {
160-
return;
161-
}
162-
const key = originalIndex + "";
163-
subItem.children.active.getView() && subMenuSelectedKeys.push(key);
164-
subMenuItems.push({
165-
key: key,
166-
label: subItem.children.label.getView(),
190+
191+
if (Array.isArray(subItems)) {
192+
subItems.forEach((subItem: any, originalIndex: number) => {
193+
if (subItem.children.hidden.getView()) {
194+
return;
195+
}
196+
const key = originalIndex + "";
197+
subItem.children.active.getView() && subMenuSelectedKeys.push(key);
198+
subMenuItems.push({
199+
key: key,
200+
label: subItem.children.label.getView(),
201+
disabled: !!subItem.children.disabled.getView(),
202+
});
167203
});
168-
});
204+
}
205+
169206
const item = (
170207
<Item
171208
key={idx}
@@ -180,18 +217,23 @@ const NavCompBase = new UICompBuilder(childrenMap, (props) => {
180217
$textTransform={props.style.textTransform}
181218
$textDecoration={props.style.textDecoration}
182219
$margin={props.style.margin}
183-
onClick={() => onEvent("click")}
220+
$disabled={disabled}
221+
onClick={() => { if (!disabled && onEvent) onEvent("click"); }}
184222
>
185223
{label}
186-
{items.length > 0 && <DownOutlined />}
224+
{Array.isArray(subItems)&&subItems.length > 0 && <DownOutlined />}
187225
</Item>
188226
);
189227
if (subMenuItems.length > 0) {
190228
const subMenu = (
191229
<StyledMenu
192230
onClick={(e) => {
193-
const { onEvent: onSubEvent } = items[Number(e.key)]?.getView();
194-
onSubEvent("click");
231+
if (disabled) return;
232+
const subItem = subItems[Number(e.key)];
233+
const isSubDisabled = !!subItem?.children?.disabled?.getView?.();
234+
if (isSubDisabled) return;
235+
const onSubEvent = subItem?.getView()?.onEvent;
236+
onSubEvent && onSubEvent("click");
195237
}}
196238
selectedKeys={subMenuSelectedKeys}
197239
items={subMenuItems}
@@ -201,6 +243,7 @@ const NavCompBase = new UICompBuilder(childrenMap, (props) => {
201243
<Dropdown
202244
key={idx}
203245
popupRender={() => subMenu}
246+
disabled={disabled}
204247
>
205248
{item}
206249
</Dropdown>
@@ -237,7 +280,7 @@ const NavCompBase = new UICompBuilder(childrenMap, (props) => {
237280
return (
238281
<>
239282
<Section name={sectionNames.basic}>
240-
{menuPropertyView(children.items)}
283+
{children.items.propertyView()}
241284
</Section>
242285

243286
{(useContext(EditorContext).editorModeStatus === "logic" || useContext(EditorContext).editorModeStatus === "both") && (

‎client/packages/lowcoder/src/comps/comps/navComp/navItemComp.tsx‎

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { clickEvent, eventHandlerControl } from "comps/controls/eventHandlerCont
33
import { list } from "comps/generators/list";
44
import { parseChildrenFromValueAndChildrenMap, ToViewReturn } from "comps/generators/multi";
55
import { withDefault } from "comps/generators/simpleGenerators";
6-
import { hiddenPropertyView } from "comps/utils/propertyUtils";
6+
import { disabledPropertyView,hiddenPropertyView } from "comps/utils/propertyUtils";
77
import { trans } from "i18n";
88
import _ from "lodash";
99
import { fromRecord, MultiBaseComp, Node, RecordNode, RecordNodeToValue } from "lowcoder-core";
@@ -14,6 +14,7 @@ const events = [clickEvent];
1414
const childrenMap = {
1515
label: StringControl,
1616
hidden: BoolCodeControl,
17+
disabled: BoolCodeControl,
1718
active: BoolCodeControl,
1819
onEvent: withDefault(eventHandlerControl(events), [
1920
{
@@ -29,6 +30,7 @@ const childrenMap = {
2930
type ChildrenType = {
3031
label: InstanceType<typeof StringControl>;
3132
hidden: InstanceType<typeof BoolCodeControl>;
33+
disabled: InstanceType<typeof BoolCodeControl>;
3234
active: InstanceType<typeof BoolCodeControl>;
3335
onEvent: InstanceType<ReturnType<typeof eventHandlerControl>>;
3436
items: InstanceType<ReturnType<typeof navListComp>>;
@@ -45,6 +47,7 @@ export class NavItemComp extends MultiBaseComp<ChildrenType> {
4547
{this.children.label.propertyView({ label: trans("label") })}
4648
{hiddenPropertyView(this.children)}
4749
{this.children.active.propertyView({ label: trans("navItemComp.active") })}
50+
{disabledPropertyView(this.children)}
4851
{this.children.onEvent.propertyView({ inline: true })}
4952
</>
5053
);
@@ -69,6 +72,7 @@ export class NavItemComp extends MultiBaseComp<ChildrenType> {
6972
return fromRecord({
7073
label: this.children.label.exposingNode(),
7174
hidden: this.children.hidden.exposingNode(),
75+
disabled: this.children.disabled.exposingNode(),
7276
active: this.children.active.exposingNode(),
7377
items: this.children.items.exposingNode(),
7478
});
@@ -78,6 +82,7 @@ export class NavItemComp extends MultiBaseComp<ChildrenType> {
7882
type NavItemExposing = {
7983
label: Node<string>;
8084
hidden: Node<boolean>;
85+
disabled: Node<boolean>;
8186
active: Node<boolean>;
8287
items: Node<RecordNodeToValue<NavItemExposing>[]>;
8388
};

‎client/packages/lowcoder/src/i18n/locales/en.ts‎

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ export const en = {
2626
"text": "Text",
2727
"basic": "Basic",
2828
"label": "Label",
29+
"hidden": "Hidden",
30+
"disabled": "Disabled",
2931
"layout": "Layout",
3032
"color": "Color",
3133
"form": "Form",
@@ -3204,7 +3206,7 @@ export const en = {
32043206
"logoURL": "Navigation Logo URL",
32053207
"horizontalAlignment": "Horizontal Alignment",
32063208
"logoURLDesc": "You can display a Logo on the left side by entering URI Value or Base64 String like data:image/png;base64,AAA... CCC",
3207-
"itemsDesc": "Hierarchical Navigation Menu Items"
3209+
"itemsDesc": "Menu Items"
32083210
},
32093211
"droppadbleMenuItem": {
32103212
"subMenu": "Submenu {number}"

0 commit comments

Comments
(0)

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